Files
SoundGame/research/new8/batch1-assets-report.md
xsl 24c526af68 feat(assets): SA3 音效补齐 radio 11+1 与 dungeon 13源+15pan(token 走 hf-mirror 实测可用)
- 模型 17/17 文件经镜像全量缓存(gated+token,直连本机不通;sfx.md/setup.md/asset-pipeline.md 镜像结论同步更新)
- 修复迁移遗留:stable_audio_3/models/ 源码子包被 .gitignore models/ 规则误伤丢失,从上游恢复并加白名单
- radio:arg_muffled/brake_screech 等叙事件落地(接线原有 L111/L154 零改动)+ phone_ring SYN→SA3 升级;dungeon 13 源 A/B 对齐(RMS 偏差 ≤0.3dB)全量同名替换,SYN 原版备份 tools/asset_fix_backup/sa3_ab_20260902/
- 关键玩法语义达标:echo 距离档 0.83<1.43<2.18<2.98s 严格递增;one-shot 真峰值全 ≤-3dBFS(解码回读法)
- check_all_assets 8 游戏全绿(radio 254/254、dungeon 303/303);playtest radio 221/dungeon 1610 全绿
2026-09-02 19:35:38 +08:00

16 KiB
Raw Permalink Blame History

批次 1 资产报告:radio《不眠频率》+ dungeon《回声地窟》

音频资产管线 agent 产出 · 2026-09-02 · 覆盖任务书 A(语音)/ B(BGM)/ C(音效)/ D(收尾)。 总耗时 ≈ 35 分钟(00:47–01:21,含 2 轮 GPU TTS 串行、8 个 Mureka 任务、全部 QC 与文档)。

1. 语音(TTS,GPU flock 串行)

项 radio dungeon
台词句数 132(双性别 103 + NPC 平铺 29) 125(×2 性别,无 NPC)
生成文件 103×2 + 29 = 235 条 ×2 格式 = 470 文件 250 条 ×2 格式 = 500 文件
speaker HOST=Uncle_Fu/Serena,PROD=Dylan/Vivian(VOICE_SPK 逐句覆盖,同性别双音色) 全表 Uncle_Fu/Serena,单一 instruct 常量
--check ALL OK(无时长离群/短句) ALL OK
  • 台词表进入 tools/gen_voice_dual.py(新增 radio/dungeon),由一次性提取脚本直接解析两份 voice-ids 设计文档生成,并做了二次闭环校验(重解析文档 vs 脚本内表格逐字 diff)——台词全文与文档一字不差。
  • NPC 平铺按 rpg 先例写入 NPCS["radio"](id, speaker, instruct, 台词),staging 走 <game>/npc/,convert 落 web/radio/audio/voice/<id>.*。
  • extract_voice_text.py 已刷新 web/harness/voice_text.json:games=8,radio 132 条、dungeon 125 条。
  • 文档内矛盾检查:无重复 id、无超 40 字(汉字口径,与文档自查注记一致;p7/p9 含标点 41/43 字,走章程 §3.4 自动拆句机制,0.12s 句间停顿)。发现一处文档头部账目笔误(不影响管线,未改文档):15-radio-voice-ids.md 头注「HOST 21 + PROD 82」与逐行表不符,逐行表实数 HOST 29 + PROD 74(总数 103 一致)。
  • radio 电话音质感(资产侧带通,15-radio.md §6.2):convert 转码时按来电者逐档 highpass+lowpass+轻压缩(老周 500-2800 / 小鹿 400-3400 / 糖糖 450-3000 / 陈姐 420-3100 / 老韩 300-3400 Hz,均 acompressor threshold=-20dB ratio=3 attack=10 release=150);已验证滤波生效(NPC 高频带能量 ≈ 未滤波 HOST 的 1/4,时长与 staging 完全一致);ogg+m4a 双格式均从同一滤波链转出。未滤波原声保留在 tools/gen_voice_dual_wav/radio/npc/(不入库)。

2. BGM(Mureka API)

