项目整理:重写主文档、归档过时文档、清理死代码、新增音频制作手册

文档整理:
- 重写 game/操作说明.md 为项目主文档(6游戏/6手势/旁白/模型生成音频/TTS两步流程)
- 归档过时文档至 other_docs/(林夏原始设计、旧执行文档)
- 新增 docs/音频制作执行手册.md(从零制作游戏音频的完整流程)
- docs/ 下保留旁白音色提示词、音频脚本

代码清理:
- 删除旧架构死代码: story.js / gestures.js / profile.js
- 删除耦合旧架构的过时测试目录 game/tests/

脚本配置修正:
- check_tts_env.sh: 启动脚本路径 AutoVideo → tts-server(实际位置)
- gen_narrator_samples.py: 硬编码地址改为环境变量,默认对齐 tts-server 端口 8000
This commit is contained in:
xsl
2026-06-19 22:29:04 +08:00
parent b3384499e3
commit 866f363591
46 changed files with 5061 additions and 2374 deletions
+95
View File
@@ -0,0 +1,95 @@
#!/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()