#!/usr/bin/env python3 """ 为各游戏脚本注入 narrateAudio 字段 用法: python audio/inject_narrateAudio.py --game shouye --dry-run python audio/inject_narrateAudio.py --game shouye 说明: 扫描 audio/mp3/narrator/{game_id}/ 目录下已生成的 MP3, 打印出对应游戏脚本中应添加的 narrateAudio 字段。 由于游戏脚本结构各异,本脚本只做"报告",不直接修改 JS 文件。 输出示例(复制粘贴到对应 scene 对象中): s01: { narrateAudio: '../audio/mp3/narrator/shouye/shouye_s01_narrate.mp3', narrate: '...', // 保留原文作 TTS 兜底 ... } """ import os import argparse import glob PROJECT_DIR = "/home/xsl/blind" NARRATOR_DIR = os.path.join(PROJECT_DIR, "audio", "mp3", "narrator") # 相对于 game/js/games/{game}.js 的音频路径 AUDIO_REL = "../../audio/mp3/narrator" def main(): parser = argparse.ArgumentParser() parser.add_argument("--game", required=True, help="游戏 ID (linxia/yinian/shouye/houzhen/yisheng/fu)") parser.add_argument("--dry-run", action="store_true", help="只列出可用文件,不输出注入建议") args = parser.parse_args() game_dir = os.path.join(NARRATOR_DIR, args.game) if not os.path.isdir(game_dir): print(f"[错误] 目录不存在: {game_dir}") print(f"请先运行 batch_narrator_tts.py 生成音频。") return files = sorted(glob.glob(os.path.join(game_dir, "*.mp3"))) if not files: print(f"[空] {game_dir}/ 中没有 MP3 文件。") return print(f"\n已生成的 {args.game} 旁白音频 ({len(files)} 条):\n") if args.dry_run: for f in files: print(f" {os.path.basename(f)}") return print("// ── 将以下 narrateAudio 字段添加到对应 scene/action 对象中 ──") print("// (保留 narrate 文字作 TTS 兜底;有了 narrateAudio 后引擎会优先播放文件)\n") for f in files: name = os.path.basename(f) # e.g. shouye_s01_narrate.mp3 stem = name[:-4] # e.g. shouye_s01_narrate # 推断 scene/action key parts = stem.split("_") # ['shouye', 's01', 'narrate'] rel_path = f"{AUDIO_REL}/{args.game}/{name}" # 判断类型 if parts[-1] == "narrate" or parts[-1].startswith("narrate"): field = "narrateAudio" note = f"// → scene {parts[1]}" elif parts[-1] == "tap" or parts[-1].startswith("tap"): field = "narrateAudio" note = f"// → scene {parts[1]} / tap" elif parts[-1] == "dt": field = "narrateAudio" note = f"// → scene {parts[1]} / doubleTap" elif parts[-1] == "intro": field = "// game.introAudio" note = "// → game 对象 intro 字段(engine.run 中用 narrateAudio 处理)" elif "ending" in parts: ending_id = "_".join(parts[parts.index("ending"):]) field = "narrateAudio" note = f"// → endings.{ending_id.replace('ending_', '')} 对象" else: field = "narrateAudio" note = "" print(f" {field}: '{rel_path}', {note}") print("\n// 提示:intro 的 narrateAudio 需在 engine.run() 里单独处理,") print("// 或在 game 对象中加 introAudio 字段并在 engine 中检查。") if __name__ == "__main__": main()