8 首全部一次成功,无重试;总花费 $0.24(预算 $0.30 内,台账见 tools/mureka_log.md 2026-09-01 节,项目累计 $0.87/$2.00)。

曲目 task id 选用 choice 候选时长 响度目标
radio onair 158551062544386 158551165370369 135.5/201.2s -20 LUFS
radio bridge 158551207313409 158551341465604 211.2/225.1s -20 LUFS
radio menu 158551383277574 158551500914690 188.6/222.0s -24 LUFS(menu pad,10 文档 §1.2)
radio ending 158551538401281 158551630872578 202.0/189.2s -20 LUFS
dungeon menu 158551678976001 158551817322499 162.8/177.8s -20 LUFS(16-dungeon.md §9.1)
dungeon explore 158551855333377 158551978868739 177.0/209.8s -20 LUFS
dungeon battle 158552010457089 158552169709569 186.4/225.9s -20 LUFS
dungeon boss 158552209555457 158552331321345 149.5/202.3s -20 LUFS
  • 选用原则:拿不准选时长更接近 90s 的候选(仅 radio ending 选候选 1)。
  • 后处理(脚本入库 web/{radio,dungeon}/gen/gen_bgm.sh,可复现):首个强 onset(silenceremove -35dB)→ 93s 裁剪 → 首尾 3s acrossfade(tri) 无缝循环 → loudnorm(TP=-2/LRA=11)→ 44.1kHz → ogg q3 + m4a 128k。成品全部 90.00s,mean -20.4~-24.7dB,循环接缝差值与在库 BGM 同量级。
  • 无节奏关键曲目,未跑 bpm_precise(dungeon battle/boss 的 bpm 仅为 prompt 特征词)。

3. 音效(SYN 程序合成;SA3 全部跳过)

  • web/radio/gen/gen_sfx.py:ui_confirm ui_menu(storyline 全局先例同款),2 文件 ×2 格式。
  • web/dungeon/gen/gen_sfx.py:19 文件 ×2 格式 = 17 id(pulse、材质尾音 4、预 pan 立体声 side_wall_l/r side_open_l/r(mono 源 + ffmpeg pan 派生,脚本断言极性:能量只在目标声道)、step_own step_turn bump coin potion gear atk_swing parry hurt levelup)。
  • QC(解码回读法,全部通过):逐声道真峰值 ≤ -3dBFS(修复:硬 pan 立体声不能按声道均值测,否则漏检超限;AAC/MDCT 过冲按实测迭代补 volume);|直流| ≤ 0.001(与在库 91 件 sfx 基线一致;修复:源去直流 + 8ms cos² 淡入淡出 + 前后垫 60/120ms 静音 + highpass=f=30 抑制编解码直流再生);无首尾爆豆。最终 42 文件全绿。
  • 可复现:两个 gen 脚本入库,一键重出全部 ogg+m4a;staging(web/<game>/gen/staging/、tools/bgm_post_wav/)已加入 .gitignore 不入库。

4. 缺失资产清单(SA3 待 HF token,本轮全部跳过、未尝试生成)

已于 2026-09-02 晚全部补产闭环,见本文档 §8(amb_studio 产出备用未接线;dungeon 28 文件 为 A/B 替换而非纯缺失——批次 2 曾以 SYN 兜底,见 web/dungeon/gen/gen_sfx2.py)。

radio(13 件):onair_sting phone_ring line_connect line_drop amb_studio amb_rain_city amb_station amb_kid_room arg_muffled amb_street_rain amb_cab brake_screech tape_static(15-radio.md §5.2;prompt 草稿在表内,token 就绪后按 gen_rpg_sfx.sh 工艺补产)。

dungeon(24 文件 = 13 个 SA3 源 + 11 个 pan 派生):echo_1 echo_2 echo_3 echo_4 stairs_down atk_hit enemy_die mob_step_small mob_step_bug mob_step_heavy(+各 l/c/r 三份派生)tel_small tel_bug tel_heavy(+各 l/r 派生)(16-dungeon.md §9.2;mono 源 → stereotools/pan 派生工艺同表注)。

