HTML5 重写:6 款游戏 + 用户系统 + 全局设置 + 5 轮迭代重构

- 新增 web/ 纯音频 HTML5 平台:共享引擎(手势/WebAudio 三层/设置/震动)、
  Node 零依赖服务器(静态 + 注册登录 + 进度存档 API)
- 游戏:剑与声(RPG 新作)、声命线、暗室(重设计)、音序回响(重设计)、
  节拍行者(跟随领奏重构)、盲航(同向闪避重构);声东击西删除
- 全局功能:男声/女声双套 TTS 资产、三档语速、BGM 音量三档、
  震动反馈语言(10 种震型)、服务器进度同步
- 资产:899 ogg + 899 m4a(Qwen3-TTS 双性别语音、Stable Audio 3 音效、
  Mureka BGM 4+3 首),终检零缺失
- 文档:docs/design/ 13 篇设计审查文档、docs/audio/ 资产管线、
  web/server/README.md API 文档
This commit is contained in:
SoundGame Dev
2026-08-29 21:55:44 +08:00
parent f0f0a9b50e
commit cc0f8c008d
1885 changed files with 11246 additions and 5 deletions
+113
View File
@@ -0,0 +1,113 @@
# 音频资产清单(R1,2026-08-29)
本文档是 5 个 web 游戏的 voice / sfx / bgm 资产总账,以及双性别语音的音色分配。
## 目录约定(R1 新增)
- 双性别旁白:`web/<game>/audio/voice/male/<id>.{ogg,m4a}` 和 `web/<game>/audio/voice/female/<id>.{ogg,m4a}`,两个目录内 id 集合完全一致。
- 原有平铺文件 `web/<game>/audio/voice/<id>.{ogg,m4a}` **暂时保留**,等引擎切换读取 male/female 子目录后由后续轮次清理。
- 所有 web 音频均为双格式:`.ogg`(libvorbis q3,44.1kHz)+ `.m4a`(aac 128k,44.1kHz,iOS 用)。
- 生成管线:`tools/gen_voice_dual.py`(台词表内嵌,从各游戏原 gen 脚本只读提取),staging wav 在 `tools/gen_voice_dual_wav/<game>/<gender>/`。
## 音色分配表(游戏 × 性别 → speaker)
| 游戏 | male | female | 备注 |
|---|---|---|---|
| storyline | Uncle_Fu | Vivian | 仅旁白+系统音双性别;角色音色不动(见下) |
| escape | Uncle_Fu | Serena | male 沿用原旁白音色 |
| simon | Uncle_Fu | Serena | female 沿用原主持人音色 |
| rhythm | Uncle_Fu | Vivian | female 沿用原解说音色 |
| space | Uncle_Fu | Serena | female 沿用原导航音色 |
| rpg | Uncle_Fu | Serena | 旁白;NPC 单音色平铺(见 rpg 章节) |
关于 Ryan:冒烟测试样本在 `tools/samples/ryan_zh_*.wav`(3 条中文句)。Ryan 是英语母语音色(见 `env.d/tts.md`),项目已有中文发音投诉(反馈⑥),男声统一采用中文母语的 Uncle_Fu;如需换成 Ryan,改 `tools/gen_voice_dual.py` 的 `SPEAKERS` 表重跑即可。
## instruct 模板(每性别全游戏内一致)
同一游戏的同一类台词,male/female 使用同一 instruct 模板(仅性别描述词不同),数字/短句(≤2 字)一整批同 instruct 连续生成:
- storyline 旁白:male「低沉醇厚的中年男声旁白,冷静、缓慢,带着末世废墟的苍凉感」/ female「冷静低沉的女声旁白,语速缓慢,带着末世废墟的苍凉感」(另有 WARM/COLD/EPIC 三个结局变体,见脚本)
- escape(R2 起,全游戏同一常量):male「低沉平稳的男声,冷静、克制,带一点神秘感」/ female「沉稳平静的女声,冷静、克制,带一点神秘感」
- simon(R2 起,全游戏同一常量,两性别同文):「平静、清晰,像一个耐心的游戏主持人」
- rhythm(R3 起,全表统一):female(Vivian)「活力清晰的年轻女声,像节奏游戏主持人,情绪饱满但不夸张」/ male(Uncle_Fu)「低沉醇厚的男声,像节奏游戏主持人,平稳有力」
- space(R3 起,全表统一):female(Serena)「平静清晰的女声,像飞船领航员,沉稳可信」/ male(Uncle_Fu)「低沉醇厚的男声,像飞船领航员,沉稳有力」
- rpg(R4 起,旁白全表统一):female(Serena)「平静清晰的年轻女声,像在讲武侠故事」/ male(Uncle_Fu)「低沉醇厚的男声,像说书人,平静有韵味」;NPC 各角色 speaker+instruct 恒定(村长 Uncle_Fu·慈祥和缓的老者/老猎人 Eric·沙哑粗犷豪爽中带着暖意/头目 Dylan·凶狠粗鲁大声喝骂/寨主 Uncle_Fu·低沉阴狠慢条斯理)
## 各游戏资产清单
### storyline《声命线》
- voice 双性别版(male/ 与 female/ 各 36 条):旁白 + 系统音 = `help menu status1 status2 status3 p1–p8 n00_intro n01_wake n04_exit n05_signal n06_whistle n08_vent n09_dead n10_rain n11_child n13_leave n14_ignore n15_bridge n16_culvert n16b_culvert_c n17_cable n17b_cable_c n20_convoy n22_fight n23_tower e1_dawn e2_price e3_alone e4_static`
- voice 角色台词(**不做双性别**,沿用平铺原文件):
| 角色 | speaker | 文件 id |
|---|---|---|
| 林晚(主角) | Serena | n02_linwan n03_radio n12_take n19_betray n21_redeem n24_open n25_secure |
| 猎狗(反派) | Dylan | n07_dog n18_dog |
| 小满(小男孩) | Vivian(稚嫩童声 instruct) | e1_child |
| 林晨(妹妹,收音机录音) | Vivian(收音机 instruct) | n03_msg |
| 广播女声 | Vivian(机械广播 instruct) | n05_bcast |
约定:角色台词在两个性别目录下使用**同一份文件**(由开发复制/链接或引擎回退到平铺目录,见 round1-report)。
- sfx(12):`footsteps gunshot heartbeat radio_static rubble signal_beep struggle ui_confirm ui_menu water whistle wind`
- bgm(1):`dark_drone`
### escape《暗室》(R2 重设计版,最终清单见 `round2-voice-ids.md`)
- voice 双性别版(male/ 与 female/ 各 74 条):引导 `g0_intro g1_move g1_done g2_wall g3_left g4_down g5_inspect g5_key g6_doubletap g6_done g7_goal`、引导纠错 `guide_wrong_* guide_blunt_* guide_offpath guide_skip reopen_prompt`、三级提示 `stuck_ask stuck_{key,cabinet,box,gate}_{1,2,3}`、导航 `nav_{up,down,left,right}`、房间 `room_{storage,cabinet,power,gate}`、用时 `time_band1–4`、保留句 `wall start_room found_key inspect_* unlock_cabinet box_fixed fix_box escape use_fail inv_* replay again empty_1–3`、菜单 `help_ops menu_*`
- voice 已删除(R2):`n0–n9 nshi unit_min unit_sec time_prefix intro tutorial hint_key hint_cabinet hint_box hint_gate`(整句化替代);平铺 `voice/` 旧文件全部移除
- sfx(16):`amb_drip amb_hum amb_wind`(保留)+ R2 新增 `amb_storage amb_cabinet amb_power amb_gate amb_gate_live`(Stable Audio 3,6s,统一 -25dB 均值,storage/power 偏左、cabinet 偏右 pan)+ `door_creak gate_open pickup power_on spark step unlock wall win_chime`;已删除 `ui_deny`(反馈改震动)
- bgm(1):`drone`
### simon《音序回响》(R2 重设计版,最终清单见 `round2-voice-ids.md`)
- voice 双性别版(male/ 与 female/ 各 68 条):交互教学 `t0_welcome t0_goal t1_up–t6_double t_try t_ok t_wrong_* t_blunt_* t7_ready t7_retry t_skip`、轮次 `round_01–round_20 round_more`(整句)、成绩 `score_band1–6`(整句)、流程 `your_turn chances_out retry_use relisten replay rules_prompt rules gameover`、反馈 `correct wrong chance_plus new_record`、菜单 `menu_*`
- voice 已删除(R2):`di lun num_shi num_0–num_9 score_pre best_pre`(拼接件)+ `intro teach_* listen`(旧连播教学);平铺 `voice/` 旧文件全部移除
- sfx(7):`gameover tone_doubletap tone_down tone_left tone_right tone_tap tone_up`;已删除 `correct wrong newrecord`(反馈改震动)
- bgm:**已于 R1 按用户要求移除**(原 `theme`,代码引用由开发删除)
### rhythm《节拍行者》(R3 重构版,台词依据 `docs/design/03-rhythm-voice-ids.md`)
- voice 双性别版(male/ 与 female/ 各 31 条):开场流程 `welcome welcome_back tut_1 tut_2 tut_3 tut_done tut_skip mid_song`、教学纠正 `retry_early retry_late retry_gesture retry_listen retry_skip`、选曲解锁 `select_hint song1_name song2_name song3_name song_locked unlock_song2 unlock_song3`、结算 `grade_s grade_a grade_b grade_c new_best_combo restart`、菜单规则 `rules settings_hint menu_main menu_resume menu_lobby`
- voice 已删除(R3):`tut_start`(平铺旧 id 全部移除,其余旧 id 均在 R2 已替换)
- voice 修订(R5):`menu_main` 改词重录为「菜单。单击切换选项,双击确认。」(对齐 round2-review 裁决②全球菜单约定;选曲界面非模态菜单不受影响)
- sfx(7,R3 补齐):`inst_kick inst_snare inst_hat_l inst_hat_r inst_tom_hi inst_tom_lo inst_accent`(演奏乐器音,详见 round3-report §7;hat_l 闭合镲极左 / hat_r 开放镲极右,accent 为 A minor 合成亮音);已删除 `judge_* tick tick_accent`(R3)与 `cue_*`(R3 收尾,重构不再使用指令音)
- bgm(3,R3 重制):`track90`(90.01 BPM,85.33s)`track105`(104.99 BPM,73.14s)`track120`(120.00 BPM,72.00s),A minor 电子乐,整数小节无缝循环,loudnorm -20 LUFS;旧 `groove` 已删除
### space《盲航》(R3 备产,台词依据 `docs/design/04-space-voice-ids.md`)
- voice 双性别版(male/ 与 female/ 各 52 条):演练 `drill_*`(14)、保护期 `protect_*`(5)、功能引入 `feat_* shield_ready shield_block`(6)、被撞归因 `hit_*`(5)、里程碑 `ms_10 ms_25 ms_50 ms_100`、结算 `time_1–4 dodge_1–4 new_record restart_hint`、菜单系统 `second_run_ask menu_* help_recap settings_hint paused`
- voice 修订(R4):`menu_main` 改词重录为「菜单。单击切换选项,双击确认。」(对齐 round2-review 裁决②全球菜单约定)
- voice 已删除(R3):`num0–9 num_shi num_bai n_time n_sec n_dodge n_ge n_milestone intro1–4 hit1 hit2 gameover restart`(数字拼接与旧教学弃用);平铺旧文件全部移除
- sfx(12):`alarm boost crash dodge hit shield shield_block whoosh_down whoosh_left whoosh_right whoosh_up`
- bgm(1):`engine`
### rpg《剑与声》(R4 新游戏第一章,台词依据 `docs/design/05-rpg-ch1-voice-ids.md` + `05-rpg-addendum.md`)
- voice 旁白双性别版(male/ 与 female/ 各 108 条,male=Uncle_Fu 说书人 / female=Serena 武侠故事):序章 `intro_1–3`、系统状态 `sys_* help_* settings_hint st_*`、场景 `desc_*`(16)、选项 `opt_*`(18)、事件 `evt_*`(6)、战斗 `btl_* cmd_* tut_*`(27,含 R5 补录 `btl_half_bandit`)、商店 `shop_*`(7)、敌方档位 `foe_hp_high/mid/low`(addendum §6.2 补录)
- voice NPC 单音色平铺(14 条,落 `voice/` 根,引擎平铺回退):村长 `npc_headman_1–4`(Uncle_Fu·慈祥和缓)、老猎人 `npc_hunter_1–4`(Eric·沙哑豪爽)、寨丁头目 `npc_elite_1/half/die`(Dylan·凶狠)、黑风寨主 `npc_boss1_1/2/die`(Uncle_Fu·低沉阴狠,与村长同 speaker 不同 instruct)
- sfx(35):前摇 `tel_wolf tel_bandit tel_spider tel_elite tel_boss1 tel_croc tel_shaman tel_puppet tel_boss2`(1.0s 格挡窗口);战斗 `atk_swing atk_hit parry skill_slash enemy_die potion` + SYN `hurt flee`;探索 `chest drink_water rest door_heavy` + SYN `step coin levelup`;环境 `amb_village amb_path amb_fork amb_chest amb_stream amb_hunter amb_deepwood amb_gate amb_hall amb_swamp amb_peak`(5s 无缝循环,均值 -25dB);`ui_deny` 按设计不做
- bgm(4,Mureka):`village battle boss ending`(90s 无缝循环,loudnorm -20);探索期无音乐(addendum §3),`amb_*` 由游戏层手动 loop 接 sfx 总线
- 再生成方法见 `web/rpg/gen/README.md`
## 发音质量
### 本轮已采取的规避措施
- 数字类语音(num_0~9、shi、bai、第、轮、分、秒、颗等)一整批同 instruct 连续生成,减少拼接 prosody 漂移(反馈⑥根因之一)。
- 台词 >40 字按句拆分生成再拼接(句间 0.12s 静音),避免长句吞字。
- 每条 assert 时长 >0.3s、峰值 >0.05,统一峰值归一 0.89;同句两性时长比 >3 判离群并重生成。
### 多音字/发音风险清单(待人工试听确认)
以下条目为文本层面的已知风险点,本轮生成保留原文;如试听发现误读,建议按右栏换写法重生成(改 `tools/gen_voice_dual.py` 台词表):
| 位置 | 原文 | 风险 | 建议换写法 |
|---|---|---|---|
| storyline help | 双击:重听刚才的台词 | 「重」可能读 zhòng | 「双击:重新听刚才的台词」 |
| storyline n11_child / n13_leave / n16b | 数到一千、数数 | 「数」shǔ/shù | 误读时写「数一数,数到一千」 |
| storyline n05_bcast / n19_betray | 三、七点、五 | 坐标需逐字读 | 误读时写「三,七,点,五」 |
| storyline n16b | 数到一百七 | 可能读成「一百七十个」 | 写「数到一百七十」 |
| 多处(escape/simon/space/storyline) | 还(hái)在/还有/还能 | 「还」hái/huán | 误读时改写句子避开 |
| rhythm welcome | S / A / B / C 评级 | 字母发音 | 现行文本为「评级,S!」,试听确认字母读音 |
(本表为文本审查结果;时长离群自动检查已通过的部分见 round1-report,最终发音准确性需人工试听把关。)
+20
View File
@@ -0,0 +1,20 @@
# 全项目音频资产终检(R5,2026-08-29)
| 游戏 | ogg | m4a | 0字节 | 解码失败 | voice male/female id 一致 |
|---|---|---|---|---|---|
| storyline | 133 | 133 | 0 | 0 | ✅ 各 36(平铺 48 个角色/NPC 句,豁免) |
| escape | 166 | 166 | 0 | 0 | ✅ 各 74 |
| simon | 143 | 143 | 0 | 0 | ✅ 各 68 |
| rhythm | 72 | 72 | 0 | 0 | ✅ 各 31 |
| space | 116 | 116 | 0 | 0 | ✅ 各 52 |
| rpg | 269 | 269 | 0 | 0 | ✅ 各 108(平铺 14 个角色/NPC 句,豁免) |
## 结论
全部通过:双格式配对完整、无 0 字节、全部可解码、voice 性别目录 id 集合一致(storyline/rpg 平铺角色句按约定豁免)。
## 附注
- storyline 平铺 48 个 = 12 个角色台词(林晚/猎狗/小满/林晨/广播,单音色永久保留)+ 36 个 R1 旁白旧文件(与 male/ 内容重复的遗产,待引擎切换验证后清理,见 round1-report §2)。
- rpg 平铺 14 个 = NPC 句(设计如此,单音色)。
- 终检脚本:`tools/check_all_assets.py`(可重复执行)。
+72
View File
@@ -0,0 +1,72 @@
# R1 音频轮次报告(2026-08-29,音乐音效总监)
本轮主题:双性别旁白资产管线 + simon BGM 移除。Mureka 花费 $0(无新 BGM,预算余额 $1.85)。
## 1. 新目录约定(给开发)
- 旁白/系统音按性别分目录:`web/<game>/audio/voice/male/<id>.{ogg,m4a}` 与 `web/<game>/audio/voice/female/<id>.{ogg,m4a}`。
- 两个目录的 **id 集合完全一致**(每游戏核对过),引擎按用户选择整目录切换即可,无需按 id 特判。
- 双格式:每个 id 都有 `.ogg`(libvorbis q3 44.1k)和 `.m4a`(aac 128k 44.1k),沿用现有格式协商逻辑。
- **平铺的旧文件 `voice/<id>.*` 本轮保留未动**。引擎切到 male/female 子目录后,后续轮次再删除平铺文件(storyline 角色台词除外,见 §3)。
- staging wav 保留在 `tools/gen_voice_dual_wav/<game>/<gender>/`,供后续轮次增量重生成(管线支持断点续跑,已有且合格的 wav 会跳过)。
## 2. 生成统计
| 游戏 | ids/性别 | male 总时长 | female 总时长 |
|---|---|---|---|
| storyline | 36 | 806.6s | 960.6s |
| escape | 41 | 230.8s | 212.4s |
| simon | 30 | 63.4s | 62.9s |
| rhythm | 9 | 71.5s | 59.0s |
| space | 27 | 78.2s | 65.1s |
| **合计** | **143 × 2 = 286 条** | 1250.5s | 1360.0s |
落盘文件 286 × 2 格式 = 572 个。质量控制:全部通过 时长>0.3s / 峰值>0.05 / 峰值归一 0.89;数字类同 instruct 整批生成;>40 字台词拆句拼接。两性时长离群(>3 倍)初检 3 条,已全部重生成并复检通过:
- `simon/male/num_4`(8.00s → 0.48s)
- `simon/female/teach_end`(29.04s → 14.80s)
- `space/male/n_ge`(2.16s → 1.12s)
## 3. storyline 角色音色映射(角色台词不做双性别)
| 角色 | speaker | 文件 id(沿用平铺原文件) |
|---|---|---|
| 旁白/系统音 | male=Uncle_Fu / female=Vivian | 36 个双性别 id(见 asset-manifest.md) |
| 林晚(主角) | Serena | n02_linwan n03_radio n12_take n19_betray n21_redeem n24_open n25_secure |
| 猎狗(反派) | Dylan | n07_dog n18_dog |
| 小满(小男孩) | Vivian(童声 instruct) | e1_child |
| 林晨(妹妹录音) | Vivian(收音机 instruct) | n03_msg |
| 广播女声 | Vivian(广播 instruct) | n05_bcast |
**需要开发配合**:角色台词在两个性别下使用同一份音频。建议引擎对 storyline 做回退:在 `voice/<gender>/` 找不到的 id 回退读平铺 `voice/<id>`;或由开发/后续轮次把 12 个角色 id 复制进两个子目录(资产侧未复制,避免重复文件进入仓库前等引擎方案定稿)。
注意:female 旁白选用 Vivian 而非 Serena,因为 Serena 是主角林晚的音色,旁白与主角同声会混淆;代价是旁白与小满/林晨/广播同 speaker,已用截然不同的 instruct(冷静低沉 vs 童声/收音机/机械广播)区分,请策划试听确认。
## 4. 音色分配表
| 游戏 | male | female |
|---|---|---|
| storyline | Uncle_Fu(沿用原旁白) | Vivian |
| escape | Uncle_Fu(沿用) | Serena |
| simon | Uncle_Fu | Serena(沿用) |
| rhythm | Uncle_Fu | Vivian(沿用) |
| space | Uncle_Fu | Serena(沿用) |
Ryan(英语母语音色)未采用:项目已有中文发音投诉(反馈⑥),男声统一中文母语 Uncle_Fu。冒烟样本在 `tools/samples/ryan_zh_*.wav`,如策划试听认为可用,改 `tools/gen_voice_dual.py` 的 `SPEAKERS` 重跑即可。
## 5. 需要游戏代码配合的点
1. **引擎支持 voice 性别目录切换**:按用户设置在 `audio/voice/male|female/` 之间切换;storyline 需平铺回退(§3)。
2. **simon 删除 BGM 引用**:资产 `web/simon/audio/bgm/theme.{ogg,m4a}` 已按用户要求删除(bgm/ 目录现为空),请移除 game.js 中的 bgm 加载/播放逻辑及 preload 清单条目。
3. **语音选择 UI 入口**:需要「男声/女声」设置项(全局或每游戏),默认建议 male=storyline/escape、female=simon/rhythm/space(即各游戏原音色性别),具体由策划定。
4. 平铺旧 voice 文件待引擎切换完成后通知音频侧清理(R2+)。
## 6. 质量遗留问题
- 本轮 QC 为自动检查(时长/峰值/两性离群),**未做人工试听**;发音准确性需策划/QA 试听把关。文本层多音字风险清单在 `docs/audio/asset-manifest.md`(如 storyline help 的「重听」建议改「重新听」),确认误读后改台词表重跑单条即可。
- `simon/female/teach_end` 重生成后 14.8s(male 7.8s),比值正常但偏长,建议试听确认无重复啰嗦。
- 管线脚本:`tools/gen_voice_dual.py`(含全部台词表,支持 `--game/--gender/--only/--check/--convert`)。
## 7. Mureka 花费
本轮 $0(无新 BGM 需求;simon BGM 为删除而非重制)。累计 $0.15 / $2.00,未动 `tools/mureka_log.md`(无新条目)。
+59
View File
@@ -0,0 +1,59 @@
# R2 音频轮次报告(2026-08-29,音乐音效总监)
本轮主题:《暗室》《音序回响》重设计语音资产 + escape 环境音扩展。依据 `docs/design/01-escape-redesign.md`、`02-simon-redesign.md` 与 `00-global-ux.md`。Mureka 花费 $0。
## 1. 首要交付物
`docs/audio/round2-voice-ids.md` —— 两款游戏全部语音 id → 台词全文 → instruct 对照表,含新增/保留/删除标记和代码映射区间(time_band/score_band)。开发照此实现即可。
## 2. 新资产统计
| 游戏 | 性别 | id 数 | 总时长 | 文件数(ogg+m4a) |
|---|---|---|---|---|
| escape | male | 74 | 346.6s | 148 |
| escape | female | 74 | 320.6s | 148 |
| simon | male | 68 | 190.2s | 136 |
| simon | female | 68 | 154.3s | 136 |
合计 142 id × 2 性别 = 284 条语音(568 文件)。全部按 R2 新规范重录:每游戏同一 speaker + 同一 instruct 常量(00 文档 §3.2),instruct 不含语速词;一句一文件整句生成,无数字拼接。escape=Uncle_Fu/Serena,simon=Uncle_Fu/Serena(沿用 R1 分配)。
环境音新增 5 条(Stable Audio 3,6s 循环,ogg+m4a):`amb_storage amb_cabinet amb_power amb_gate amb_gate_live`,统一归一到 -25dB 均值(对齐旧 amb_drip/-28.7、amb_wind/-21.3 之间),storage/power 轻微偏左、cabinet 轻微偏右 pan 增强房间辨识;staging wav 在 `tools/gen_amb_wav/`。
## 3. 删除清单(资产侧已执行,代码侧开发跟进)
**escape voice**(20 id × 2 性别 × 2 格式 + 平铺):
- 数字拼接链:`n0–n9 nshi unit_min unit_sec time_prefix` → `time_band1–4` 替代
- 旧开场:`intro tutorial` → GUIDE `g0–g7` 替代
- 旧提示:`hint_key hint_cabinet hint_box hint_gate` → `stuck_*` 三级提示替代
**simon voice**(23 id × 2 性别 × 2 格式 + 平铺):
- 拼接件:`di lun num_shi num_0–num_9 score_pre best_pre` → `round_*`/`score_band*` 整句替代
- 旧教学:`intro teach_up teach_down teach_left teach_right teach_tap teach_doubletap teach_end listen` → 交互教学 `t*_*` 替代
**sfx**:`simon/correct wrong newrecord`、`escape/ui_deny` 删除(反馈改震动,00 文档 §2)。
**平铺目录**:escape/simon 的 `audio/voice/*.{ogg,m4a}` 平铺旧文件已全部移除(引擎已支持 gender 目录)。storyline/rhythm/space 的平铺文件未动。
## 4. QC 结果
- 284 条全部通过:时长 >0.3s、峰值 >0.05、峰值归一 0.89。
- 两性时长离群检测(>3 倍):escape、simon 均 **ALL OK**,本轮零重生成。
- 双格式逐条核对:male/female 各目录 id 数与清单精确一致(74/68),无缺失(convert 已改为按台词表驱动,staging 残留旧 id 不会误落盘)。
- 人工试听仍未做:发音准确性需策划/QA 把关;多音字规避已在新台词写作时执行(如"重听"→"重新听一遍"(reopen_prompt)、避免"还/得/着"歧义写法)。
## 5. 给开发的配合说明
1. 语音 id 以 `round2-voice-ids.md` 为唯一权威清单;删除 id 不得再引用(文件已不存在,引擎容错会静默跳过,但请清理引用)。
2. `time_band1–4` 区间映射:`<120s / 120–300s / 300–600s / ≥600s`;`score_band1–6` 映射:`0 / 1–3 / 4–6 / 7–9 / 10–14 / ≥15`。
3. escape L3 提示 = `stuck_<阶段>_3` + 按当前坐标算路链播 `nav_up/down/left/right`(两句以内);单击检查 = 先重播当前房间 `amb_*` 再播描述。
4. escape 大门通电后环境音切 `amb_gate_live`;空房 `amb_wind`/`amb_hum` 轮换。
5. simon 无 BGM(`bgm/` 已空,勿加载);`sfx/gameover` 保留为结束音。
6. 菜单句 `menu_open/menu_restart/menu_home/menu_back` 两款游戏已各备一份;设置值播报("当前:女声,正常语速")为跨游戏需求,本清单未覆盖,建议 R3 统一处理。
## 6. 管线变更
- `tools/gen_voice_dual.py`:escape/simon 台词表整体替换为 R2 新版(全常量 instruct);`--convert` 改为按台词表驱动;其余游戏(storyline/rhythm/space)台词表与资产未动,脚本仍可全量复跑。
## 7. Mureka 花费
本轮 $0(两款游戏均无新 BGM 需求,simon 为去 BGM)。累计 $0.15 / $2.00。
+242
View File
@@ -0,0 +1,242 @@
# R2 语音 id 清单:escape《暗室》/ simon《音序回响》
> 给开发:本文件是两款游戏重设计的**最终语音资产清单**。`✦` = 新增 id,`●` = 保留 id(文本不变或微调,全部按新 instruct 重录),`✗` = 删除 id(文件已从 voice/male|female/ 移除,代码不得再引用)。
> 所有 id 在 `audio/voice/male/` 与 `audio/voice/female/` 下成对存在(.ogg + .m4a)。
> 生成规范(00 文档 §3):每游戏同一 speaker 常量 + 同一 instruct 常量;instruct 不含语速词(语速由引擎 playbackRate 控制);一句一文件,禁止拼接。
## 音色与 instruct 常量
| 游戏 | 目录 | speaker | instruct(本游戏全部 id 共用) |
|---|---|---|---|
| escape | male | Uncle_Fu | 低沉平稳的男声,冷静、克制,带一点神秘感 |
| escape | female | Serena | 沉稳平静的女声,冷静、克制,带一点神秘感 |
| simon | male | Uncle_Fu | 平静、清晰,像一个耐心的游戏主持人 |
| simon | female | Serena | 平静、清晰,像一个耐心的游戏主持人 |
---
## 一、escape《暗室》(共 74 id)
### 1. 开场引导 GUIDE(G0–G7,✦ 全部新增)
| id | 台词 | 对应设计步骤 |
|---|---|---|
| g0_intro ✦ | 黑暗。你在废弃的地下设施里醒来,什么都想不起来。你必须找到出路。 | G0(单击继续) |
| g1_move ✦ | 先活动一下。朝任意方向滑一下,走一小步。 | G1 |
| g1_done ✦ | 很好,你迈出了第一步。 | G1 反馈 |
| g2_wall ✦ | 这个房间不大,四面都是墙。再滑两下,试试碰碰墙。 | G2 |
| g3_left ✦ | 跟着我指的路走。向左滑。 | G3 |
| g4_down ✦ | 对。再向下滑。 | G3 反馈 + G4 指令(同一句) |
| g5_inspect ✦ | 听到水声了吗?单击一下,仔细检查这个房间。 | G5 |
| g5_key ✦ | 你摸到了一把钥匙! | G5 反馈(谜题链第一环) |
| g6_doubletap ✦ | 钥匙能开锁。双击,是把物品用出去的用法。现在,双击试试。 | G6 |
| g6_done ✦ | 对,就是这样。接下来,靠你自己了。 | G6 反馈 |
| g7_goal ✦ | 找到能用这把钥匙打开的东西。需要帮助时,在原地双击。 | G7 → PLAY |
### 2. 引导纠错与跳过(✦)
| id | 台词 | 用途 |
|---|---|---|
| guide_wrong_up ✦ | 不是这个方向。向上滑。 | 做错方向纠正(4 向各一) |
| guide_wrong_down ✦ | 不是这个方向。向下滑。 | 同上 |
| guide_wrong_left ✦ | 不是这个方向。向左滑。 | 同上 |
| guide_wrong_right ✦ | 不是这个方向。向右滑。 | 同上 |
| guide_wrong_gesture ✦ | 不是这个操作。照我说的做。 | 手势类型错误(该滑动了却点按等) |
| guide_blunt_up ✦ | 手指贴着屏幕,向上推一下。 | 同一步错 3 次的直白重述(4 向各一) |
| guide_blunt_down ✦ | 手指贴着屏幕,向下推一下。 | 同上 |
| guide_blunt_left ✦ | 手指贴着屏幕,向左推一下。 | 同上 |
| guide_blunt_right ✦ | 手指贴着屏幕,向右推一下。 | 同上 |
| guide_offpath ✦ | 先跟我走。 | 引导期间偏离脚本路线的温和拦回 |
| guide_skip ✦ | 跳过引导,直接开始自由探索。 | 引导期间下滑跳过确认 |
| reopen_prompt ✦ | 上滑,重新听一遍引导。单击,直接开始。 | 二周目开场(已完成过引导) |
### 3. 卡关三级提示(✦ 12 句 + 前置句 + 导航句 4 句)
L1/L2 每阶段自动播一次;L3 = `stuck_<阶段>_3` + 按当前位置算路链播 `nav_*`(两句以内)。
| id | 台词 | 级别/阶段 |
|---|---|---|
| stuck_ask ✦ | 需要帮助吗? | L1 前置句(播完接 L1 内容) |
| stuck_key_1 ✦ | 铁锈味最重的地方,值得仔细看看。 | L1·找钥匙 |
| stuck_key_2 ✦ | 去西南角的储物间,单击检查,找到钥匙。 | L2·找钥匙(双击兜底也播这条) |
| stuck_key_3 ✦ | 跟我说的方向走,去西南角的储物间。 | L3·找钥匙(后接 nav_* 链) |
| stuck_cabinet_1 ✦ | 钥匙就在你身上。它能打开某一把锁。 | L1·开铁柜 |
| stuck_cabinet_2 ✦ | 去东边的铁柜房,双击,用钥匙打开铁柜。 | L2·开铁柜 |
| stuck_cabinet_3 ✦ | 跟我说的方向走,去铁柜所在的房间。 | L3·开铁柜 |
| stuck_box_1 ✦ | 保险丝属于电箱。有电流声的地方,就有电箱。 | L1·修电箱 |
| stuck_box_2 ✦ | 去西北角的电箱房,双击,把保险丝装进电箱。 | L2·修电箱 |
| stuck_box_3 ✦ | 跟我说的方向走,去电箱所在的房间。 | L3·修电箱 |
| stuck_gate_1 ✦ | 电已经通了。该去找那扇铁门了。 | L1·开大门 |
| stuck_gate_2 ✦ | 去东南角的大门,双击,打开它,离开这里。 | L2·开大门 |
| stuck_gate_3 ✦ | 跟我说的方向走,去大门所在的房间。 | L3·开大门 |
| nav_up ✦ | 向上滑。 | L3 导航词(算路链播,可两句连读) |
| nav_down ✦ | 向下滑。 | 同上 |
| nav_left ✦ | 向左滑。 | 同上 |
| nav_right ✦ | 向右滑。 | 同上 |
### 4. 房间描述(✦ 首次进入关键房间时播,配合环境音)
| id | 台词 | 房间 |
|---|---|---|
| room_storage ✦ | 一间储物间。货架上堆满杂物,角落里传来水滴声。 | 储物间 (0,2),环境音 amb_storage |
| room_cabinet ✦ | 这个房间里,立着一个铁柜。 | 铁柜房 (2,1),amb_cabinet |
| room_power ✦ | 这个房间的墙上,有一只电箱。 | 电箱房 (0,0),amb_power |
| room_gate ✦ | 面前,是一扇沉重的铁门。 | 大门 (2,2),amb_gate / 通电后 amb_gate_live |
### 5. 用时播报(✦ 4 段整句,替代全部数字拼接)
| id | 台词 | 区间(供代码映射) |
|---|---|---|
| time_band1 ✦ | 你逃出来了,用时不到两分钟。了不起! | t < 120s |
| time_band2 ✦ | 你逃出来了,用时不到五分钟。 | 120s ≤ t < 300s |
| time_band3 ✦ | 你逃出来了,用时不到十分钟。 | 300s ≤ t < 600s |
| time_band4 ✦ | 你逃出来了,用时超过十分钟。 | t ≥ 600s |
### 6. 保留 id(● 文本不变,按新 instruct 双性别重录)
| id | 台词 |
|---|---|
| wall ● | 那边是墙,换个方向。(新文本;引导 G2 与 PLAY 撞墙共用,每次撞墙都播) |
| start_room ● | 你站在设施中央的房间里。滑动移动,单击检查,双击使用物品。(新文本;跳过引导后的 PLAY 开场) |
| found_key ● | 你蹲下身在储物架的角落里摸索,指尖碰到一个冰凉的金属物件——是一把钥匙!钥匙到手了。 |
| inspect_cabinet_locked ● | 这个房间里立着一个铁柜,柜门上挂着一把锁。也许,有什么钥匙能打开它。 |
| unlock_cabinet ● | 钥匙插进锁孔,缓缓转动。咔哒一声,柜门开了。柜子深处,躺着一枚保险丝。保险丝到手了。 |
| inspect_box_dead ● | 墙上是一只电箱,箱盖敞开着,里面的保险丝座空空如也。没有电,这里的大门永远打不开。 |
| box_fixed ● | 电箱运转正常,电流的嗡鸣声平稳而持续。 |
| fix_box ● | 你把保险丝用力按进卡座。火花一闪,嗡鸣声响起——头顶的线路恢复供电了! |
| inspect_gate ● | 面前是一扇沉重的铁门。门边的电子锁一片漆黑,没有任何反应。它需要电力。 |
| inspect_gate_ready ● | 电子锁的指示灯亮了,发出微弱的绿光。大门已经通电。双击,打开它,离开这里。 |
| escape ● | 你扳动开关。电机轰鸣,沉重的铁门缓缓升起,刺眼的光线涌了进来。你眯起眼睛,向前迈出了第一步。自由了。你逃出来了。 |
| use_fail ● | 这里没有用得上东西的地方。换个房间试试,或者先单击检查一下周围。 |
| inv_empty ● | 你摸了摸身上,什么也没有。 |
| inv_key ● | 你身上带着一把钥匙。 |
| inv_fuse ● | 你身上带着一枚保险丝。 |
| inv_both ● | 你身上带着一把钥匙和一枚保险丝。 |
| replay ● | 黑暗再次合拢。你回到了中央的房间。这一次,你会更快。 |
| again ● | 单击屏幕,再来一次。下滑,打开菜单。(新文本;ENDING 提示) |
| empty_1 ● | 房间里空空荡荡,只有你自己的回声。 |
| empty_2 ● | 你伸出手,摸到的只有冰冷粗糙的墙壁。 |
| empty_3 ● | 除了远处的水滴声,这里什么都没有。 |
### 7. 菜单与帮助(✦)
| id | 台词 | 用途 |
|---|---|---|
| help_ops ✦ | 滑动,在房间之间移动。单击,检查房间,或者重听房间的声音。双击,使用物品,或者查看背包。 | 菜单「重听帮助」/ 兜底说明 |
| menu_open ✦ | 菜单。 | 菜单打开播报第一项前 |
| menu_restart ✦ | 重新开始。 | 菜单选项 |
| menu_home ✦ | 回大厅。 | 菜单选项(保存并回大厅) |
| menu_back ✦ | 返回游戏。 | 菜单选项 |
### 8. escape 删除清单(✗ 文件已移除,代码禁止引用)
- 数字拼接链(14):`n0 n1 n2 n3 n4 n5 n6 n7 n8 n9 nshi unit_min unit_sec time_prefix` → 由 `time_band1..4` 替代
- 旧开场(2):`intro tutorial` → 由 GUIDE(g0–g7)替代
- 旧四级提示(4):`hint_key hint_cabinet hint_box hint_gate` → 由 `stuck_*` 三级提示替代
- 平铺目录 `audio/voice/` 下的 escape 旧文件全部移除(引擎已切 gender 目录)
---
## 二、simon《音序回响》(共 68 id)
### 1. 交互式教学(✦ T0–T7;T8 即 round_01)
| id | 台词 | 用途 |
|---|---|---|
| t0_welcome ✦ | 欢迎来到音序回响。先认识六种声音。 | T0(与下句链播) |
| t0_goal ✦ | 我会演奏一串声音,请你记住顺序,原样复现。 | T0 第二句 |
| t1_up ✦ | 向上滑,是这个声音。 | T1(播完接 tone_up,再接 t_try) |
| t2_down ✦ | 向下滑,是这个声音。 | T2 |
| t3_left ✦ | 向左滑,是这个声音。 | T3 |
| t4_right ✦ | 向右滑,是这个声音。 | T4 |
| t5_tap ✦ | 单击,是这个声音。 | T5 |
| t6_double ✦ | 双击,是这个声音。 | T6 |
| t_try ✦ | 你试试。 | T1–T6 共用,等待玩家做该手势 |
| t_ok ✦ | 对了。 | 做对,进下一个 |
| t_wrong_up ✦ | 不是这个,向上滑试试。 | 做错纠正(6 手势各一) |
| t_wrong_down ✦ | 不是这个,向下滑试试。 | 同上 |
| t_wrong_left ✦ | 不是这个,向左滑试试。 | 同上 |
| t_wrong_right ✦ | 不是这个,向右滑试试。 | 同上 |
| t_wrong_tap ✦ | 不是这个,单击试试。 | 同上 |
| t_wrong_double ✦ | 不是这个,双击试试。 | 同上 |
| t_blunt_up ✦ | 手指贴着屏幕,向上推一下。 | 同一手势错 3 次的直白版(6 手势各一) |
| t_blunt_down ✦ | 手指贴着屏幕,向下推一下。 | 同上 |
| t_blunt_left ✦ | 手指贴着屏幕,向左推一下。 | 同上 |
| t_blunt_right ✦ | 手指贴着屏幕,向右推一下。 | 同上 |
| t_blunt_tap ✦ | 用指尖,轻轻点一下屏幕。 | 同上 |
| t_blunt_double ✦ | 用指尖,快速点两下屏幕。 | 同上 |
| t7_ready ✦ | 六种声音都记住了。后面的序列,会越来越长。 | T7(与下句链播) |
| t7_retry ✦ | 答错可以消耗机会重听。双击,可以随时重听。 | T7 第二句 |
| t_skip ✦ | 跳过教学,直接开始。 | 教学期间下滑跳过确认 |
### 2. 轮次播报(✦ 21 句整句)
| id | 台词 |
|---|---|
| round_01 … round_20 ✦ | 第一轮,听好了。/第二轮,听好了。/第三轮,听好了。/第四轮,听好了。/第五轮,听好了。/第六轮,听好了。/第七轮,听好了。/第八轮,听好了。/第九轮,听好了。/第十轮,听好了。/第十一轮,听好了。/第十二轮,听好了。/第十三轮,听好了。/第十四轮,听好了。/第十五轮,听好了。/第十六轮,听好了。/第十七轮,听好了。/第十八轮,听好了。/第十九轮,听好了。/第二十轮,听好了。 |
| round_more ✦ | 新的一轮,听好了。 | round > 20 兜底 |
### 3. 成绩播报(✦ 6 段整句)
| id | 台词 | 区间(供代码映射,score=完成轮数) |
|---|---|---|
| score_band1 ✦ | 一轮都没坚持下来。别灰心。 | score = 0 |
| score_band2 ✦ | 你坚持了三轮以内。 | 1–3 |
| score_band3 ✦ | 你坚持了五轮左右。 | 4–6 |
| score_band4 ✦ | 你坚持了将近十轮。 | 7–9 |
| score_band5 ✦ | 你坚持了十轮以上,很厉害。 | 10–14 |
| score_band6 ✦ | 你坚持了十五轮以上,大师级! | ≥ 15 |
### 4. 流程句(✦/●)
| id | 台词 | 用途 |
|---|---|---|
| your_turn ● | 轮到你了。 | 第 1 轮复现阶段(之后轮次仅震动) |
| chances_out ✦ | 重听机会用完了,小心。 | 机会归 0 时提示 |
| retry_use ✦ | 错了。用一次机会,再听一遍。 | 答错且有机会(自动重播序列) |
| relisten ✦ | 再听一遍。 | 输入阶段双击主动重听(耗机会) |
| replay ● | 单击屏幕,再来一局。 | 结算 |
| rules_prompt ✦ | 上滑,重听规则。下滑,打开菜单。 | 结算/非输入阶段提示 |
| rules ✦ | 上行音,向上滑。下行音,向下滑。左边的音,向左滑。右边的音,向右滑。一声轻响,单击。两声轻响,双击。 | 规则重听句(上滑) |
| gameover ● | 游戏结束。 | 答错且无机会(sfx/gameover 之后链播成绩) |
### 5. 反馈短句(● 文本不变重录)
| id | 台词 | 用途 |
|---|---|---|
| correct ● | 答对了! | 整轮复现成功(每 4 轮播一次,其余仅震动) |
| wrong ● | 错了。 | 答错(retry_use 已含"错了",此句供无机会外的即时反馈,可选) |
| chance_plus ✦ | 机会加一。 | 每过 4 轮机会 +1 |
| new_record ● | 新纪录! | 破纪录 |
### 6. 菜单(✦)
| id | 台词 |
|---|---|
| menu_open ✦ | 菜单。 |
| menu_restart ✦ | 重新开始。 |
| menu_home ✦ | 回大厅。 |
| menu_back ✦ | 返回游戏。 |
### 7. simon 删除清单(✗ 文件已移除,代码禁止引用)
- 数字拼接件(14):`di lun num_shi num_0 num_1 num_2 num_3 num_4 num_5 num_6 num_7 num_8 num_9 score_pre best_pre` → 由 `round_*` / `score_band*` 整句替代
- 旧教学连播(9):`intro teach_up teach_down teach_left teach_right teach_tap teach_doubletap teach_end listen` → 由交互式教学 `t*_*` 替代
- sfx(3):`sfx/correct sfx/wrong sfx/newrecord` 已删除(反馈改震动);`sfx/gameover` 与 6 个 `tone_*` 保留
- 平铺目录 `audio/voice/` 下的 simon 旧文件全部移除
---
## 三、escape 环境音(sfx,非语音)
| id | 状态 | 内容 |
|---|---|---|
| amb_drip | 保留 | 起点 (1,1):单一滴水 |
| amb_wind | 保留 | 空房轮换:风声弱化版 |
| amb_hum | 保留 | 空房轮换:远处嗡鸣弱化版 |
| amb_storage ✦ | 新增 | 储物间:滴水 + 金属杂物轻响 |
| amb_cabinet ✦ | 新增 | 铁柜房:嗡鸣 + 铁皮共振 |
| amb_power ✦ | 新增 | 电箱房:电流嗡鸣 + 偶尔火花 |
| amb_gate ✦ | 新增 | 大门:风声 + 门外空旷感 |
| amb_gate_live ✦ | 新增 | 大门通电后:风声 + 电流声 |
| ui_deny ✗ | 删除 | 反馈提示音退役(改震动) |
+68
View File
@@ -0,0 +1,68 @@
# R3 音频轮次报告(2026-08-29,音乐音效总监)
本轮主题:《节拍行者》重构语音 + 3 首 BPM 精确 BGM,《盲航》重构语音备产。依据 `docs/design/03-rhythm-voice-ids.md`、`03-rhythm-rebuild.md`、`04-space-voice-ids.md`。Mureka 本轮 $0.15 / $0.30,累计 $0.30 / $2.00。
## 1. rhythm 语音(重构版)
- 台词表照录 `docs/design/03-rhythm-voice-ids.md`(31 句),合入 `tools/gen_voice_dual.py` 全量替换 R1 版。female=Vivian / male=Uncle_Fu,全表同一 instruct 常量。
- 生成统计:**male 31 条 / 116.6s,female 31 条 / 105.4s**(ogg+m4a 各 62 文件)。
- QC:时长/峰值/两性离群(>3 倍)全部 **ALL OK,零重生成**。
- 旧 id 清理:平铺 9 个旧 id 全部删除(`welcome rules tut_start tut_done grade_* restart`,其中 `grade_* restart` 按新文案重录覆盖,`welcome` 文案变更重录);`tut_start` 彻底弃用。目录现仅含新表 31 id × 2 性别。
## 2. rhythm BGM(3 首,Mureka)
| 曲目 | 选用候选(task/choice) | 源实测 BPM | 处理 | 成品实测 BPM | 循环时长 |
|---|---|---|---|---|---|
| track90《启程》 | 157963509563393 / 157963627134980(首提候选 1) | 98.75 | atempo=0.911392 拉伸 | **90.01** | 85.33s(32 小节) |
| track105《追风》 | 157963652431875 / 157963780292611(首提候选 0) | **105.00 精确** | 无拉伸 | **104.99** | 73.14s(32 小节) |
| track120《星爆》 | 157964212305921 / 157964317097985(重提候选 0) | **120.00 精确** | 无拉伸 | **120.00** | 72.00s(36 小节) |
- 后处理:首个强 onset 对齐小节头裁剪 → 整数小节 + 末 2 拍与开头 acrossfade 无缝循环 → loudnorm I=-20/TP=-2 → ogg q3 + m4a 128k。成品 mean -21.2/-21.3/-19.9dB。
- **BPM 测量方法学(重要)**:`librosa.beat.beat_track` 在 22050Hz/hop512 下按整帧量化,105 BPM 附近一档=4.3 BPM(读数 103.36/107.67 都是量化伪影)。改用自写梳状扫描 `tools/bpm_precise.py`(0.05 BPM 步进 + 相位扫描 + 抛物线插值,合成 105.00 点击轨校准通过)。`tools/bpm_check.py`(粗筛)+ `bpm_precise.py`(判定)均留在 tools/。
- 重试记录:track90 首提 121.0/98.75、重提 80.0/120.0 四候选均不达标,已达"每首最多重试 1 次"上限,按规则停止重提,选用 98.75 拉伸修正(电子乐 8.9% 减速,瞬态影响可接受,成品实测 90.01)。track120 首提不达标、重提即中 120.00。track105 首提即中。
- 旧 `bgm/groove` 已删除。花费明细已追加 `tools/mureka_log.md`(5 任务 × $0.03 = $0.15)。
## 3. space 语音(备产,已完成)
`docs/design/04-space-voice-ids.md` 在本轮执行期间就绪(52 句),已全量生成:
- **male 52 条 / 188.0s,female 52 条 / 159.4s**(ogg+m4a 各 104 文件)。female=Serena / male=Uncle_Fu,全表同一 instruct。
- QC:**ALL OK,零重生成**。
- 旧 id 清理:`num0–9 num_shi num_bai n_* intro1–4 hit1 hit2 gameover restart` 全部弃用删除(含平铺);`shield_ready shield_block` 沿用 id 重录。
- 注意:重构版闪避改为**同向**(左来左滑),新台词已按此写死,与 R1 旧台词(反向)语义相反——开发务必以新 game.js + 新语音为准,不可混用。
## 4. 删除清单(资产侧已执行)
- rhythm voice 平铺 9 id;rhythm sfx `judge_good judge_miss judge_perfect tick tick_accent`(反馈改震动、数拍融入 BGM);rhythm `bgm/groove`。
- space voice 旧 27 id(平铺 + male/female 全部,新表 52 id 重录替换)。
## 5. 给开发的配合说明
1. **rhythm 乐器音 sfx(已于 R3 收尾补齐,见 §7)**:重构 §4 需要的 `inst_kick inst_snare inst_hat_l inst_hat_r inst_tom_hi inst_tom_lo inst_accent` 已生产落盘;`cue_*` 6 个旧提示音已确认不再使用并删除。
2. BGM 对网格:三首成品 BPM 实测偏差 ≤0.01%,直接按设计 SPB(0.667/0.571/0.5s)排程即可;循环长度均为整数小节,`src.start(t0)` 从 0 播即是小节头。
3. rhythm 结算评级句已含准确率档位文案(S=九成五/A=八成五/B=七成/C=不到七成),与 §2 判定阈值一致,代码直接按 rate 映射 grade_* 即可。
4. space 里程碑触发点:10/25/50/100 颗(`ms_*`);结算 time 档 `<30/30–60/60–120/≥120s`,dodge 档 `<5/5–14/15–49/≥50`。
## 6. Mureka 花费
本轮 $0.15(5 任务,全部 succeeded);累计 **$0.30 / $2.00**。详见 `tools/mureka_log.md` R3 节。
## 7. 补产:rhythm 演奏乐器音 sfx(R3 收尾,2026-08-29)
重构 §4 的 7 个手势乐器音已补齐,落 `web/rhythm/audio/sfx/`(ogg q3 + m4a 128k):
| id | 内容 | 生成方式 | 时长 | 峰值 | 声像/调性 |
|---|---|---|---|---|---|
| inst_kick | 底鼓(tap) | Stable Audio 3("punchy deep EDM kick, dry, single hit") | 0.50s | -0.8dB | 中央 |
| inst_snare | 军鼓(doubletap) | Stable Audio 3 | 0.45s | -1.1dB | 中央 |
| inst_tom_hi | 高通鼓(up) | Stable Audio 3(high pitched synth tom) | 0.50s | -1.2dB | 中央,升调感 |
| inst_tom_lo | 低通鼓(down) | Stable Audio 3(low pitched deep synth tom) | 0.60s | -1.0dB | 中央,降调感 |
| inst_hat_l | 闭合镲(left) | Stable Audio 3(closed hi-hat) | 0.20s | -1.1dB | **极左**(L=-1.1dB / R=-22.7dB) |
| inst_hat_r | 开放镲(right) | Stable Audio 3(open hi-hat) | 0.60s | -2.2dB | **极右**(R=-2.2dB / L=-23.3dB) |
| inst_accent | Perfect 亮音叠加层 | **numpy 程序合成**(音高可控) | 0.38s | -1.8dB(0.8 峰值) | A minor 上行琶音 A5→E6→A6,三音 90ms 间隔快衰减 |
- 调性处理:三首 BGM 均 A minor(Mureka prompt 指定);accent 用 A 小调音级(A/E/A)程序合成,音高精确对齐;鼓件为伪音高打击乐,tom_hi/lo 在 prompt 里分了高低音区。staging wav 在 `tools/gen_inst_wav/`。
- 后处理:去头静音(silenceremove -45dB)→ 定长裁剪 + 末端 40-100ms 淡出防爆音 → 峰值归一 -1dBFS → hat 先 downmix 再 pan 后归一(避免了 pan 叠加削波的一版返工)。
- **id 映射注意**:设计文档 §4 写的叠加层 id 是 `sfx/accent`,本轮按主 agent 指令统一命名 `inst_accent`(与其他 6 件同前缀),开发以 `inst_accent` 为准。
- **cue_* 处置:删除**。通读 03-rhythm-rebuild.md,全文无 cue_* 资产引用(仅 §8.2 有内部变量 `_cues` 指期望音符),§4 手势音全部改走 inst_* 乐器音——旧指令音 `cue_double cue_down cue_left cue_right cue_tap cue_up`(6 id × 2 格式)已删。
- Mureka 花费不变(本轮 $0,累计 $0.30 / $2.00)。
+102
View File
@@ -0,0 +1,102 @@
# R4 音频轮次报告(2026-08-29,音乐音效总监)
本轮主题:新 RPG《剑与声》第一章全套音频资产 + space `menu_main` 改词重录。依据 `docs/design/05-rpg-ch1-voice-ids.md`、`05-rpg-chapter1.md`、`05-rpg-addendum.md`。Mureka 本轮 $0.12 / $0.30,**累计 $0.42 / $2.00**。
## 1. 语音(107 旁白 ×2 + 14 NPC)
| 类别 | 数量 | 总时长 | 落点 |
|---|---|---|---|
| 旁白 male(Uncle_Fu·说书人) | 107 | 282.8s | `web/rpg/audio/voice/male/` |
| 旁白 female(Serena·武侠故事) | 107 | 242.6s | `web/rpg/audio/voice/female/` |
| NPC 单音色(村长/老猎人/头目/寨主) | 14 | 50.9s | `web/rpg/audio/voice/` 平铺 |
- 台词表照录 05-rpg-ch1-voice-ids.md(104 句)+ addendum §6.2 补录 `foe_hp_high/mid/low`(3 句)= 107 句,已合入 `tools/gen_voice_dual.py`(新增 `rpg` 条目与 `NPCS` 平铺机制,管线断点续跑/`--only`/`--check`/`--convert` 全部适用)。
- **计数勘误**:台词表头写"NPC 16 句",实表只有 14 句(headman 4 + hunter 4 + elite 3 + boss1 3);合计 107×2+14 = 228 条(×2 格式 = 456 文件),以此为准。
- QC:时长/峰值/两性离群(>3 倍)**ALL OK,零重生成**。
- 已知风险:村长与黑风寨主同 speaker(Uncle_Fu)不同 instruct(慈祥和缓 vs 低沉阴狠),按设计"从不在同场景出现"处理,**需人工试听确认区分度**。
## 2. BGM(4 首,Mureka)
| id | task/choice | 选用 | 成品 |
|---|---|---|---|
| village | 157968630808577 / 157968750477315 | 候选 1(229.2s) | 90.00s 循环,mean -23.0dB |
| battle | 157968792551426 / 157968893214722 | 候选 0(212.8s) | 90.00s,mean -20.5dB |
| boss | 157968932864001 / 157969029332994 | 候选 1(178.2s) | 90.00s,mean -22.6dB |
| ending | 157969071407105 / 157969188913155 | 候选 1(248.4s) | 90.00s,mean -21.9dB |
- 4 任务一次成功无重试。处理:强 onset 起点 → 90s 裁剪 + 首尾 3s crossfade 无缝循环 → loudnorm -20 LUFS → ogg q3 + m4a。RPG 无节拍网格,BPM 不做硬校验。
- addendum §3 裁定:`bgm/explore` 取消(探索期无音乐),amb 走 sfx 层。花费已追加 `tools/mureka_log.md`。
## 3. SFX(35 件)
- **SA3 29 件**(`tools/gen_rpg_sfx.sh`,staging `tools/gen_rpg_sfx_wav/`):前摇 `tel_*` ×9(含 ch2/3 备用 croc/shaman/puppet/boss2,统一裁 1.0s 格挡窗口)、战斗 `atk_swing atk_hit parry skill_slash enemy_die potion`、探索 `chest drink_water rest door_heavy`、环境 `amb_*` ×11(含备用 swamp/peak,6s→1s 首尾交叉淡化成 5s 循环)。
- **SYN 5 件**(`tools/gen_rpg_syn.py`):`hurt`(60Hz 低频闷击,与 atk_hit 区分)、`flee`(渐远脚步)、`step`(单步)、`coin`(硬币叮当)、`levelup`(A 小调五声 A4-C5-D5-E5-A5 上行钟声琶音)。
- 响度:one-shot 峰值 -1dBFS;amb 均值 -25dB(amb_hunter/amb_hall 因 crackle 峰值封顶初次仅 -31dB,已用 `alimiter level=false` 限幅重做至 -25.9dB——R2 学到的 level=true 陷阱的反向应用)。
- `ui_deny` 按设计不做。`web/rpg/gen/README.md` 有完整清单与再生成方法。
## 4. space `menu_main` 改词重录
按 round2-review 裁决②(全球菜单约定:单击切换/双击确认),文本由「菜单。左右滑选择,单击确认。」改为「**菜单。单击切换选项,双击确认。**」,双性别重录覆盖 `web/space/audio/voice/male|female/menu_main.*`。
**同类遗留**:rhythm `menu_main` 文本同为旧约定("左右滑选择,单击确认"),且 rpg 的 `sys_menu`/`shop_open` 按 RPG 豁免条款保持"左右滑+单击"不变(正确)。rhythm 那句建议 R5 一并处理(rhythm 选曲界面非模态菜单仍用左右滑+单击,仅模态菜单改新约定——需策划确认文案后我重录)。
## 5. 给开发的 id 总表(可直接 import)
语音 id 分组(旁白 male/female 同集,NPC 平铺单集):
```js
const RPG_VOICE = {
intro: ['intro_1','intro_2','intro_3'],
system: ['sys_continue_ask','sys_new_game','sys_saved','sys_rest','sys_drink',
'sys_menu','sys_menu_resume','sys_menu_save','sys_menu_help',
'help_explore','help_battle','settings_hint'],
status: ['st_hp_high','st_hp_mid','st_hp_low','st_gold_poor','st_gold_some','st_gold_rich',
'st_lv_low','st_lv_mid','st_lv_high',
'st_weapon_none','st_weapon_iron','st_weapon_steel','st_weapon_wind',
'st_armor_none','st_armor_leather','st_armor_iron'],
foeHp: ['foe_hp_high','foe_hp_mid','foe_hp_low'], // 敌方血量档位(addendum §6.2)
desc: ['desc_village','desc_village_re','desc_path','desc_path_re','desc_fork','desc_fork_re',
'desc_chest','desc_chest_re','desc_stream','desc_stream_re','desc_hunter','desc_hunter_re',
'desc_deepwood','desc_deepwood_re','desc_gate','desc_hall'],
option: ['opt_go_path','opt_go_fork','opt_go_chest','opt_go_stream','opt_go_hunter',
'opt_go_deepwood','opt_go_gate','opt_back','opt_shop','opt_rest','opt_status',
'opt_investigate','opt_open_chest','opt_drink','opt_talk_hunter','opt_assault',
'opt_sneak','opt_leave'],
event: ['evt_gold15','evt_nothing','evt_chest','evt_hunter_gift','evt_gate_open','evt_ch1_end'],
battle: ['btl_start_wolf','btl_start_bandit','btl_start_spider','btl_start_elite','btl_start_boss1',
'cmd_attack','cmd_skill','cmd_defend','cmd_item','btl_nomp','btl_noitem','btl_flee',
'btl_noflee','btl_enemy_die','btl_win','btl_loot_small','btl_loot_mid','btl_loot_big',
'btl_levelup','btl_lose','btl_lose_hint','tut_b1','tut_b2','tut_b3','tut_b4','tut_b5'],
shop: ['shop_open','shop_price_sword','shop_price_armor','shop_price_potion',
'shop_owned','shop_poor','shop_buy'],
npc: ['npc_headman_1','npc_headman_2','npc_headman_3','npc_headman_4',
'npc_hunter_1','npc_hunter_2','npc_hunter_3','npc_hunter_4',
'npc_elite_1','npc_elite_half','npc_elite_die',
'npc_boss1_1','npc_boss1_2','npc_boss1_die'], // 平铺 voice/,无性别目录
};
const RPG_BGM = ['village','battle','boss','ending'];
const RPG_SFX = {
telegraph: ['tel_wolf','tel_bandit','tel_spider','tel_elite','tel_boss1', // 1.0s 格挡窗口
'tel_croc','tel_shaman','tel_puppet','tel_boss2'], // ch2/3 备用
combat: ['atk_swing','atk_hit','parry','skill_slash','enemy_die','potion','hurt','flee'],
explore: ['step','coin','chest','drink_water','rest','levelup','door_heavy'],
ambient: ['amb_village','amb_path','amb_fork','amb_chest','amb_stream','amb_hunter',
'amb_deepwood','amb_gate','amb_hall','amb_swamp','amb_peak'], // 5s 循环,手动 loop 接 sfx 总线
};
```
配合要点:
1. `amb_*` 需手动 BufferSource loop 接 `_sfxBus`(addendum §3 对实现的唯一新要求;不受 bgm=off 设置影响)。
2. 前摇音 `tel_<enemy>` 起点即格挡窗口起点(1.0s),Boss 二阶段 `tel_boss1` 以 playbackRate 1.2 重播(不加资产)。
3. `foe_hp_*` 为战斗态上滑敌方档位句;降档才播 `st_hp_mid/low`。
4. 场景 `desc_*` 首次/回访成对(`_re` 后缀为回访短句)。
5. **设计缺口(请策划补)**:敌人表中山贼标了半血句 `btl_half_bandit`,但台词表无此 id(头目有 `npc_elite_half`)——按 chapter1 §3"无此语音的敌人跳过"可运行,如需补齐请发文案我重录。`npc_boss3_warn`/`btl_half_shaman`/`btl_half_shadow` 属 ch2/3 最小集(addendum §5),等 ch2 台词表。
## 6. 遗留问题
- 村长/寨主同 speaker 区分度、全部新语音发音准确性:未做人工试听(QC 均为自动检查)。
- rhythm `menu_main` 旧菜单约定文案(§4)。
- rhythm 乐器音 `inst_accent` 与设计文档 §4 的 `accent` 命名差异(R3 已按 inst_accent 落盘,开发以此为准)。
## 7. Mureka 花费
本轮 $0.12(4 任务全成功);累计 **$0.42 / $2.00**,剩 $1.58。明细见 `tools/mureka_log.md` R4 节。
+39
View File
@@ -0,0 +1,39 @@
# R5 音频轮次报告(2026-08-29,音乐音效总监)
最终轮收尾:两处小批量补录 + 全项目资产终检。Mureka 本轮 $0(累计 **$0.42 / $2.00**,未再变动)。
## 1. 补录明细
### rhythm `menu_main` 改词重录(与 space R4 同款问题)
- 旧文案「菜单。左右滑选择,单击确认。」→ 新文案「**菜单。单击切换选项,双击确认。**」(round2-review 裁决②全球菜单约定;rhythm 选曲界面非模态菜单,仍左右滑+单击,不受影响)。
- 双性别重录(male=Uncle_Fu 4.00s / female=Vivian 4.16s,沿用 rhythm 统一 instruct),覆盖 `web/rhythm/audio/voice/male|female/menu_main.{ogg,m4a}`。台词表已同步更新(`tools/gen_voice_dual.py` RHYTHM_LINES)。
### rpg `btl_half_bandit` 补录(设计缺口)
- 敌人表(05-rpg-chapter1 §4.2)给山贼标了半血句但台词表漏发;按 B 组风格补写「**山贼的攻势缓了下来。**」,已合入 `tools/gen_voice_dual.py` RPG_LINES(B 组,27→含此句)。
- 双性别生成(male=Uncle_Fu 2.64s / female=Serena 1.52s),落 `web/rpg/audio/voice/male|female/btl_half_bandit.{ogg,m4a}`。rpg 旁白现为 108 id ×2。
- 触发点:`CHECK_ENEMY_DEAD` 前、山贼 HP 首次 ≤50% 时插播(chapter1 §3 半血叙事钩子)。
## 2. 全项目资产终检(`docs/audio/final-asset-check.md`)
终检脚本 `tools/check_all_assets.py`(可重复执行),检查 6 游戏:双格式配对、0 字节、ffprobe 全量解码、voice 性别目录 id 集合一致性(storyline/rpg 平铺角色句豁免):
| 游戏 | ogg | m4a | voice 性别一致性 |
|---|---|---|---|
| storyline | 133 | 133 | ✅ 各 36(平铺 48 = 12 角色 + 36 R1 旁白遗产) |
| escape | 166 | 166 | ✅ 各 74 |
| simon | 143 | 143 | ✅ 各 68 |
| rhythm | 72 | 72 | ✅ 各 31 |
| space | 116 | 116 | ✅ 各 52 |
| rpg | 269 | 269 | ✅ 各 108(平铺 14 NPC) |
| **合计** | **899** | **899** | 全部通过 |
零 0 字节、零解码失败、零格式缺失。
## 3. 五轮累计遗留(供后续迭代参考)
1. **人工试听从未执行**:全部 QC 为自动检查(时长/峰值/离群/BPM/电平)。多音字风险清单在 asset-manifest.md,村长 vs 寨主同 speaker 区分度(R4)为最高优先试听项。
2. storyline 平铺 36 个 R1 旁白遗产文件待引擎切换验证后清理。
3. ch2/3 台词表最小集(addendum §5:`npc_boss3_warn`、`btl_half_shaman`、`btl_half_shadow`)待策划补发。
4. Ryan 音色未采用样本在 `tools/samples/ryan_zh_*.wav`(如策划想给某游戏换年轻男声,改 SPEAKERS 重跑即可)。