Initial TrueGrowth source import
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
## Context
|
||||
|
||||
当前音频生成链路已经支持:
|
||||
|
||||
- `music` 与 `lyrics` 两类 Suno 提交动作
|
||||
- 统一通过 `/suno/submit/music` 或 `/suno/submit/lyrics` 提交
|
||||
- 统一通过 `/suno/fetch/{task_id}` 轮询
|
||||
- 将音乐结果标准化为 `primaryClipId / clipIds / clips`
|
||||
|
||||
同时,项目已有两个关键前提:
|
||||
|
||||
- 爆款音乐工具倾向使用统一工作流,而不是拆散成多个独立工具
|
||||
- `clip_id` 才是 Suno 续写所需的真实片段标识,不能退化成列表层的 `id`
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
- Goals:
|
||||
- 在统一表单中支持新生成、续写、Infill 三类音乐动作
|
||||
- 根据动作自动约束和显隐 `continue_clip_id / continue_at / infill_start_s / infill_end_s`
|
||||
- 把轮询里发现的 `clip_id` 串到续写和 Infill 请求
|
||||
- 尽量复用现有 `/suno/submit/music` 与轮询标准化逻辑
|
||||
- Non-Goals:
|
||||
- 本次不引入新的独立音乐编辑工具
|
||||
- 本次不实现 clip 拼接 `concat`
|
||||
- 本次不实现音频波形编辑器
|
||||
|
||||
## Decisions
|
||||
|
||||
- Decision: 统一入口 + 动作切换
|
||||
|
||||
- 在 `GeneratePage` 中增加动作枚举,例如 `generate | continue | infill`
|
||||
- 表单仍保持单页结构,但根据动作切换展示不同字段
|
||||
|
||||
- Decision: 参数按动作严格约束
|
||||
|
||||
- `generate`
|
||||
- 使用 `prompt / title / tags / mv`
|
||||
- 不发送 `continue_clip_id / continue_at / infill_start_s / infill_end_s`
|
||||
- `continue`
|
||||
- 必须有 `continue_clip_id`
|
||||
- 必须有 `continue_at`
|
||||
- 可继续使用 `prompt / title / tags / mv`
|
||||
- 不发送 `infill_start_s / infill_end_s`
|
||||
- `infill`
|
||||
- 必须有 `continue_clip_id`
|
||||
- 必须有 `continue_at`
|
||||
- 必须有 `infill_start_s / infill_end_s`
|
||||
- 要求 `infill_start_s < infill_end_s`
|
||||
|
||||
- Decision: 续写目标优先来自已生成片段
|
||||
|
||||
- 每个 `GeneratedClip` 必须稳定保存轮询得到的真实 `clip_id`
|
||||
- 点击片段上的“续写 / Infill”入口时,自动把目标 `clip_id` 带入表单
|
||||
- 若当前任务还没有真实 `clip_id`,则禁止进入续写动作
|
||||
|
||||
- Decision: 仍走同一 Suno submit 接口
|
||||
|
||||
- 三种动作都沿用 `POST /suno/submit/music`
|
||||
- 通过 body 中是否携带 `continue_clip_id / continue_at / infill_start_s / infill_end_s` 决定服务端行为
|
||||
|
||||
## Data Model
|
||||
|
||||
```ts
|
||||
type SunoMusicEditAction = 'generate' | 'continue' | 'infill';
|
||||
|
||||
interface MusicAnalysisRecord {
|
||||
continueFromClipId?: string | null;
|
||||
continueAt?: number | null;
|
||||
infillStartS?: number | null;
|
||||
infillEndS?: number | null;
|
||||
musicEditAction?: SunoMusicEditAction | null;
|
||||
}
|
||||
|
||||
interface AudioGenerationRequest {
|
||||
prompt: string;
|
||||
title?: string;
|
||||
tags?: string;
|
||||
mv?: string;
|
||||
continueClipId?: string;
|
||||
continueAt?: number;
|
||||
params?: {
|
||||
infillStartS?: number | null;
|
||||
infillEndS?: number | null;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## UI Strategy
|
||||
|
||||
- 在“爆款音乐生成 -> 生成”页面增加动作切换区:
|
||||
- `新生成`
|
||||
- `续写`
|
||||
- `Infill`
|
||||
- 在已生成片段卡片上增加快捷入口:
|
||||
- `续写`
|
||||
- `Infill`
|
||||
- 字段展示策略:
|
||||
- `新生成`:标题 / 风格标签 / 歌词 / 版本 / 调用次数
|
||||
- `续写`:目标片段 / 续写起点秒数 / 标题 / 风格标签 / 歌词 / 版本 / 调用次数
|
||||
- `Infill`:目标片段 / 续写起点秒数 / Infill 开始秒数 / Infill 结束秒数 / 标题 / 风格标签 / 歌词 / 版本 / 调用次数
|
||||
- 表单校验失败时,错误提示继续贴近提交按钮
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- 风险:统一表单状态过多,切动作时容易串值
|
||||
- Mitigation:将动作相关字段单独建模,并在切换动作时只保留兼容字段
|
||||
|
||||
- 风险:用户不知道 `continue_at` 与 `infill_start_s/end_s` 的区别
|
||||
- Mitigation:UI 文案明确区分“续写起点”和“局部重绘窗口”
|
||||
|
||||
- 风险:早期轮询返回有 `clip_id`、最终结果缺 `clip_id`
|
||||
- Mitigation:在轮询层缓存并回填真实 `clip_id`
|
||||
|
||||
## Open Questions
|
||||
|
||||
- 是否需要在第一版允许手动输入 `continue_clip_id`,还是只允许从已生成片段选择
|
||||
- 是否要在统一表单中直接支持“续写完成后自动拼接完整音频”,还是留到后续 `concat` 能力再做
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
# Change: 为爆款音乐工具增加统一的续写与 Infill 动作
|
||||
|
||||
## Why
|
||||
|
||||
当前“爆款音乐工具”已经具备:
|
||||
|
||||
- 从零创作歌词
|
||||
- 提交 Suno 音乐生成
|
||||
- 轮询获取音乐生成结果
|
||||
|
||||
但还缺少两类核心后续编辑能力:
|
||||
|
||||
- 基于已生成片段继续续写
|
||||
- 基于已生成片段对局部时间窗口进行 Infill
|
||||
|
||||
而且这些能力依赖一组强约束参数:
|
||||
|
||||
- `continue_clip_id`
|
||||
- `continue_at`
|
||||
- `infill_start_s`
|
||||
- `infill_end_s`
|
||||
|
||||
如果只是把这些字段直接堆进现有“新生成”表单,会产生三个问题:
|
||||
|
||||
- 用户难以理解哪些参数在什么动作下必填
|
||||
- UI 容易形成无效参数组合,例如普通生成时误填续写字段
|
||||
- 续写依赖的 `clip_id` 与展示层 `id` 容易混淆,导致后续调用失败
|
||||
|
||||
因此需要在现有统一入口中,引入显式动作模型,并把参数约束、轮询回填和后续调用链打通。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 在爆款音乐工具的统一入口下新增音乐动作选择:
|
||||
- 新生成
|
||||
- 续写
|
||||
- Infill
|
||||
- 统一沿用现有 Suno `/suno/submit/music` + `/suno/fetch/{task_id}` 链路,不拆分成独立工具
|
||||
- 为 `continue_clip_id / continue_at / infill_start_s / infill_end_s` 建立动作级参数约束与 UI 显隐规则
|
||||
- 将轮询结果中的 `clip_id` 作为续写和 Infill 的真实目标 ID 持久化保存
|
||||
- 在已生成片段区域增加“继续创作”入口,自动带入目标片段与默认参数
|
||||
- 扩展音频请求模型与结果模型,使 unified 表单能安全表达新生成、续写、Infill 三类请求
|
||||
|
||||
## Impact
|
||||
|
||||
- Affected specs:
|
||||
- `audio-generation`
|
||||
- Affected code:
|
||||
- `packages/drawnix/src/components/music-analyzer/pages/GeneratePage.tsx`
|
||||
- `packages/drawnix/src/components/music-analyzer/types.ts`
|
||||
- `packages/drawnix/src/components/music-analyzer/storage.ts`
|
||||
- `packages/drawnix/src/components/music-analyzer/task-sync.ts`
|
||||
- `packages/drawnix/src/services/audio-api-service.ts`
|
||||
- `packages/drawnix/src/services/model-adapters/types.ts`
|
||||
- `packages/drawnix/src/services/model-adapters/default-adapters.ts`
|
||||
- `packages/drawnix/src/services/task-queue-service.ts`
|
||||
- `packages/drawnix/src/mcp/tools/audio-generation.ts`
|
||||
- `packages/drawnix/src/utils/suno-model-aliases.ts`
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Support Unified Suno Music Edit Actions In The Music Analyzer
|
||||
|
||||
The system SHALL expose Suno music generation, continuation, and infill as action variants within one unified music creation flow.
|
||||
|
||||
#### Scenario: User switches from generate to continue in one unified form
|
||||
|
||||
- **GIVEN** the user is editing music in the music analyzer generation page
|
||||
- **WHEN** the user changes the action from `generate` to `continue`
|
||||
- **THEN** the UI SHALL keep the user in the same unified form
|
||||
- **AND** SHALL reveal only the continuation parameters relevant to the selected action
|
||||
|
||||
#### Scenario: User switches from continue to infill in one unified form
|
||||
|
||||
- **GIVEN** the user is editing music in the music analyzer generation page
|
||||
- **WHEN** the user changes the action from `continue` to `infill`
|
||||
- **THEN** the UI SHALL remain in the same unified form
|
||||
- **AND** SHALL reveal `infill_start_s` and `infill_end_s`
|
||||
- **AND** SHALL preserve any compatible shared fields such as `prompt`, `title`, `tags`, and `mv`
|
||||
|
||||
### Requirement: Use clip_id As The Source Of Truth For Continuation Targets
|
||||
|
||||
The system SHALL use the Suno polling result field `clip_id` as the source-of-truth identifier for continuation and infill requests.
|
||||
|
||||
#### Scenario: Polling response discovers continuation clip ids before audio is ready
|
||||
|
||||
- **GIVEN** `/suno/fetch/{task_id}` returns generated items that already include `clip_id`
|
||||
- **WHEN** playable audio URLs are not yet fully available
|
||||
- **THEN** the system SHALL still remember those `clip_id` values
|
||||
- **AND** SHALL reuse them in later normalized results for continuation actions
|
||||
|
||||
#### Scenario: User launches continuation from a generated clip card
|
||||
|
||||
- **GIVEN** the music analyzer displays generated clips
|
||||
- **WHEN** the user chooses to continue or infill a clip
|
||||
- **THEN** the system SHALL use that clip's remembered `clip_id`
|
||||
- **AND** SHALL not substitute the list row `id` in place of `clip_id`
|
||||
|
||||
### Requirement: Scope Suno Music Parameters By Edit Action
|
||||
|
||||
The system SHALL validate and submit Suno music parameters according to the selected unified edit action.
|
||||
|
||||
#### Scenario: Basic generation omits continuation parameters
|
||||
|
||||
- **GIVEN** the selected action is `generate`
|
||||
- **WHEN** the user submits the request
|
||||
- **THEN** the system SHALL send `prompt`, `mv`, `title`, and `tags` when provided
|
||||
- **AND** SHALL omit `continue_clip_id`, `continue_at`, `infill_start_s`, and `infill_end_s`
|
||||
|
||||
#### Scenario: Continuation requires clip id and continue time
|
||||
|
||||
- **GIVEN** the selected action is `continue`
|
||||
- **WHEN** the user submits the request
|
||||
- **THEN** the system SHALL require `continue_clip_id`
|
||||
- **AND** SHALL require `continue_at`
|
||||
- **AND** SHALL submit both fields to `/suno/submit/music`
|
||||
|
||||
#### Scenario: Infill requires continuation anchor and infill window
|
||||
|
||||
- **GIVEN** the selected action is `infill`
|
||||
- **WHEN** the user submits the request
|
||||
- **THEN** the system SHALL require `continue_clip_id`
|
||||
- **AND** SHALL require `continue_at`
|
||||
- **AND** SHALL require `infill_start_s`
|
||||
- **AND** SHALL require `infill_end_s`
|
||||
- **AND** SHALL ensure `infill_start_s` is less than `infill_end_s`
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
## 1. Spec
|
||||
|
||||
- [x] 1.1 补充 unified 动作模型与参数约束说明
|
||||
- [x] 1.2 明确 `clip_id` 作为续写真实标识的保存规则
|
||||
|
||||
## 2. Data And Service
|
||||
|
||||
- [x] 2.1 扩展音频请求类型,支持 `infill_start_s / infill_end_s`
|
||||
- [x] 2.2 扩展音乐记录类型,保存统一动作与续写参数
|
||||
- [x] 2.3 在音频服务中为 `/suno/submit/music` 发送续写与 Infill 参数
|
||||
- [x] 2.4 确保轮询中发现的 `clip_id` 能稳定进入最终结果
|
||||
|
||||
## 3. Music Analyzer UI
|
||||
|
||||
- [x] 3.1 在 `GeneratePage` 增加 `新生成 / 续写 / Infill` 动作切换
|
||||
- [x] 3.2 根据动作展示和校验 `continueAt / infillStartS / infillEndS`
|
||||
- [x] 3.3 在已生成片段卡片上增加“续写 / Infill”快捷入口
|
||||
- [x] 3.4 将所选片段的真实 `clip_id` 自动带入表单
|
||||
|
||||
## 4. Verification
|
||||
|
||||
- [x] 4.1 为音频服务补充续写与 Infill 参数构造测试
|
||||
- [x] 4.2 为 `clip_id` 继承逻辑补充回归测试
|
||||
- [x] 4.3 手工验证统一入口下三种动作的字段显隐与校验
|
||||
Reference in New Issue
Block a user