SA3 缺失影响评估:radio 的 amb/线索音缺失时游戏层按「资产缺失回退路径」静默降级(设计 §9 断言已有屏蔽资产的兜底断言);dungeon 回声/脚步是核心动词,开发联调前建议先补产 dungeon 的 SA3 条目(或临时用 SYN 兜底:side_* 已有 SYN 版,echo/mat 可参考 §9.2 降级条款程序合成)。

5. check_all_assets 结果(radio/dungeon 已入 GAMES 列表)

| 游戏 | ogg | m4a | 0字节 | 解码失败 | voice male/female id 一致 |
| radio   | 241 | 241 | 0 | 0 | ✅ 各 103(平铺 29 个角色/NPC 句,豁免) |
| dungeon | 273 | 273 | 0 | 0 | ✅ 各 125 |
结论:全部通过(8 游戏全绿,exit=0)

radio ogg 构成 = 103+103 双性别 + 29 平铺 NPC + 2 sfx + 4 bgm;dungeon = 125+125 + 19 sfx + 4 bgm。

6. 遗留问题 / 待办

  1. SA3 token:环境未配置(env.d/sfx.sh 无有效 HF token),radio 13 + dungeon 24 件 sfx 待补产(清单见 §4,prompt 均已在设计文档定稿)。 已闭环(2026-09-02 §8)。
  2. 人工试听两处:① radio NPC 带通句可读性抽检(不可读回退未滤波原声,staging 重转即可,管线已支持);② 多音字风险句(15-radio-voice-ids.md 文末注记:h1_dango「嘶」、k1_lullo、d9_face 等;16b:btl_bat「蝠」、unlock_potion「行囊」)。
  3. 文档笔误待策划改:15-radio-voice-ids.md 头注「HOST 21 + PROD 82」应为「HOST 29 + PROD 74」(总数 103 不变,不影响任何资产)。
  4. radio 无「大姐/姑娘」自称合规、gd_* 两级不同句等台词侧设计约束均已在表内落实,开发接线时按 §7.2 看门狗表取用即可。
  5. 红线遵守:GPU 全程 flock 串行(radio → dungeon 两轮,无并行);Mureka $0.24 ≤ $0.30 且每笔记账;未改 web/engine/、未写任何 game.js/index.html/test;key 未入任何入库文件(mureka.sh 本就被 gitignore)。

7. 产出物索引

类型 路径
台词表(入库) tools/gen_voice_dual.py(radio/dungeon 表 + SPEAKERS + VOICE_SPK + NPC_BANDPASS)
voice 成品 web/{radio,dungeon}/audio/voice/{male,female}/(+ radio 平铺 voice/<id>.*)
bgm 成品 + 脚本 web/{radio,dungeon}/audio/bgm/;web/{radio,dungeon}/gen/gen_bgm.sh
sfx 成品 + 脚本 web/{radio,dungeon}/audio/sfx/;web/{radio,dungeon}/gen/gen_sfx.py
期望文本映射 web/harness/voice_text.json(games=8)
台账/总账 tools/mureka_log.md(2026-09-01 节);docs/audio/asset-manifest.md(radio/dungeon 章节)
staging(不入库) tools/gen_voice_dual_wav/{radio,dungeon}/、web/<game>/gen/staging/、tools/bgm_post_wav/、tools/mureka_out/

8. SA3 补产(2026-09-02 晚,HF token 就绪后;§4 缺失清单闭环)

总耗时 ≈ 40 分钟(18:57–19:38,3 轮 GPU flock 串行生成 + 全部 QC/A-B/文档)。 模型 stabilityai/stable-audio-3-small-sfx 17 文件经 hf-mirror(gated+token)全量下载成功, 落 models/hf/hub/models--stabilityai--stable-audio-3-small-sfx/。生成参数:--steps 8 --seed 20260902, 3 轮 CLI 批量(radio 12 + dungeon 13 + amb_studio 1),原始 wav 在 web/<game>/gen/staging/sfx_sa3/(不入库)。

