修复 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:
ypshidifu
2026-09-17 13:22:49 +08:00
parent 430e7156b8
commit 3af7501b47
+55 -3
View File
@@ -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)")