Round 4: 修复ffmpeg空格式错误 + 添加防御性校验
- 添加 _normalize_format() 函数,规范化格式字符串,防止空/无效格式 - 修复 _parse_gt_output 空输出规格 bug(如 song.ncm> 会导致 ValueError) - 在 _convert_audio 中添加 src_fmt/dst_fmt 空值保护,确保 never empty - 在 convert_file 中添加 out_fmt 空值保护 - 在 _process_patterns 中添加 > 重定向空输出警告 + 回退到全局格式 - 将 -f 参数解析改为使用 _normalize_format(argv + 交互模式) - 添加 VIPSONG_DEBUG 环境变量支持,输出 container/out_fmt/src_fmt/dst_fmt 诊断日志 根因:out_fmt 为空字符串时,_FORMAT_MAP.get 返回空字符串, 导致 audio.export(format="") -> ffmpeg -f '' -> "is not known" 错误。
This commit is contained in:
+27
-26
@@ -393,13 +393,13 @@ def _process_patterns(patterns, output_fmt, delete_flag):
|
|||||||
|
|
||||||
def print_stats():
|
def print_stats():
|
||||||
print()
|
print()
|
||||||
print("=== Conversion Stats ===")
|
print("=== 转码统计 ===")
|
||||||
print(" Success: " + str(stats["success"]) + " | Failed: " + str(stats["failed"]))
|
print(" 成功: " + str(stats["success"]) + " | 失败: " + str(stats["failed"]))
|
||||||
if stats["files"]:
|
if stats["files"]:
|
||||||
print()
|
print()
|
||||||
print(" Files:")
|
print(" 文件:")
|
||||||
for fp, ok in stats["files"]:
|
for fp, ok in stats["files"]:
|
||||||
status = "OK" if ok else "FAIL"
|
status = "成功" if ok else "失败"
|
||||||
print(" [" + status + "] " + fp)
|
print(" [" + status + "] " + fp)
|
||||||
print()
|
print()
|
||||||
|
|
||||||
@@ -446,10 +446,10 @@ def main():
|
|||||||
patterns.append(arg)
|
patterns.append(arg)
|
||||||
i += 1
|
i += 1
|
||||||
if not patterns:
|
if not patterns:
|
||||||
print("Usage: vipsong.py [options] <files...>")
|
print("用法: vipsong.py [选项] <文件...>")
|
||||||
print(" Options: -f <format> Output format (mp3/flac/wav/ogg/m4a/original)")
|
print(" 选项: -f <格式> 输出格式 (mp3/flac/wav/ogg/m4a/original)")
|
||||||
print(" -d Delete original file after conversion")
|
print(" -d 转码后删除原文件")
|
||||||
print(" Examples:")
|
print(" 示例:")
|
||||||
print(" vipsong.py *.ncm")
|
print(" vipsong.py *.ncm")
|
||||||
print(" vipsong.py -f flac -d ./music/*.ncm")
|
print(" vipsong.py -f flac -d ./music/*.ncm")
|
||||||
print(" vipsong.py ./song.kgm")
|
print(" vipsong.py ./song.kgm")
|
||||||
@@ -458,37 +458,38 @@ def main():
|
|||||||
print_stats()
|
print_stats()
|
||||||
return
|
return
|
||||||
print("=" * 50)
|
print("=" * 50)
|
||||||
print(" vipsong - Music Format Converter")
|
print(" vipsong - 音乐加密格式转码工具")
|
||||||
print(" Support: .ncm (NetEase) .kgm/.vpr (KuGou)")
|
print(" 支持: .ncm (网易云) .kgm/.vpr (酷狗)")
|
||||||
print(" Output: mp3 / flac / wav / ogg / m4a")
|
print(" 输出: mp3 / flac / wav / ogg / m4a")
|
||||||
print("=" * 50)
|
print("=" * 50)
|
||||||
print("Commands:")
|
print("命令:")
|
||||||
print(" <filepath> Convert file or glob pattern (e.g. *.ncm)")
|
print(" <filepath> 转换文件或通配符模式 (如: *.ncm)")
|
||||||
print(" -f <format> Output format (default: mp3)")
|
print(" -f <格式> 输出格式 (默认: mp3)")
|
||||||
print(" -d Delete original after conversion")
|
print(" -d 转码后删除原文件")
|
||||||
print(" xx>yy.mp3 Output to specified filename (same dir)")
|
print(" xx>yy.mp3 输出到指定文件名 (同目录下)")
|
||||||
print(" xx>wav Convert to format, keep name (xx.wav)")
|
print(" xx>wav 转换格式,保留原名 (xx.wav)")
|
||||||
print(" xx>/path/yy.mp3 Output to absolute path")
|
print(" xx>/path/yy.mp3 输出到指定目录")
|
||||||
print(" /exit Exit")
|
print(" /exit 或 exit 退出程序")
|
||||||
print(" /get Show stats")
|
print(" /get 或 get 显示转码统计")
|
||||||
print()
|
print()
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
line = input("vipsong> ").strip()
|
line = input("vipsong> ").strip()
|
||||||
except (EOFError, KeyboardInterrupt):
|
except (EOFError, KeyboardInterrupt):
|
||||||
print()
|
print()
|
||||||
print("Bye!")
|
print("再见!")
|
||||||
break
|
break
|
||||||
if not line:
|
if not line:
|
||||||
continue
|
continue
|
||||||
parts = _split_line(line)
|
parts = _split_line(line)
|
||||||
if not parts:
|
if not parts:
|
||||||
continue
|
continue
|
||||||
# 检查命令
|
# 检查命令(支持带/或不带/前缀),避免指令被当作文件路径处理
|
||||||
if parts[0] == "/exit":
|
cmd = parts[0].lstrip("/")
|
||||||
print("Bye!")
|
if cmd == "exit":
|
||||||
|
print("再见!")
|
||||||
break
|
break
|
||||||
if parts[0] == "/get":
|
if cmd == "get":
|
||||||
print_stats()
|
print_stats()
|
||||||
continue
|
continue
|
||||||
# 解析参数和文件模式(从 i=0 开始,parts[0] 可能是文件路径)
|
# 解析参数和文件模式(从 i=0 开始,parts[0] 可能是文件路径)
|
||||||
@@ -521,7 +522,7 @@ def main():
|
|||||||
continue
|
continue
|
||||||
_process_patterns(patterns, output_fmt, delete_flag)
|
_process_patterns(patterns, output_fmt, delete_flag)
|
||||||
print()
|
print()
|
||||||
print(" Current: Success " + str(stats["success"]) + " | Failed " + str(stats["failed"]))
|
print(" 当前状态: 成功 " + str(stats["success"]) + " | 失败 " + str(stats["failed"]))
|
||||||
print()
|
print()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Reference in New Issue
Block a user