环境修复(重要,机器迁移遗留):tools/stable-audio-3/.gitignore 的 models/ 规则误伤了 源码子包 stable_audio_3/models/(factory.py 的依赖,初迁时未入库而丢失,import 直接报 ModuleNotFoundError)。已从上游 GitHub(经 ghfast.top 代理,本机直连 GitHub 不通)恢复该子包, 并在 .gitignore 追加 !stable_audio_3/models/ 防复发。CLI 需 source env.d/sfx.sh (HF_TOKEN/HF_ENDPOINT),模型已在缓存时加 HF_HUB_OFFLINE=1 免网络。

工艺(入库脚本 web/{radio,dungeon}/gen/gen_sfx_sa3.py,含 --emit 打印生成命令): SA3 输出为定长 latent 床(radio raw 16.16s / dungeon raw 10.59s,与请求时长无关),按实测事件 窗截取(arg_muffled 摔门峰 @5.00s、brake_screech 最强吱咬 @3.91s、tape_static 停带 @3.72s, 窗切点 50ms 缓出);one-shot 去直流 + 8ms cos² 淡化 + 峰值定档;amb 床只去直流不淡化 (游戏层 0.4s 重触发重叠掩接缝),RMS −26dBFS 定档 + 峰值帽 −8(escape amb 床先例); dungeon 候选按在役 SYN 版解码 RMS 同口径对齐(保混音参数,峰值帽 −4 不变;垫后计算避免稀释偏差; 派生 l/r/c 从对齐后基准复制,与 SYN 派生逐声道振幅一致)。编码 ogg q4 + m4a 128k (hp30 + 垫 60/120ms),解码回读 QC 全过:逐声道真峰值 ≤ −3dBFS、|直流| ≤ 0.001、 超限降增益 + 首轮重编 18kHz 低通(本轮无一触发补偿);phone_ring 另验循环边界 ≤ −60dBFS。

8a. radio(13 件 = 缺失 11 + phone_ring 替换 + amb_studio 备用;11+替换件已接线)

id 时长s ogg峰dBFS m4a峰dBFS RMS 结论
onair_sting 2.14 −4.10 −4.14 −19.0 补产落地(台标 sting,k1 前 INTRO 已接线)
phone_ring 5.20 −4.00 −3.76 −30.5 替换 SYN(A/B:真电话铃双击响明显更优;循环周期 5.2s 烘进文件、边界静音 ≤−60dBFS,游戏侧 _ringSrc loop 接口零改动,原 SYN 备份在 tools/asset_fix_backup/sa3_ab_20260902/radio/)
line_connect 0.78 −7.30 −7.11 −33.6 补产落地(接听咔哒,subtle 档 −7)
line_drop 2.23 −7.27 −7.51 −31.1 补产落地(挂断+忙音)
amb_rain_city 16.16 −8.77 −8.58 −26.2 补产落地(C1 老周侧 amb 床)
amb_station 16.16 −7.66 −7.73 −34.3 补产落地(C2 小鹿侧;峰值帽导致偏静,深夜车站符合设计)
amb_kid_room 16.16 −10.52 −10.70 −37.2 补产落地(C3 糖糖侧;刻意安静,反衬 arg_muffled 线索)
arg_muffled 4.58 −8.44 −8.74 −33.9 补产落地(C3 埋线索:k1_b 已接线 ×2 播,事件窗含摔门 @raw 5.0s)
amb_street_rain 16.16 −8.14 −7.76 −27.2 补产落地(C4 陈姐侧)
amb_cab 16.16 −11.31 −11.20 −26.4 补产落地(C5 老韩侧,引擎+雨刷)
brake_screech 2.38 −4.75 −5.01 −22.9 补产落地(C5 危机拍:h1_danger 已接线 preMs=2000 前置,最强吱咬事件窗 2.2s)
tape_static 3.53 −5.70 −5.40 −33.4 补产落地(p9 直面留言机电流)
amb_studio 10.00 −14.56 −14.59 −27.1 备用(文档 §5.2 有、game.js 未接线——直播间底噪由 bgm/onair 承担;不改代码)

