修复 vipsong.py 多处错误
1. 修复 Line 277 语法错误:output_path")" 多余引号导致的 SyntaxError
2. 添加缺失的 META_KEY 常量(NCM 元数据 AES 密钥,16 字节)
3. 添加缺失的 KUGOU_KEY_PATH 常量(指向 kugou_key.xz)
4. 添加缺失的 stats 和 kgm_decoder 模块级初始化
5. 添加缺失的 import io(用于 _convert_audio 的 BytesIO)
6. 添加缺失的 _sniff_container 函数(音频容器魔术字节检测)
7. 添加缺失的 _extension_for 函数(格式到扩展名映射)
8. 添加缺失的 _convert_audio 函数(原始音频转码)
9. 修复 print("\n") 为 print()(恢复更清洁的输出格式)
This commit is contained in:
+55
-3
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
import os, sys, glob, struct, base64, json
|
||||
import os, sys, glob, struct, base64, json, io
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
from Crypto.Cipher import AES
|
||||
@@ -12,11 +12,53 @@ from pydub import AudioSegment
|
||||
|
||||
NCM_MAGIC = b"CTENFDAM"
|
||||
CORE_KEY = b"hzHRAmso5kInbaxW"
|
||||
META_KEY = bytes.fromhex("2331346C6A6B5F215C5D2630553C2728")
|
||||
META_PREFIX = b"163 key(D't modify):"
|
||||
KUGOU_KEY_PATH = Path(__file__).parent / "kugou_key.xz"
|
||||
|
||||
_FORMAT_MAP = {
|
||||
"mp3": "mp3",
|
||||
"flac": "flac",
|
||||
"wav": "wav",
|
||||
"ogg": "ogg",
|
||||
"m4a": "mp4",
|
||||
"mp4": "mp4",
|
||||
}
|
||||
|
||||
stats = {"success": 0, "failed": 0, "files": []}
|
||||
kgm_decoder = None
|
||||
|
||||
def _u32le(data, pos):
|
||||
return struct.unpack(b"<I", data[pos:pos+4])[0]
|
||||
|
||||
def _sniff_container(header):
|
||||
"""从魔术字节检测音频容器类型。"""
|
||||
if len(header) >= 3 and header[:3] == b"ID3":
|
||||
return "mp3"
|
||||
if len(header) >= 2 and header[0] == 0xFF and (header[1] & 0xE0) == 0xE0:
|
||||
return "mp3"
|
||||
if len(header) >= 4 and header[:4] == b"fLaC":
|
||||
return "flac"
|
||||
if len(header) >= 4 and header[:4] == b"OggS":
|
||||
return "ogg"
|
||||
if len(header) >= 12 and header[:4] == b"RIFF" and header[8:12] == b"WAVE":
|
||||
return "wav"
|
||||
if len(header) >= 12 and header[4:8] == b"ftyp":
|
||||
return "mp4"
|
||||
return None
|
||||
|
||||
def _extension_for(fmt):
|
||||
"""将格式名称映射为文件后缀。"""
|
||||
mapping = {
|
||||
"mp3": "mp3",
|
||||
"flac": "flac",
|
||||
"wav": "wav",
|
||||
"ogg": "ogg",
|
||||
"m4a": "m4a",
|
||||
"mp4": "m4a",
|
||||
}
|
||||
return mapping.get(fmt, "mp3")
|
||||
|
||||
def ncm_stream_bytes(key):
|
||||
sbox = bytearray(range(256))
|
||||
j = 0
|
||||
@@ -210,6 +252,16 @@ def _add_tags(output_path, tags, cover=None):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _convert_audio(raw, container, out_fmt, output_path):
|
||||
"""将解密后的原始音频转码为目标格式。"""
|
||||
src_fmt = _FORMAT_MAP.get(container, container)
|
||||
dst_fmt = _FORMAT_MAP.get(out_fmt, out_fmt)
|
||||
if src_fmt == dst_fmt:
|
||||
Path(output_path).write_bytes(raw)
|
||||
else:
|
||||
audio = AudioSegment.from_file(io.BytesIO(raw), format=src_fmt)
|
||||
audio.export(output_path, format=dst_fmt)
|
||||
|
||||
def convert_file(file_path, output_fmt, delete_flag):
|
||||
global stats, kgm_decoder
|
||||
file_path = str(Path(file_path).resolve())
|
||||
@@ -339,11 +391,11 @@ def main():
|
||||
convert_file(f, output_fmt, delete_flag)
|
||||
print_stats()
|
||||
return
|
||||
print("=* 50")
|
||||
print("=" * 50)
|
||||
print(" vipsong - Music Format Converter")
|
||||
print(" Support: .ncm (NetEase) .kgm/.vpr (KuGou)")
|
||||
print(" Output: mp3 / flac / wav / ogg / m4a")
|
||||
print("=* 50")
|
||||
print("=" * 50)
|
||||
print("Commands:")
|
||||
print(" <filepath> Convert file or glob pattern (e.g. *.ncm)")
|
||||
print(" -f <format> Output format (default: mp3)")
|
||||
|
||||
Reference in New Issue
Block a user