feat(new8/batch2): 《深海回音》abyss +《雨夜专案》detective 全套交付(多agent流水线:策划→资产→开发→测试→真资产复跑)

- abyss:game.js 242 断言全绿(剧本A-F六路径/氧气门三形态/sonarGate仲裁/结算死窗/双轨看门狗/radio 8项修复继承);资产 148句+11key变体(电台滤波带内能量47-62%→69-80%)
- detective:game.js 265 断言真资产下全绿(矩阵不变式独立重算/指证全路径/评级12组注入/VERDICT死窗/二周目变体);真资产复跑回炉3处实现修复(无进展轨墙钟化/菜单暂停记账/停止播报真停声——mock时长掩盖的正确性bug)
- 资产:TTS 539条×2格式、Mureka 7首 $0.21(累计$1.08/$2.00)、SYN12+SA3 19件(QC抓出1例AAC过冲并修复)、封面×2、check_all_assets 10游戏全绿(abyss 298/298、detective 279/279)
- 平台接线:大厅双卡片、BUCKETS 增 abyss/detective 桶(H4 断言更新 10 游戏)、voice_text.json 10游戏991句
- 回归:14 套件全绿(10 playtest+guide+engine-voice+engine-input+api-smoke 12/12)
- 设计偏差登记:abyss 7条/detective 9条(全为设计内部冲突按承诺清单/归因真话律取优)
This commit is contained in:
xsl
2026-09-10 01:40:31 +08:00
parent cd4c5ec65a
commit 31372615b2
1183 changed files with 8445 additions and 10 deletions
+5 -4
View File
@@ -16,9 +16,10 @@ import subprocess
import sys
ROOT = "/home/xsl/SoundGame/web"
GAMES = ["storyline", "escape", "simon", "rhythm", "space", "rpg", "radio", "dungeon"]
GAMES = ["storyline", "escape", "simon", "rhythm", "space", "rpg", "radio", "dungeon",
"abyss", "detective"]
# 平铺 voice 文件(角色/NPC,单音色,不做性别集合一致性要求)
FLAT_OK = {"storyline", "rpg", "radio"}
FLAT_OK = {"storyline", "rpg", "radio", "abyss", "detective"}
def ids(d, ext):
@@ -29,7 +30,7 @@ def ids(d, ext):
def main():
problems = []
print("# 全项目音频资产终检(R5 建立,批次 1 起含 radio/dungeon,2026-09-01)\n")
print("# 全项目音频资产终检(R5 建立,批次 1 起含 radio/dungeon,批次 2 起含 abyss/detective,2026-09-09)\n")
print("| 游戏 | ogg | m4a | 0字节 | 解码失败 | voice male/female id 一致 | key male/female 一致且 ⊆ 主集 |")
print("|---|---|---|---|---|---|---|")
for g in GAMES:
@@ -98,7 +99,7 @@ def main():
for p in problems:
print(f"- {p}")
return 1
print("## 结论\n\n全部通过:双格式配对完整、无 0 字节、全部可解码、voice 性别目录 id 集合一致(storyline/rpg/radio 平铺角色句按约定豁免)、键盘变体目录两性别一致且 ⊆ 主集合。")
print("## 结论\n\n全部通过:双格式配对完整、无 0 字节、全部可解码、voice 性别目录 id 集合一致(storyline/rpg/radio/abyss/detective 平铺角色句按约定豁免)、键盘变体目录两性别一致且 ⊆ 主集合。")
return 0
+408 -2
View File
@@ -59,6 +59,9 @@ SPEAKERS = {
# radio 默认 speaker 仅作兜底;双性别行按 VOICE_SPK["radio"] 逐句覆盖(HOST/PROD 双配对)
"radio": {"male": "Uncle_Fu", "female": "Serena"},
"dungeon": {"male": "Uncle_Fu", "female": "Serena"},
# abyss 默认=DECK 调度(多数行);DIVER 行按 VOICE_SPK["abyss"] 逐句覆盖(radio 同型)
"abyss": {"male": "Dylan", "female": "Vivian"},
"detective": {"male": "Uncle_Fu", "female": "Serena"},
}
# instruct 对:(male, female)。None 表示两性别共用同一 instruct。
@@ -901,7 +904,365 @@ DUNGEON_LINES = [
("unlock_none", _DUN, "金币还不够,继续攒。"),
]
NPCS = {"rpg": RPG_NPC, "radio": RADIO_NPC}
# ---------------------------------------------------------------- abyss
# 《深海回音》批次 2(docs/design/17-abyss-voice-ids.md,148 句:双性别 127 + 平铺 NPC 21)。
# 台词全文逐字照抄 voice-ids 文档;双性别组分 DIVER(潜航员=玩家)/ DECK(母船调度/系统/
# 向导 gd_*)两个 speaker 配对(同性别双音色,VOICE_SPK["abyss"] 覆盖,radio HOST/PROD 同型:
# 同场景高频对话的两者永不同 speaker);_k 键盘变体 11 对在 KEY_LINES["abyss"]。
# NPC 平铺 21 句(小舟/老白/陈医官/高船长),转码时按 17-abyss.md §5.3 水声电台带通
# (NPC_BANDPASS["abyss"]),DIVER/DECK 不滤波(母船级音质)。
_ABY_DIVER = _pair("低沉冷静的男声,深潜救援员,干练沉着,水下通讯的轻微气声",
"低沉冷静的年轻女声,深潜救援员,干练沉着,水下通讯的轻微气声")
_ABY_DECK = _pair("清晰稳定的男声,母船潜水调度员,专业干脆,隔着耳机下达指令",
"清晰稳定的女声,母船潜水调度员,专业干脆,隔着耳机下达指令")
ABYSS_DIVER_LINES = [
# ---- G1 开场 ----
("b_open", _ABY_DIVER, "风停了。我站在问海号甲板上,下面三千米,是海燕号。"),
# ---- D1 第一潜·找船·小舟 ----
("d1_listen", _ABY_DIVER, "都别出声。管子那头,敲得很稳。"),
("d1_up", _ABY_DIVER, "小舟,抓住我的肩锁。我们上。"),
("d1_nolog", _ABY_DIVER, "日志可以补,人不能等。走了。"),
# ---- D2 第二潜·机舱·老白 ----
("d2_pry", _ABY_DIVER, "老白,忍住。先泄压,再撬。"),
("d2_cut", _ABY_DIVER, "切割枪。老白,闭眼,憋气。"),
("d2_valve", _ABY_DIVER, "电池舱我陪你去。这片海不能脏。"),
("d2_leave", _ABY_DIVER, "阀门交给母船。你先上,腿要紧。"),
# ---- D3 第三潜·病舱·陈医官/小郑 ----
("d3_chen", _ABY_DIVER, "陈医官,你的手在抖。这次,听我的。"),
("d3_zheng", _ABY_DIVER, "小郑先走。陈医官,下一潜,就是你的。"),
("d3_spare", _ABY_DIVER, "备用瓶留下。灯,给我亮着。"),
("d3_promise", _ABY_DIVER, "四小时内,我下来。等我。"),
# ---- D4 第四潜·指挥舱·高船长 ----
("d4_slow", _ABY_DIVER, "逐站停,慢慢浮。规矩不能破。"),
("d4_fast", _ABY_DIVER, "来不及了。直浮!"),
("d4_pick_gao", _ABY_DIVER, "船长,抓住我。海燕号的事,上面再说。"),
("d4_pick_chen", _ABY_DIVER, "陈医官,轮到你了。抓住,上浮。"),
("d4_pick_zheng", _ABY_DIVER, "小郑,吊床连人一起。走了。"),
("d4_talk", _ABY_DIVER, "日志我听完了。海燕号为什么沉,我会带上去。走吧。"),
("d4_silent", _ABY_DIVER, "纪律就是纪律。抓住,上浮。"),
# ---- F9 签收抉择(心结) ----
("g9_knot", _ABY_DIVER, "三年前,也是这条沟。我按时上浮了,搭档没有。"),
("d9_bell", _ABY_DIVER, "最后一潜。不为救人,为个交代。"),
("d9_rest", _ABY_DIVER, "交代,留给明天的人。我去医疗舱。"),
# ---- EP 结局与尾声回响 ----
("e1_a", _ABY_DIVER, "五个人都在甲板上。船钟的第一声,是替这条沟敲的。"),
("e1_b", _ABY_DIVER, "三年了,我终于敢往下看。明天,想再潜一次。"),
("e2_a", _ABY_DIVER, "五个人都救上来了。船钟,留在了沟底。"),
("e2_b", _ABY_DIVER, "没人怪我。可半夜醒来,总听见钟在响。"),
("e3_a", _ABY_DIVER, "没能都带回来。可我到底下去了,敲响了那口钟。"),
("e3_b", _ABY_DIVER, "钟声替他们,在沟底响了一声。这样,也好。"),
("e4_a", _ABY_DIVER, "我按规矩上浮了。规矩里,没写怎么难过。"),
("e4_b", _ABY_DIVER, "沟底很安静。安静得,像三年前那天。"),
]
ABYSS_DECK_LINES = [
# ---- G0.a 操作提示句(触屏版;_k 变体在 KEY_LINES) ----
("gd_brief", _ABY_DECK, "单击继续简报。要选择时,向左或向右滑。"),
("gd_continue", _ABY_DECK, "单击屏幕,继续。"),
("gd_again", _ABY_DECK, "还在吗?单击继续。"),
("gd_ping1", _ABY_DECK, "声呐待命。单击,发脉冲。"),
("gd_ping2", _ABY_DECK, "回波不会自己来。单击。"),
("sys_help", _ABY_DECK, "单击继续,双击重新听。上滑听状态,下滑开菜单。选择时,左右滑。"),
("sys_menu", _ABY_DECK, "菜单。单击切换选项,双击确认。"),
("sys_skip", _ABY_DECK, "想跳过这句,单击就行。"),
("sys_continue_ask", _ABY_DECK, "检测到你的下潜记录。单击继续上次,右滑开始新救援。"),
# ---- G0.b 状态/系统句 ----
("gd_invalid", _ABY_DECK, "这个手势,水里用不上。"),
("gd_prog1", _ABY_DECK, "滑动在这里用不上。想想调度刚说的话。"),
("gd_prog2", _ABY_DECK, "别乱。停一下,想想下一步。"),
("sys_menu_resume", _ABY_DECK, "回到水下。"),
("sys_menu_restart", _ABY_DECK, "重新开始这次救援。"),
("sys_menu_lobby", _ABY_DECK, "保存并回大厅。"),
("sys_settings", _ABY_DECK, "音色、语速、背景音乐,请回大厅修改。"),
("sys_new_dive", _ABY_DECK, "新的一次下潜,开始了。"),
("prog_d1", _ABY_DECK, "现在是第一次下潜。"),
("prog_d2", _ABY_DECK, "现在是第二次下潜。"),
("prog_d3", _ABY_DECK, "现在是第三次下潜。"),
("prog_d4", _ABY_DECK, "现在是最后一次下潜。"),
("oxy_full", _ABY_DECK, "气瓶还足,救得动。"),
("oxy_ok", _ABY_DECK, "氧气还够两潜。"),
("oxy_low", _ABY_DECK, "氧气告急,只够最后一潜。"),
("oxy_crit", _ABY_DECK, "氧气见底,必须上浮。"),
("oxy_gain", _ABY_DECK, "应急瓶接上了,多三格。"),
("dry_a", _ABY_DECK, "气瓶用干了。立刻上浮。"),
("dry_b", _ABY_DECK, "气花在了人身上。人,都上来了。"),
# ---- G1 开场 ----
("b_rule", _ABY_DECK, "规矩就一条:气不够一潜,人就必须上浮。"),
("b_goal", _ABY_DECK, "海燕号,五个人。你的双瓶,够下四潜。"),
("b_go", _ABY_DECK, "第一潜,找船。耳朵交给声呐。"),
# ---- D1 第一潜 ----
("dv1_down", _ABY_DECK, "下潜开始。水会越来越黑,声音会越来越多。"),
("dv1_teach", _ABY_DECK, "到深度了。声呐静了。单击,发一枚脉冲。"),
("dv1_metal", _ABY_DECK, "金属回波,钢板。听见这个,就是海燕号的船身。"),
("dv1_link", _ABY_DECK, "回波后面有杂音,是电台!接通了。"),
("p1", _ABY_DECK, "管路在响。向左滑,停下来听敲管的暗号。向右滑,先带小舟上浮。"),
("d1_code", _ABY_DECK, "是老白的暗号:腿被压住,先泄压,再撬。记住这个敲法。"),
("p2", _ABY_DECK, "小舟想回去拿声呐日志。向左滑,等她。向右滑,直接上浮。"),
("d1_surf", _ABY_DECK, "小舟出水,第一潜收工。往返,扣三格气。"),
# ---- D2 第二潜 ----
("dv2_down", _ABY_DECK, "第二潜,机舱。顺着敲管的声音走。"),
("dv2_found", _ABY_DECK, "碎石回波后面,敲管声密了。机舱到了。"),
("p3", _ABY_DECK, "钢梁压着腿。向左滑,泄压后慢慢撬。向右滑,切割枪,快切。"),
("d2_pry_ok", _ABY_DECK, "暗号没白听。管子一松,钢梁抬起来了。"),
("d2_pry_slow", _ABY_DECK, "摸着找泄压阀,多费了一格气。腿,出来了。"),
("d2_flash", _ABY_DECK, "火花炸了一下,虚惊。老白咳着,腿抽出来了。"),
("p4", _ABY_DECK, "老白要去关电池舱阀门。向左滑,陪他去。向右滑,直接上浮。"),
("d2_valve_e", _ABY_DECK, "阀门关死了。两格气,换一片干净海。"),
("d2_surf", _ABY_DECK, "老白出水。他一直扒着舱门,往水里看。"),
("d2_supply", _ABY_DECK, "潜友阿凯捎来应急瓶。甲板上,粥给你温着。"),
# ---- D3 第三潜 ----
("dv3_down", _ABY_DECK, "第三潜,病舱。海燕号在倾斜,别恋战。"),
("dv3_groan", _ABY_DECK, "回波发闷。船体在呻吟,它撑不久了。"),
("p5", _ABY_DECK, "病舱一次只能走一个。向左滑,先带陈医官。向右滑,先带小郑。"),
("d3_chen_e", _ABY_DECK, "陈医官出水。小郑固定在吊床上,呼吸平稳。"),
("d3_zheng_e", _ABY_DECK, "小郑吊上去了。他一路,都没敢出声。"),
("p6", _ABY_DECK, "留守的人要空气。向左滑,留下你的备用瓶。向右滑,约定下一潜来接。"),
("d3_spare_e", _ABY_DECK, "备用瓶挂上了,能多撑十二小时。"),
("d3_surf", _ABY_DECK, "病舱的人出水。海燕号的呻吟,隔着水都听得见。"),
# ---- D4 第四潜 ----
("dv4_none", _ABY_DECK, "气不够一潜了。第四潜,取消。"),
("dv4_down", _ABY_DECK, "最后一潜,指挥舱。海燕号,撑不住了。"),
("dv4_slide", _ABY_DECK, "它滑了!抓稳索缆,指挥舱里还有人!"),
("p7", _ABY_DECK, "双人上浮。向左滑,逐站减压慢慢浮。向右滑,违规直浮,搏一把。"),
("p7_chen", _ABY_DECK, "气只够带一个。向左滑,带船长。向右滑,带陈医官。"),
("p7_zheng", _ABY_DECK, "气只够带一个。向左滑,带船长。向右滑,带小郑。"),
("d4_slow_e", _ABY_DECK, "减压站一个个过。气瓶在跳,人稳着。"),
("d4_fast_e", _ABY_DECK, "违规快浮。医疗舱的灯,先给你们开好。"),
("d4_stay_lost", _ABY_DECK, "另一位,留在了倾斜的船舱。航标灯,替所有人亮着。"),
("p8", _ABY_DECK, "船长的话没说完。向左滑,把你听到的说出来。向右滑,什么都不问,拉他上浮。"),
("d4_surf", _ABY_DECK, "最后一潜收工。问海号的甲板,从没这么亮过。"),
# ---- F9 签收抉择 ----
("g9_in", _ABY_DECK, "医疗舱躺满了。你的气瓶剩多少,你比我清楚。"),
("p9", _ABY_DECK, "海燕号的船钟,还挂在沉船上。向左滑,用最后的气,下去取。向右滑,进医疗舱。"),
("g9_dry", _ABY_DECK, "一格气都不剩了。能带的,你都带回来了。"),
("d9_bello", _ABY_DECK, "船钟出水。海燕号的声音,回家了。"),
# ---- EP 尾声回响 ----
("ep_lead", _ABY_DECK, "收队了。调度台给你记一笔——他们,后来怎样了。"),
("ep_zhou_ok", _ABY_DECK, "小舟:归队报告打了三页。她说,声音都记得。"),
("ep_zhou_no", _ABY_DECK, "小舟:声呐日志没了。她凭记忆,重新描了一遍海图。"),
("ep_bai_ok", _ABY_DECK, "老白:腿保住了。阀门那夜之后,见人就夸你。"),
("ep_bai_no", _ABY_DECK, "老白:腿打了钢钉。他说,瘸着也值。"),
("ep_chen_ok", _ABY_DECK, "陈医官:回了医院。诊室里,挂着一盏海底的灯。"),
("ep_chen_lost", _ABY_DECK, "陈医官:她守着灯,到最后一小时。灯,还亮着。"),
("ep_zheng_ok", _ABY_DECK, "小郑:拆了石膏,第一件事,去看海。"),
("ep_zheng_lost", _ABY_DECK, "小郑:吊床随船,滑进了沟底。他没来得及看日出。"),
("ep_gao_peace", _ABY_DECK, "高船长:退役申请自己写的。第一行写着:数据不如人。"),
("ep_gao_up", _ABY_DECK, "高船长:上了岸,一直没说话。听说,他在学敲管语。"),
("ep_gao_lost", _ABY_DECK, "高船长:随海燕号留在沟底。航标灯,还亮着。"),
("ep_trench_bell", _ABY_DECK, "沟底:船钟挂在问海号桅杆上。风一过,就响一声。"),
("ep_trench_deep", _ABY_DECK, "沟底:很深,很静。海燕号睡在里面,像睡着了。"),
]
ABYSS_LINES = ABYSS_DIVER_LINES + ABYSS_DECK_LINES
# NPC 单音色平铺(id, speaker, instruct, 台词)→ web/abyss/audio/voice/<id>.*
#(转码时按 17-abyss.md §5.3 逐船员水声电台带通,见 NPC_BANDPASS;staging 保留未滤波原声)。
ABYSS_NPC = [
# 小舟(23 岁声呐兵,女,Serena)
("z1_a", "Serena", "年轻女声,二十三岁声呐兵,缺氧后发虚,强撑着干脆", "……有人吗?声呐兵,小舟。我们还活着,全艇五个人。"),
("z1_b", "Serena", "年轻女声,二十三岁声呐兵,缺氧后发虚,强撑着干脆", "轮机长老白困在机舱,陈医官和小郑在病舱,船长在指挥舱。"),
("z1_knock", "Serena", "年轻女声,二十三岁声呐兵,缺氧后发虚,强撑着干脆", "等等,你听。管子里,有人在敲。"),
("z1_bye", "Serena", "年轻女声,二十三岁声呐兵,缺氧后发虚,强撑着干脆", "好。上面……是不是天亮了?"),
("d1_log", "Serena", "年轻女声,二十三岁声呐兵,缺氧后发虚,强撑着干脆", "日志里有失事前,最后一段录音。给你,替我们收好。"),
# 老白(50 岁轮机长,男,Uncle_Fu)
("bai_a", "Uncle_Fu", "沙哑爽朗的中年男声,五十岁轮机长,忍着伤痛开玩笑", "哈哈,救援的?我这腿,跟冷却管缠上了。"),
("bai_b", "Uncle_Fu", "沙哑爽朗的中年男声,五十岁轮机长,忍着伤痛开玩笑", "艇上的药板烧了。病舱那两个,比我悬。"),
("bai_out", "Uncle_Fu", "沙哑爽朗的中年男声,五十岁轮机长,忍着伤痛开玩笑", "腿还在!我的腿还在!走,我给你带路。"),
("bai_thanks", "Uncle_Fu", "沙哑爽朗的中年男声,五十岁轮机长,忍着伤痛开玩笑", "这片海养着一村人。这份情,我记一辈子。"),
# 陈医官(45 岁船医,女,Vivian)
("chen_a", "Vivian", "平静沙哑的中年女声,四十五岁船医,专业镇定,语气温和", "你来了。小郑股骨断了,我给他固定好了。"),
("chen_b", "Vivian", "平静沙哑的中年女声,四十五岁船医,专业镇定,语气温和", "救援钟一次带一个。我是医生,我最后走。"),
("chen_up", "Vivian", "平静沙哑的中年女声,四十五岁船医,专业镇定,语气温和", "……好。小郑,等我,上面给你热粥。"),
("chen_stay", "Vivian", "平静沙哑的中年女声,四十五岁船医,专业镇定,语气温和", "去吧。我守着灯,灯不灭,人就不散。"),
("chen_last", "Vivian", "平静沙哑的中年女声,四十五岁船医,专业镇定,语气温和", "去吧。灯我留着,人齐了就熄。"),
# 高船长(58 岁船长,男,Eric)
("gao_final", "Eric", "低沉苍老的男声,五十八岁船长,疲惫克制,有老舵手的威严", "别下来。带他们回家,就算救完了。海燕号,通话结束。"),
("gao_a", "Eric", "低沉苍老的男声,五十八岁船长,疲惫克制,有老舵手的威严", "救援员。我船上,还剩两个活人。"),
("gao_b", "Eric", "低沉苍老的男声,五十八岁船长,疲惫克制,有老舵手的威严", "都带走,我最后上。这是船长的规矩。"),
("gao_last", "Eric", "低沉苍老的男声,五十八岁船长,疲惫克制,有老舵手的威严", "航标灯替我留着。就说,船长睡了。"),
("gao_c", "Eric", "低沉苍老的男声,五十八岁船长,疲惫克制,有老舵手的威严", "三年前……没什么。走吧,别耽误。"),
("gao_confess", "Eric", "低沉苍老的男声,五十八岁船长,疲惫克制,有老舵手的威严", "日志你拿了?里面写着。是我下令,多采了一小时。"),
("gao_peace", "Eric", "低沉苍老的男声,五十八岁船长,疲惫克制,有老舵手的威严", "……好。这一次,听救援员的。"),
]
# ---------------------------------------------------------------- detective
# 《雨夜专案》批次 2(docs/design/18-detective-voice-ids.md,158 句:旁白 106 双性别 + 平铺 NPC 52)。
# 台词全文逐字照抄 voice-ids 文档;旁白只做系统/指引/教学/状态/现场自勘(探长自勘)/裁决宣读,
# 不念证词(证词=证人 NPC 平铺,DETECTIVE_NPC);键盘变体 V 组 10 对在 KEY_LINES["detective"]。
# NPC 不加电话滤波(区别于 radio/abyss——区分度靠 speaker+instruct+游戏侧签名 earcon 前缀)。
_DET = _pair("低沉沉稳的男声,专案组探长,冷静克制,像在雨夜读卷宗",
"沉稳清晰的女声,专案组探长,冷静克制,像在雨夜读卷宗")
DETECTIVE_LINES = [
# ---- G0 系统/菜单/帮助 ----
("sys_menu", _DET, "菜单。单击切换,双击确认。"),
("sys_menu_resume", _DET, "回到证词板。"),
("sys_menu_cf", _DET, "去指证。"),
("sys_menu_save", _DET, "保存并回大厅。"),
("sys_menu_help", _DET, "重新听帮助。"),
("sys_menu_restart", _DET, "重新查这桩案子。"),
("sys_saved", _DET, "进度已保存。"),
("settings_hint", _DET, "音色、语速、背景音乐,请回大厅修改。"),
("sys_help", _DET, "左右滑换卷宗,单击听取,双击重新听。长按指证,上滑状态,下滑菜单。"),
("sys_continue_ask", _DET, "检测到未结的案子。单击继续,右滑换一桩新案。"),
("sys_new_case", _DET, "新案开卷。"),
# ---- G1 开场/教学 ----
("intro_1", _DET, "雨下了一整夜。清晨,聚宝斋后院,古董商沈万川死了。"),
("intro_2", _DET, "你是专案组探长。这桩案子,归你。"),
("intro_3", _DET, "卷宗六份:四位证人的证词,现场勘验,法医报告。"),
("tut_d0", _DET, "先熟悉证词板。左右滑,换卷宗。"),
("tut_listen", _DET, "单击,听取当前卷宗。"),
("tut_replay", _DET, "双击,重新听这一句。"),
("tut_status", _DET, "上滑,随时听进度:问了几份,疑点几处。"),
("tut_confront", _DET, "按住屏幕,进入指证。去找两句对不上的证词。"),
("tut_cf_try", _DET, "练习一次。选一份证词,单击确认;再选一份,任意一句。"),
("tut_cf_ok", _DET, "指证就是这样。练习不算数,真矛盾要靠耳朵找。"),
("tut_done", _DET, "教学完了。开始查案。"),
("tut_skip", _DET, "已跳过教学。左右滑换卷宗,单击听取。"),
# ---- G2 状态/条目 ----
("st_asked_0", _DET, "六份卷宗,一份都没听。"),
("st_asked_1", _DET, "已听一份,还有五份。"),
("st_asked_2", _DET, "已听两份,还有四份。"),
("st_asked_3", _DET, "已听三份,还有三份。"),
("st_asked_4", _DET, "已听四份,还有两份。"),
("st_asked_5", _DET, "已听五份,还有一份。"),
("st_asked_6", _DET, "六份都听完了。"),
("st_doubt_0", _DET, "疑点,还没有。"),
("st_doubt_1", _DET, "疑点,一处。"),
("st_doubt_2", _DET, "疑点,两处。"),
("st_doubt_3", _DET, "疑点,三处。"),
("st_doubt_4", _DET, "疑点,四处,齐了。"),
("item_w1", _DET, "门卫老葛的证词。"),
("item_w2", _DET, "学徒小顺的证词。"),
("item_w3", _DET, "账房周先生的证词。"),
("item_w4", _DET, "房东温太太的证词。"),
("item_scene", _DET, "现场勘验。"),
("item_fore", _DET, "法医报告。"),
("item_case", _DET, "结案陈词。"),
("intro_w3", _DET, "周先生,管了十年的账,见人三分笑。"),
# ---- G3 现场勘验(探长自勘) ----
("sc_0", _DET, "你打伞进了后院。雨水顺着瓦檐,淌成一道帘子。"),
("sc_1", _DET, "柴房门口,沈万川面朝下倒着。后脑一处伤,现场没有凶器。"),
("sc_2", _DET, "后门门闩完好,是死者自己开的门。生人叫不开这扇门。"),
("sc_3", _DET, "泥地上只有进来的脚印,没有出去的。墙根的花盆,翻了一个。"),
("sc_4", _DET, "库房铜秤立在架上,秤砣不见了。"),
("sc_5", _DET, "柴房墙上,挂钥匙的铜钩,空着。"),
# ---- G4 指证 ----
("cf_start", _DET, "指证矛盾。先选第一份证词。左右滑换,单击确认。"),
("cf_pick_line", _DET, "左右滑,一句一句听。"),
("cf_confirm", _DET, "就这句?单击,定下来。"),
("cf_second", _DET, "再选与它矛盾的那份证词。"),
("cf_self", _DET, "同一句证词,和自己比不出矛盾。"),
("cf_same", _DET, "这两句说得一致,不矛盾。"),
("cf_diff", _DET, "这两句,说的不是一件事。"),
("cf_hit", _DET, "对不上!矛盾成立,记入疑点。"),
# ---- G5 结案三问 ----
("fin_start", _DET, "结案陈词。先指认真凶:四位证人,选一个。"),
("fin_who_confirm", _DET, "就指认他?单击,定下来。"),
("fin_clear", _DET, "不在场证明成立。证据放人,回到证词板。"),
("fin_right", _DET, "证据链闭合。周先生,你还有什么话说?"),
("fin_right_b", _DET, "证据链闭合。小顺,你还有什么话说?"),
("fin_ask_weapon", _DET, "第二问:凶器是什么?"),
("wp_1", _DET, "松木劈柴。"),
("wp_2", _DET, "铜秤砣。"),
("wp_3", _DET, "铁门闩。"),
("wp_4", _DET, "青瓷花盆。"),
("fin_wp_right", _DET, "对。创口的铜屑,不见了的秤砣,都指向它。"),
("fin_wp_wrong", _DET, "不对。铜屑不答应。记下了。"),
("fin_ask_motive", _DET, "第三问:动机是什么?"),
("mv_1", _DET, "监守自盗。"),
("mv_2", _DET, "寻仇泄愤。"),
("mv_3", _DET, "劫财入户。"),
("fin_mv_right", _DET, "对。库里短的东西,就是引线。"),
("fin_mv_wrong", _DET, "不对。账上短的东西,才是引线。记下了。"),
# ---- G6 结算 ----
("settle_open", _DET, "案件归档。雨,停了。"),
("rate_s", _DET, "教科书结案。四处疑点,一击即中。"),
("rate_a", _DET, "干净利落的结案。"),
("rate_b", _DET, "案子结了,卷宗上有疏漏。"),
("rate_c", _DET, "案子是结了,卷宗上补丁不少。"),
("st_miss_0", _DET, "指证,一次没错。"),
("st_miss_1", _DET, "指证,错过一两回。"),
("st_miss_2", _DET, "指证,错了不少。"),
("settle_hook", _DET, "同一场雨里,还有别的案子。单击,接新案。"),
# ---- G7 看门狗/卡关/纠错 ----
("gd_board", _DET, "还在证词板。左右滑,换卷宗。"),
("gd_cf", _DET, "还在选证词。左右滑,单击确认。"),
("gd_fin", _DET, "在想?左右滑选,单击定。"),
("gd_invalid", _DET, "这个操作,这里用不上。"),
("hint_a", _DET, "探长,还没听的卷宗,先过一遍耳朵。"),
("hint_b", _DET, "探长,证词里有对不上的地方,逐句比对。"),
("hint_c1", _DET, "试试指证:周先生说熄了灯,温太太说灯还亮着。"),
("hint_c2", _DET, "试试指证:周先生说铜秤卖了,现场铜秤还在。"),
("b_hint_c1", _DET, "试试指证:小顺说熄了灯,温太太说灯还亮着。"),
("b_hint_c2", _DET, "试试指证:小顺说铜秤卖了,现场铜秤还在。"),
("hint_fin", _DET, "疑点齐了。去结案陈词。"),
("recap_go", _DET, "接着查。"),
]
# NPC 单音色平铺(id, speaker, instruct, 台词)→ web/detective/audio/voice/<id>.*
# 证人 4 + 秦法医(≤5 约束);同一角色 speaker+instruct 恒定;不加滤波(18b 头注)。
DETECTIVE_NPC = [
# 老葛(62 岁门卫,Eric)
("w1_1", "Eric", "苍老沙哑的男声,守夜人,慢悠悠,带倦意", "昨儿夜里雨大,我守着街门,一步没敢挪窝。"),
("w1_2", "Eric", "苍老沙哑的男声,守夜人,慢悠悠,带倦意", "九点四十,雨点子刚砸下来,小顺打着伞出的街门。"),
("w1_3", "Eric", "苍老沙哑的男声,守夜人,慢悠悠,带倦意", "十点一刻,一位先生收着黑伞进了后巷。个儿高,微驼背。"),
("w1_4", "Eric", "苍老沙哑的男声,守夜人,慢悠悠,带倦意", "九点五十,周账房出的街门,跟我说了声,回家。"),
("w1_5", "Eric", "苍老沙哑的男声,守夜人,慢悠悠,带倦意", "后半夜,温太太还来门房借过一回热水。"),
("w1_6", "Eric", "苍老沙哑的男声,守夜人,慢悠悠,带倦意", "听说店里账上短了银子,沈老板撂了话,月底清账。"),
("acc_ge", "Eric", "苍老沙哑的男声,守夜人,慢悠悠,带倦意", "我守了一夜门!温太太来借热水,她能作证!"),
# 小顺(19 岁学徒,Dylan)
("w2_1", "Dylan", "年轻清亮的男声,学徒,怯生生的,慌张诚实", "夜里,师父打发我去城南,给刘掌柜送匣子。"),
("w2_2", "Dylan", "年轻清亮的男声,学徒,怯生生的,慌张诚实", "雨太大,刘掌柜留我住的,今早才回店。"),
("w2_3", "Dylan", "年轻清亮的男声,学徒,怯生生的,慌张诚实", "库房钥匙?师父嫌沉,平日就挂在柴房墙上的铜钩。"),
("w2_4", "Dylan", "年轻清亮的男声,学徒,怯生生的,慌张诚实", "师父的账,向来只信周先生一个人。"),
("w2_5", "Dylan", "年轻清亮的男声,学徒,怯生生的,慌张诚实", "后门那闩,生人叫不开。熟人来了,师父才亲自去开。"),
("w2_6", "Dylan", "年轻清亮的男声,学徒,怯生生的,慌张诚实", "周先生常念叨,账房的活,越到夜里越清静。"),
("acc_shun", "Dylan", "年轻清亮的男声,学徒,怯生生的,慌张诚实", "我宿在城南刘掌柜家,他全家都能作证!"),
("b_shun_1", "Dylan", "年轻清亮的男声,学徒,怯生生的,慌张诚实", "我走的时候,顺手熄了店堂的灯。"),
("b_shun_2", "Dylan", "年轻清亮的男声,学徒,怯生生的,慌张诚实", "钥匙,师父贴身带着,从不离身。"),
("b_shun_3", "Dylan", "年轻清亮的男声,学徒,怯生生的,慌张诚实", "那伤,八成是柴房劈柴砸的。铜秤早卖给收废品的了。"),
("b_shun_4", "Dylan", "年轻清亮的男声,学徒,怯生生的,慌张诚实", "库房的货,我一件都没碰过。"),
("b_shun_react_1", "Dylan", "年轻清亮的男声,学徒,怯生生的,慌张诚实", "灯?我、我走的时候明明熄了……"),
("b_shun_react_2", "Dylan", "年轻清亮的男声,学徒,怯生生的,慌张诚实", "别问了……别问了……"),
("b_shun_break_1", "Dylan", "年轻清亮的男声,学徒,怯生生的,慌张诚实", "匣子是我送的,可我半路折回来了……"),
("b_shun_break_2", "Dylan", "年轻清亮的男声,学徒,怯生生的,慌张诚实", "我把棉袄反穿,弓着背,葛大爷没认出我。"),
("b_shun_break_3", "Dylan", "年轻清亮的男声,学徒,怯生生的,慌张诚实", "库房的货,我拿过三件换了钱。他说要对账……秤砣下去的时候,他看着我。"),
# 周先生(45 岁账房,pack A 真凶,Uncle_Fu——与 male 旁白同 speaker,靠签名+instruct 区分)
("z_1", "Uncle_Fu", "平板谨慎的男声,账房,字斟句酌,被追问时渐慌", "我七点进店上夜账。九点五十对完,锁了前门回家。"),
("z_2", "Uncle_Fu", "平板谨慎的男声,账房,字斟句酌,被追问时渐慌", "临走,我顺手熄了店堂的灯。那会儿,店里就剩老板。"),
("z_3", "Uncle_Fu", "平板谨慎的男声,账房,字斟句酌,被追问时渐慌", "库房钥匙?沈老板贴身带着,从不离身。"),
("z_4", "Uncle_Fu", "平板谨慎的男声,账房,字斟句酌,被追问时渐慌", "那伤,是松木劈柴砸的。铜秤?上个月卖给收废品的了。"),
("z_5", "Uncle_Fu", "平板谨慎的男声,账房,字斟句酌,被追问时渐慌", "我到家倒头就睡,夜里的事,一概不知。"),
("z_6", "Uncle_Fu", "平板谨慎的男声,账房,字斟句酌,被追问时渐慌", "你们要是不信,去问我家婆娘。"),
("z_react_1", "Uncle_Fu", "平板谨慎的男声,账房,字斟句酌,被追问时渐慌", "灯?……许是我记岔了。人上了岁数,记性不济。"),
("z_react_2", "Uncle_Fu", "平板谨慎的男声,账房,字斟句酌,被追问时渐慌", "钥匙的事……他、他有时候,也贴身带着的……"),
("z_react_3", "Uncle_Fu", "平板谨慎的男声,账房,字斟句酌,被追问时渐慌", "秤!秤的事,你们别再问了……"),
("z_react_4", "Uncle_Fu", "平板谨慎的男声,账房,字斟句酌,被追问时渐慌", "……随你们怎么问。我要回去了。"),
("acc_zhou", "Uncle_Fu", "平板谨慎的男声,账房,字斟句酌,被追问时渐慌", "我十点就到家了!我家婆娘能作证!"),
("z_break_1", "Uncle_Fu", "平板谨慎的男声,账房,字斟句酌,被追问时渐慌", "别念了……我说。库房短的三件货,是我抵了赌债。"),
("z_break_2", "Uncle_Fu", "平板谨慎的男声,账房,字斟句酌,被追问时渐慌", "他说月底清账,要报官。我求他,他不肯。"),
("z_break_3", "Uncle_Fu", "平板谨慎的男声,账房,字斟句酌,被追问时渐慌", "我只想把钥匙放回去,把被盗做真。抡起秤砣的时候,他认出了我。"),
("b_zhou_1", "Uncle_Fu", "平板谨慎的男声,账房,字斟句酌,被追问时渐慌", "我对完账就回家了,夜里雨大,路上没停。"),
("b_zhou_2", "Uncle_Fu", "平板谨慎的男声,账房,字斟句酌,被追问时渐慌", "钥匙?平时就挂在柴房铜钩上,十年了。"),
("b_zhou_3", "Uncle_Fu", "平板谨慎的男声,账房,字斟句酌,被追问时渐慌", "柴房我常去,没什么不对劲的。"),
# 温太太(50 岁房东,Vivian)
("wen_1", "Vivian", "快嘴泼辣的中年女声,房东太太,嗓门亮,热心肠", "雨是九点四十下的。我正收晾的衣裳,记得真真的。"),
("wen_2", "Vivian", "快嘴泼辣的中年女声,房东太太,嗓门亮,热心肠", "十点二十,我出门倒垃圾。聚宝斋店堂的灯,亮着呢。"),
("wen_3", "Vivian", "快嘴泼辣的中年女声,房东太太,嗓门亮,热心肠", "刚回屋,柴房后墙咯噔一响,有人爬墙!花盆翻了一个。"),
("wen_4", "Vivian", "快嘴泼辣的中年女声,房东太太,嗓门亮,热心肠", "吓得我蒙头半宿没睡着,天亮才敢吱声。"),
("wen_5", "Vivian", "快嘴泼辣的中年女声,房东太太,嗓门亮,热心肠", "店里短银子的事,街坊都有耳闻。上礼拜他还摔了账本。"),
("wen_6", "Vivian", "快嘴泼辣的中年女声,房东太太,嗓门亮,热心肠", "周账房那人,见人三分笑,账算得比谁都精。"),
("acc_wen", "Vivian", "快嘴泼辣的中年女声,房东太太,嗓门亮,热心肠", "我这把年纪翻墙?先问问那墙答不答应!"),
# 秦法医(Serena——与 female 旁白同 speaker,靠签名+报告语境区分)
("fo_1", "Serena", "冷静干练的女声,验尸官,临床腔,短句平直", "验尸报告,念给你听。"),
("fo_2", "Serena", "冷静干练的女声,验尸官,临床腔,短句平直", "死亡时间,昨夜十点到十点半。"),
("fo_3", "Serena", "冷静干练的女声,验尸官,临床腔,短句平直", "后脑单次钝器伤,一击毙命。创口嵌有铜屑,凶器是铜器。"),
("fo_4", "Serena", "冷静干练的女声,验尸官,临床腔,短句平直", "死者双手干净,没有搏斗痕迹。"),
("fo_5", "Serena", "冷静干练的女声,验尸官,临床腔,短句平直", "鞋底是干的。当夜,死者没出过后门。"),
]
NPCS = {"rpg": RPG_NPC, "radio": RADIO_NPC, "abyss": ABYSS_NPC, "detective": DETECTIVE_NPC}
# ---------------------------------------------------------------- 键盘变体(P1 路线 a)
# 「生效输入模式=键盘」的玩家听按键措辞:向左滑→按左方向键(四向同理,WASD 不进
@@ -1092,6 +1453,34 @@ KEY_LINES = {
("gd_turn", "轮到你了。按空格挥击。"),
("settle_again", "按空格,再探一次。"),
],
# abyss:11 对(17-abyss-voice-ids.md §G0.a 9 对 + §D1 dv1_teach/p1;措辞「左箭头/右箭头」
# 「上箭头/下箭头」为文档原文,与 dungeon 的「左方向键」系两文档各自定稿措辞,不改写)。
"abyss": [
("gd_brief", "按空格继续简报。要选择时,用左右方向键。"),
("gd_continue", "按空格,继续。"),
("gd_again", "还在吗?按空格继续。"),
("gd_ping1", "声呐待命。按空格,发脉冲。"),
("gd_ping2", "回波不会自己来。按空格。"),
("sys_help", "空格继续,回车重新听。上箭头听状态,下箭头开菜单。选择时,左右箭头。"),
("sys_menu", "菜单。空格切换选项,回车确认。"),
("sys_skip", "想跳过这句,按空格。"),
("sys_continue_ask", "检测到你的下潜记录。空格继续上次,右箭头开始新救援。"),
("dv1_teach", "到深度了。声呐静了。按空格,发一枚脉冲。"),
("p1", "管路在响。左箭头,停下来听敲管的暗号。右箭头,先带小舟上浮。"),
],
# detective:V 组 10 对(18-detective-voice-ids.md 文末;_k 逻辑 id 落 key/ 子目录)。
"detective": [
("sys_help", "方向键换卷宗,空格听取,回车重新听。按住空格指证,上键状态,下键菜单。"),
("tut_d0", "先熟悉证词板。左右方向键,换卷宗。"),
("tut_listen", "空格,听取当前卷宗。"),
("tut_replay", "回车,重新听这一句。"),
("tut_confront", "按住空格,进入指证。"),
("gd_board", "还在证词板。左右方向键,换卷宗。"),
("gd_cf", "还在选证词。左右方向键,空格确认。"),
("cf_pick_line", "左右方向键,一句一句听。"),
("cf_confirm", "就这句?空格,定下来。"),
("settle_hook", "同一场雨里,还有别的案子。按空格,接新案。"),
],
}
@@ -1121,6 +1510,12 @@ VOICE_SPK = {"radio": {}}
VOICE_SPK["radio"].update({fid: ("Uncle_Fu", "Serena") for fid, _i, _t in RADIO_HOST_LINES})
VOICE_SPK["radio"].update({fid: ("Dylan", "Vivian") for fid, _i, _t in RADIO_PROD_LINES})
# abyss 双性别行的逐句 speaker 覆盖(DIVER=潜航员玩家 / DECK=母船调度,17b 录制说明:
# female 侧玩家 Serena/调度 Vivian、male 侧玩家 Uncle_Fu/调度 Dylan,同场景永不同 speaker)。
VOICE_SPK["abyss"] = {}
VOICE_SPK["abyss"].update({fid: ("Uncle_Fu", "Serena") for fid, _i, _t in ABYSS_DIVER_LINES})
VOICE_SPK["abyss"].update({fid: ("Dylan", "Vivian") for fid, _i, _t in ABYSS_DECK_LINES})
# radio 来电者电话滤波(15-radio.md §6.2,全部 + 轻压缩):按 NPC id 前缀分档,
# convert 转码时应用;staging wav 保留未滤波原声以便重滤/回退(宁窄勿脏)。
NPC_BANDPASS = {
@@ -1130,7 +1525,16 @@ NPC_BANDPASS = {
("k1_", "highpass=f=450,lowpass=f=3000"), # 糖糖:家用座机,小而近
("w1_", "highpass=f=420,lowpass=f=3100"), # 陈姐:户外手机,风噪
("h1_", "highpass=f=300,lowpass=f=3400"), # 老韩:车载蓝牙,宽而轰
]
],
# abyss 船员水声电台滤波(17-abyss.md §5.3/17b 头注,全部 + 轻压缩):
# 「电台里的人」与「耳机里的人」靠音质差立住;d1_log 是小舟(z1_ 前缀外单独登记)。
"abyss": [
("z1_", "highpass=f=420,lowpass=f=3200"), # 小舟:年轻女声,窄带
("d1_log", "highpass=f=420,lowpass=f=3200"),
("bai_", "highpass=f=350,lowpass=f=3000"), # 老白:沙哑中年男,中窄带
("chen_", "highpass=f=400,lowpass=f=3100"), # 陈医官:平静女声
("gao_", "highpass=f=300,lowpass=f=2800"), # 高船长:苍老男声,最低最窄
],
}
_NPC_ACOMP = "acompressor=threshold=-20dB:ratio=3:attack=10:release=150" # 轻压缩(全档)
@@ -1152,6 +1556,8 @@ GAMES = {
"rpg": RPG_LINES,
"radio": RADIO_LINES,
"dungeon": DUNGEON_LINES,
"abyss": ABYSS_LINES,
"detective": DETECTIVE_LINES,
}
+29
View File
@@ -144,3 +144,32 @@ boss=候选 0(149.5s,choice 158552331321345)。
radio onair/bridge/ending 与 dungeon 4 首按各设计文档用 I=-20(成品 mean -20.4 ~ -21.3dB)。
本作无节奏关键曲目(dungeon battle/boss 的 bpm 仅为特征词,不做节拍网格同步),未跑 bpm_precise。
flac 原件存 tools/mureka_out/{radio,dungeon}-*/。
## 2026-09-09 批次 2:abyss《深海回音》+ detective《雨夜专案》BGM(7 首)
预算线:本轮 $0.30(abyss 4 + detective 3 × $0.03);总预算 $2.00。后处理脚本入库:
`web/abyss/gen/gen_bgm.sh` / `web/detective/gen/gen_bgm.sh`(首个强 onset 起点 → 93s 裁剪 +
首尾 3s acrossfade(tri) 无缝循环 → loudnorm → 44.1kHz → ogg q:a 3 + m4a 128k,成品均 90.00s)。
| # | task id | 用途 | 状态 | 花费 |
|---|---|---|---|---|
| 30 | 160001236664321 | abyss bgm/deck(2 候选) | succeeded | $0.03 |
| 31 | 160001429798913 | abyss bgm/dive(2 候选) | succeeded | $0.03 |
| 32 | 160001576402945 | abyss bgm/comms(2 候选) | succeeded | $0.03 |
| 33 | 160001717043203 | abyss bgm/ending(2 候选) | succeeded | $0.03 |
| 34 | 160001918435329 | detective bgm/menu(2 候选) | succeeded | $0.03 |
| 35 | 160002065039361 | detective bgm/board(2 候选) | succeeded | $0.03 |
| 36 | 160002209873922 | detective bgm/verdict(2 候选) | succeeded | $0.03 |
**本轮花费:$0.21 / $0.30。累计:$1.08 / $2.00。** 7 首全部一次成功无重试。
选用(拿不准选时长更接近 90s 的候选):abyss deck=候选 0(192.1s,choice 160001381367809);
dive=候选 0(179.8s,choice 160001536622595);comms=候选 1(168.7s,choice 160001689714693);
ending=候选 0(191.4s,choice 160001815478273);detective menu=候选 1(219.8s);
board=候选 0(216.8s);verdict=候选 1(223.7s)。
响度:abyss 4 首与 detective 3 首全部 I=-20(17-abyss.md §5.1 未设独立 menu 曲——MENU 复用
deck 低响度淡入由游戏层控制;18-detective.md §8.1 明确 3 首 -20 LUFS)。成品 mean:
abyss -20.5 ~ -21.9dB;detective -20.2 ~ -21.7dB,与在库 BGM 同量级。
雨声底按 18 号文档烤进 detective 曲目(省第三声流)。无节奏关键曲目,未跑 bpm_precise。
flac 原件存 tools/mureka_out/{abyss,detective}-*/。