8.6 KiB
拼图与抓大鹅结果页音乐入口 2026-05-11
1. 范围
本方案把 VectorEngine 音频生成能力从视觉小说结果页扩展到拼图与抓大鹅结果页:
- 拼图结果页在
素材配置 > 背景音乐中支持通过 Suno 生成作品背景音乐;旧一级音乐Tab 已删除。 - 抓大鹅结果页在
素材配置 > 背景音乐中支持通过 Suno 生成作品背景音乐;旧一级音乐Tab 已删除。 - 抓大鹅
素材配置 > 物品支持为每个生成物体通过 Vidu 手动生成点击音效;创作入口不展示点击音效生成开关。 - 拼图运行态与抓大鹅运行态内置默认关卡音频配置:通用点击音效
/audio/ui-click-soft.wav、过关音效/audio/ui-level-clear.wav、倒计时临界音效/audio/ui-countdown-warning.wav。 - 拼图和抓大鹅草稿生成阶段会自动生成背景音乐并转存 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 音效资产 |
通用转存请求由前端传入 entityKind、entityId、slot、assetKind、profileId。后端仍负责:
- 校验 VectorEngine 与 OSS 环境变量。
- 轮询供应商任务结果。
- 下载音频字节。
- 写入 OSS 私有对象。
- 确认
asset_object并绑定asset_entity_binding。 - 音频真正可下载并准备转存时,按
taskId + assetKind + entityId + slot幂等扣费;背景音乐固定扣除5泥点,物品点击音效固定扣除10泥点。任务仍在处理中不扣费,转存或资产绑定失败自动退款。
通用背景音乐提交允许 prompt = ""。拼图和抓大鹅草稿生成都按纯音乐处理:后端提交 Suno 时固定带 make_instrumental = true,只用 title 和 tags 约束作品气质,不把歌词或规则描述写入 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 title,prompt 为空,tags 使用轻快、拼图、循环、instrumental。自动草稿编译必须拿到可播放的 backgroundMusic.audioSrc 后才返回成功;生成失败应返回上游错误并停留在生成页,不能进入结果页后显示“暂无音乐”。运行态从 PuzzleRuntimeLevelSnapshot.backgroundMusic.audioSrc 读取该字段作为背景音乐源,游戏开始后自动循环播放;历史草稿或手动删除音乐时字段为空,则保持静默背景音乐兜底。
3.2 抓大鹅
抓大鹅作品级音频与物体点击音效复用 generated_item_assets_json 数组保存,不新增表字段:
- 作品背景音乐暂存到第一个
Match3DGeneratedItemAsset.backgroundMusic,表示当前 work profile 的作品级背景音乐。 - 单个物体点击音效保存到对应
Match3DGeneratedItemAsset.clickSound。
这是一个兼容性折中:当前 Match3D work profile 没有 work-level metadata 字段,而 generated_item_assets_json 已经随作品详情、草稿架、运行态入口稳定传递。草稿生成阶段的文本计划在生成物品名称时同步生成 backgroundMusic.title 作为背景音乐名称,backgroundMusic.prompt 固定为空字符串,后端用该名称作为 Suno title 并生成纯音乐。自动草稿编译必须把生成后的 backgroundMusic.audioSrc 写回首个素材后才返回成功;若 Suno 提交、轮询、下载、OSS 转存或资产绑定失败,本次草稿生成返回失败并允许用户重试同一 session/profile。后续若新增正式作品 metadata 表达,应迁移 backgroundMusic 到作品级字段。
4. 前端交互
结果页 UI 保持轻量:
- 拼图
素材配置 > 背景音乐与抓大鹅素材配置 > 背景音乐只展示必要输入、生成按钮、状态与音频预览,不展示供应商规则说明。 - 生成完成后立即写回本地草稿状态,并触发既有保存链路或专用保存接口。
- 抓大鹅每个物体音效生成入口放在对应素材详情面板内,不在列表下方展开大段配置。
- 抓大鹅物体音效提示词允许在素材详情面板内编辑;背景音乐只允许在
素材配置 > 背景音乐编辑曲名和风格,生成请求固定使用空prompt。 - 背景音乐和物体音效生成期间都显示进度条,生成完成后展示 audio 控件试听。
- 背景音乐重新生成只要求曲名非空;重新生成继续按纯音乐提交,
prompt = "",按钮展示5泥点成本。
4.1 运行态默认点击音效
src/services/runtimeAudioFeedback.ts提供通用关卡音频配置DEFAULT_RUNTIME_LEVEL_AUDIO_CONFIG,内部缓存HTMLAudioElement,失败时静默兜底,不阻塞玩法交互。- 拼图点击、按压或拖拽拼块时播放默认通用点击音效,并继续保留既有触觉反馈。
- 抓大鹅点击物体时优先播放该物体绑定的
clickSound.audioSrc;若作品没有生成物体点击音效,则回退播放/audio/ui-click-soft.wav。 - 拼图关卡
currentLevel.status首次进入cleared时播放默认过关音效;抓大鹅 runstatus首次进入won时播放默认过关音效。 - 拼图使用
displayRemainingMs,抓大鹅使用timeLeftMs。当剩余时间进入默认阈值5_000ms后,每个自然秒桶最多播放一次倒计时音效,归零后停止。 - 默认关卡音效跟随现有
musicVolume设置,不新增独立音量 UI,不在运行态界面增加说明文案。 - 拼图和抓大鹅运行态背景音乐同样跟随
musicVolume,读取 generated legacy path 时先换签,再交给隐藏<audio loop preload="auto">自动播放;浏览器拒绝自动播放时静默失败,不阻断游戏交互。
4.2 草稿音乐试听与自动播放补充
2026-05-13 修正:
- 拼图
素材配置 > 背景音乐的试听控件也必须通过useResolvedAssetReadUrl对 generated legacy path 换签后再设置<audio src>;签名未就绪或失败时只显示“音频已绑定”,不得把裸/generated-puzzle-assets/...路径交给浏览器请求。 - 抓大鹅结果页已使用同一换签口径,后续新增音频试听入口必须复用该模式。
- 拼图和抓大鹅运行态在开局时会尝试自动播放背景音乐;若浏览器因自动播放策略拒绝,玩家首次按下拼图块或点击抓大鹅物品时必须再次调用同一个背景音乐播放函数,避免草稿音乐已经传入运行态但局内始终无声。
- 播放失败仍只做静默兜底,不弹出规则说明或阻断局内交互。
- 拼图结果页合并后端生成完成回包时,若本地首关仍处于
generationStatus = generating,必须把backgroundMusic与候选图、正式图、UI 背景一起合并进编辑态;否则音乐面板会继续显示“暂无音乐”,后续自动保存还会把空音乐写回 profile。
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_URL、VECTOR_ENGINE_API_KEY 与 OSS 变量。后端改动后使用 npm run api-server 启动,并确认 /healthz。