8b. dungeon(28 文件 = 13 SA3 源 + 15 pan 派生,全部同名替换在役 SYN 兜底)

源 id SA3 时长s (SYN) ogg峰 (SYN峰) SA3 RMS (SYN RMS) 结论
echo_1 0.83 (0.58) −11.1 (−5.5) −28.4 (−28.3) 替换;距离档递增校验通过 0.83<1.43<2.18<2.98
echo_2 1.43 (1.08) −4.3 (−4.4) −29.7 (−27.3) 替换(峰值型瞬态,RMS 对齐受峰值帽 −1~2dB 内)
echo_3 2.18 (1.68) −14.0 (−4.2) −28.5 (−28.4) 替换
echo_4 2.98 (2.38) −14.1 (−4.2) −26.9 (−26.2) 替换
stairs_down 3.72 (1.88) −4.0 (−4.6) −25.1 (−24.1) 替换(真实下行金属梯+窟内混响)
atk_hit 0.87 (0.48) −4.5 (−4.6) −25.8 (−21.4) 替换(甲壳钝响峰值对齐,RMS −4.4dB 为峰值帽所致)
enemy_die 1.88 (1.08) −3.6 (−4.0) −21.5 (−19.8) 替换
mob_step_small 0.63 (0.42) −7.2 (−4.4) −27.1 (−27.0) 替换(+_l/_c/_r 派生 3 文件)
mob_step_bug 0.73 (0.48) −4.3 (−3.7) −22.6 (−20.7) 替换(+派生 3;虫肢咔嗒质感)
mob_step_heavy 0.83 (0.58) −4.4 (−4.3) −22.6 (−20.8) 替换(+派生 3)
tel_small 1.18 (0.78) −3.5 (−3.6) −19.5 (−17.6) 替换(+_l/_r 派生 2)
tel_bug 1.28 (0.78) −5.3 (−4.7) −23.1 (−23.0) 替换(+派生 2)
tel_heavy 1.48 (1.08) −3.5 (−4.3) −17.4 (−12.9) 替换(+派生 2;SYN 低吼 RMS −12.9 受峰值帽只对齐到 −17.4,峰值 −3.5 保留冲击力)

A/B 结论(默认「质量明显更好才替换」):13 源全部替换。依据:① 真实声源质感(石壁反射/ 虫甲/金属梯)对合成正弦+噪声团,听感代差明确,且 16-dungeon.md §9.2 本就以 SA3 为正选、SYN 仅为 无 token 兜底(gen_sfx2.py 头注「日后补产 SA3 版,直接覆盖同名文件」);② 语义可测项全部达标—— echo 距离档时长/暗度严格递增(回声尾长=墙距是核心玩法信息)、脚步/前摇/命中时长落在玩法窗口 (mob_step ≤0.83s、tel 1.18-1.48s、atk_hit 0.87s)、响度按在役 SYN 解码 RMS 对齐(混音零改动)。 SYN 版全部备份于 tools/asset_fix_backup/sa3_ab_20260902/dungeon/,可一键回退。

8c. 终检与回归

  • tools/check_all_assets.py:8 游戏全绿——radio 254/254(235 voice + 15 sfx + 4 bgm)、 dungeon 303/303(250 voice + 49 sfx + 4 bgm),0 字节/解码失败/配对缺失均为 0。
  • web/radio/test/playtest.mjs:221 断言全绿(未改任何代码;静态审计「sfx 缺失」变 0—— STABLE_AUDIO_PENDING 清单闭环;arg_muffled ×2 / brake_screech 前置 2s 触发断言原本就有)。
  • web/dungeon/test/playtest.mjs:1610 断言全绿(同名替换游戏层零改动)。
  • 接线复核:arg_muffled=game.js L111(k1_b sfx + sfxEcho atMs 6500)、brake_screech=L154 (h1_danger danger:true, preMs:2000, sfx),R1 报告属实,本轮零代码改动。
  • key/token 未入任何入库文件;GPU 全程 flock 串行(3 轮);未动 web/engine/、web/harness/live/**、 8123/8124/8001 服务。