项目整理:重写主文档、归档过时文档、清理死代码、新增音频制作手册
文档整理: - 重写 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:
@@ -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()
|
||||
Reference in New Issue
Block a user