Files
Genarrative/docs/technical/PUZZLE_MATCH3D_RESULT_AUDIO_TAB_2026-05-11.md
2026-05-13 00:28:07 +08:00

6.8 KiB
Raw Blame History

拼图与抓大鹅结果页音乐入口 2026-05-11

1. 范围

本方案把 VectorEngine 音频生成能力从视觉小说结果页扩展到拼图与抓大鹅结果页:

  1. 拼图结果页新增 音乐 Tab支持通过 Suno 生成作品背景音乐。
  2. 抓大鹅结果页在 素材配置 > 背景音乐 中支持通过 Suno 生成作品背景音乐;旧一级 音乐 Tab 已删除。
  3. 抓大鹅 素材配置 > 物品 支持为每个生成物体通过 Vidu 生成点击音效。
  4. 拼图运行态与抓大鹅运行态内置默认关卡音频配置:通用点击音效 /audio/ui-click-soft.wav、过关音效 /audio/ui-level-clear.wav、倒计时临界音效 /audio/ui-countdown-warning.wav
  5. 拼图和抓大鹅草稿生成阶段会自动生成背景音乐并转存 OSS结果页继续支持试听和重新生成。

本轮不新增 SpacetimeDB 表,不修改表字段,不把供应商密钥下发到前端。

2. 通用音频接口

后端在既有视觉小说音频路由外新增通用创作音频路由:

方法 路由 用途
POST /api/creation/audio/background-music 提交 Suno 背景音乐任务
POST /api/creation/audio/background-music/{task_id}/asset 查询并转存 Suno 音频资产
POST /api/creation/audio/sound-effect 提交 Vidu 音效任务
POST /api/creation/audio/sound-effect/{task_id}/asset 查询并转存 Vidu 音效资产

通用转存请求由前端传入 entityKindentityIdslotassetKindprofileId。后端仍负责:

  1. 校验 VectorEngine 与 OSS 环境变量。
  2. 轮询供应商任务结果。
  3. 下载音频字节。
  4. 写入 OSS 私有对象。
  5. 确认 asset_object 并绑定 asset_entity_binding
  6. 音频真正可下载并准备转存时,按 taskId + assetKind + entityId + slot 幂等扣除 10 光点;任务仍在处理中不扣费,转存或资产绑定失败自动退款。

通用背景音乐提交允许 prompt = ""。拼图和抓大鹅草稿生成都按纯音乐处理:后端提交 Suno 时固定带 make_instrumental = true,只用 titletags 约束作品气质,不把歌词或规则描述写入 prompt。视觉小说原路由保持兼容内部继续复用同一套提交、轮询、转存逻辑。

3. 数据落点

3.1 拼图

拼图作品没有独立作品级 metadata 字段。背景音乐随 levels_json 保存到首个 PuzzleDraftLevel.backgroundMusic

{
  "levelId": "puzzle-level-1",
  "backgroundMusic": {
    "taskId": "suno-task",
    "provider": "vector-engine-suno",
    "assetObjectId": "assetobj_1",
    "assetKind": "puzzle_background_music",
    "audioSrc": "/generated-puzzle-assets/..."
  }
}

草稿生成阶段在生成首关作品题目后,使用作品题目作为 Suno titleprompt 为空,tags 使用轻快、拼图、循环、instrumental。生成失败只记录 warning不阻断草稿进入结果页。运行态从 PuzzleRuntimeLevelSnapshot.backgroundMusic.audioSrc 读取该字段作为背景音乐源,游戏开始后自动循环播放;若字段为空,保持静默背景音乐兜底。

3.2 抓大鹅

抓大鹅作品级音频与物体点击音效复用 generated_item_assets_json 数组保存,不新增表字段:

  1. 作品背景音乐暂存到第一个 Match3DGeneratedItemAsset.backgroundMusic,表示当前 work profile 的作品级背景音乐。
  2. 单个物体点击音效保存到对应 Match3DGeneratedItemAsset.clickSound

这是一个兼容性折中:当前 Match3D work profile 没有 work-level metadata 字段,而 generated_item_assets_json 已经随作品详情、草稿架、运行态入口稳定传递。草稿生成阶段的文本计划在生成物品名称时同步生成 backgroundMusic.title 作为背景音乐名称,backgroundMusic.prompt 固定为空字符串,后端用该名称作为 Suno title 并生成纯音乐。后续若新增正式作品 metadata 表达,应迁移 backgroundMusic 到作品级字段。

4. 前端交互

结果页 UI 保持轻量:

  1. 音乐 Tab 只展示必要输入、生成按钮、状态与音频预览,不展示供应商规则说明。
  2. 生成完成后立即写回本地草稿状态,并触发既有保存链路或专用保存接口。
  3. 抓大鹅每个物体音效生成入口放在对应素材详情面板内,不在列表下方展开大段配置。
  4. 抓大鹅物体音效提示词允许在素材详情面板内编辑;背景音乐只允许在 素材配置 > 背景音乐 编辑曲名和风格,生成请求固定使用空 prompt
  5. 背景音乐和物体音效生成期间都显示进度条,生成完成后展示 audio 控件试听。
  6. 背景音乐重新生成只要求曲名非空;重新生成继续按纯音乐提交,prompt = ""

4.1 运行态默认点击音效

  1. src/services/runtimeAudioFeedback.ts 提供通用关卡音频配置 DEFAULT_RUNTIME_LEVEL_AUDIO_CONFIG,内部缓存 HTMLAudioElement,失败时静默兜底,不阻塞玩法交互。
  2. 拼图点击、按压或拖拽拼块时播放默认通用点击音效,并继续保留既有触觉反馈。
  3. 抓大鹅点击物体时优先播放该物体绑定的 clickSound.audioSrc;若作品没有生成物体点击音效,则回退播放 /audio/ui-click-soft.wav
  4. 拼图关卡 currentLevel.status 首次进入 cleared 时播放默认过关音效;抓大鹅 run status 首次进入 won 时播放默认过关音效。
  5. 拼图使用 displayRemainingMs,抓大鹅使用 timeLeftMs。当剩余时间进入默认阈值 5_000ms 后,每个自然秒桶最多播放一次倒计时音效,归零后停止。
  6. 默认关卡音效跟随现有 musicVolume 设置,不新增独立音量 UI不在运行态界面增加说明文案。
  7. 拼图和抓大鹅运行态背景音乐同样跟随 musicVolume,读取 generated legacy path 时先换签,再交给隐藏 <audio loop preload="auto"> 自动播放;浏览器拒绝自动播放时静默失败,不阻断游戏交互。

5. 验收

建议执行:

npm run check:encoding
npm run test -- src\components\puzzle-result\PuzzleResultView.test.tsx
npm run test -- src\components\match3d-result\Match3DResultView.test.tsx
npm run typecheck
cargo test -p shared-contracts creation_audio --manifest-path server-rs\Cargo.toml
cargo test -p shared-contracts puzzle --manifest-path server-rs\Cargo.toml
cargo test -p shared-contracts match3d --manifest-path server-rs\Cargo.toml
cargo test -p api-server vector_engine_audio_generation --manifest-path server-rs\Cargo.toml
cargo test -p api-server match3d --manifest-path server-rs\Cargo.toml
cargo check -p api-server --manifest-path server-rs\Cargo.toml

真实生成 smoke 需要本地私密环境配置 VECTOR_ENGINE_BASE_URLVECTOR_ENGINE_API_KEY 与 OSS 变量。后端改动后使用 npm run api-server 启动,并确认 /healthz