- name
- MV 智能制作(歌词对齐·Seedance)
- description
- 在已有歌曲与歌词基础上,结合 ASR、文生图/文生视频生成高一致性 MV(首尾帧对齐、可选硬烧字幕)。 使用 Seedream / Seedance 等;须从环境预检按序执行,保障音视频时长一致。
- version
- 1.0.0
- trigger
- MV、音乐视频、歌词对齐、分镜视频、Seedance MV
**必须保障音视频时长一致**
## 工作流总览
本 Skill 负责在已有 `song.mp3 + lyrics.txt` 的前提下,完成:
- ASR 识别与歌词对齐;
- 计算前奏与入口点,避免口型错位;
- **从剧本/歌词中提炼角色 / 动物 / 场景 / 道具等资产设定,并与用户确认细节**(头饰、发型、服装、体型、毛色、场景布局等);
- 分镜设计与时间轴分配(由宿主 Agent 完成),并严格遵守资产一致性和出入场/动作连贯性约束;
- 调用 Seedream 5.0 结合剧本与分镜生成整支 MV 的首帧图(first_frame.png),再调用 Seedance 1.5 Pro 生成分镜视频;
- 拼接生成最终 MV,并支持本地硬编码字幕或通过 VOD 烧录字幕。
> **所有任务必须从 Step 1(环境预检)开始执行,并严格按编号顺序推进,禁止跳步。**
### 流程控制规则(全局约束)
宿主 Agent 在编排本 Skill 时,必须遵守以下**流程控制规则**,作为全局约束:
1. **严格按步骤顺序执行,禁止跳步**
必须按 Step 1 → Step 2 → … → Step 10 的顺序执行,不得跳过、颠倒或并行执行不同步骤的主流程。
2. **环境预检是最高优先级,必须首先执行**
Step 1(P0_PRECHECK)必须在任何其他步骤之前执行;未通过 Step 1 不得进入 Step 2。
3. **任一步骤失败立即停止,报告错误**
任一步骤执行失败时,必须立即停止后续步骤,并向用户或调用方报告错误信息,不得在失败状态下继续执行后续步骤。
4. **每步完成后输出检查点状态**
每步成功完成后,必须输出当前步骤的检查点状态(例如「Step N 已完成,产物 xxx 已就绪」),便于监控与从断点恢复。
### 执行约束(必须遵守)
宿主 Agent 在编排本 Skill 时,除上述流程控制规则外,还须遵守以下硬性约束:
- **阶段顺序不可更改**
- 主链路必须严格按如下顺序执行,不得任意跳过或交换阶段:
- `P0_PRECHECK → M0_AV_SEPARATION → M1_ASR → M2_LYRICS_ALIGN → M3_INTRO_OFFSET → M5_STORYBOARD → M4_IMAGE_REFERENCES → M6_SHOT_VIDEOS → M7_MV_COMPOSE → M8_SUBTITLE_BURN`
- 说明:**先分镜(M5)再参考图(M4)**,参考图(角色三视图、场景图、道具图)须**基于分镜**中的 scene/props/character 生成。
- **参考图与首帧不得混淆**
- 用户放入 `ref_images/` 的图为**参考图**(用于风格/生图参考),**不得**默认作为视频生成的「首帧」(first_frame)。
- 视频接口的 `first_frame_image_url` 仅允许来自:**上一镜的尾帧**(由脚本自动衔接),或分镜中**显式指定**的某图作为该镜头首帧。不得将 `ref_images/` 下路径自动写入分镜的 `first_frame_image_url`,除非用户或分镜明确指定该图即为该镜头的首帧。
- **关键依赖不能缺失**
- 未完成前一阶段的必需产物时,禁止进入下一阶段,例如:
- 未生成 `voice.mp3`(且未记录异常降级)不得直接进入 `M1_ASR`;
- 未生成 `asr_corrected.json` 不得进入 `M3_INTRO_OFFSET` / `M5_STORYBOARD`;
- 未生成带 `video_path` 的 `storyboard_updated.json` 不得进入 `M7_MV_COMPOSE`。
- **禁止绕过纠错与对齐**
- 字幕相关流程必须走完「`M1_ASR` → `M2_LYRICS_ALIGN` → 全局对齐修正 → 生成 `lyrics_aligned.srt`」;
- 不得直接使用原始 ASR 文本生成字幕,更不得跳过歌词对齐与全局时间修正步骤。
- **显式状态与日志**
- 推荐在实现中维护显式 `stage` 状态机:只有当前阶段成功完成且产物有效时,才允许迁移到下一阶段;
- 日志与对用户的反馈中必须清晰标注当前阶段(如「当前阶段:M3_INTRO_OFFSET」),便于排查是否存在越级或漏执行。
- **从某阶段重新开始时必须清理后续产物**
- 若用户明确要求从某一阶段重新开始(例如「从 ASR 阶段重新来」「从分镜开始重做」),宿主 Agent **必须先删除该阶段及其之后所有阶段在 `output_dir` 中已产生的文件**,再从该阶段起严格按流程重新执行。
- 各阶段主要产物(便于按阶段清理):
- M0:`voice.mp3`、`background.mp3`、`.demucs_output/`
- M1:`asr_raw.json`、`song_base64.txt`(若有)
- M2:`asr_corrected.json`、`lyrics_aligned.srt`(若有)
- M3:`timing_meta.json`
- M4:`ref_images/`、`character_views/`、`key_scenes/`
- M5:`storyboard.json`
- M6:`storyboard_updated.json`、`*_last.png`、各 `shot_*.mp4`
- M7:`mv.mp4`、`temp_video_silent.mp4`、`shots.txt`
- M8:VOD 侧任务与烧录结果(若在本地有缓存也需一并清理)
- 例如:用户说「从 ASR 重新开始」→ 删除 M1 及之后所列产物(从 `asr_raw.json` 到 M8),保留 M0 产物(`voice.mp3` 等),然后从 M1_ASR 开始执行。
### 显式编号步骤 + 前置依赖声明
以下步骤均带有明确的前置条件与依赖规则,**只有上一步骤全部通过后,才可进入下一步骤**;每步完成后须输出检查点状态。
| 步骤 | 阶段标识 | 前置条件 | 子任务摘要 | 依赖规则 |
| ----------- | ------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
| **Step 1** | P0_PRECHECK | 无 | 检测 Python ≥3.10、uv、`.env` 配置;检测 `song.mp3`、`lyrics.txt` 存在;检测 `output_dir` 可写;可选:ASR/视频服务健康检查 | **只有 Step 1 全部通过后,才进入 Step 2** |
| **Step 2** | M0_AV_SEPARATION | Step 1 通过 | 对人声/背景音分离:运行 `av_separation.py`,得到 `voice.mp3`、`background.mp3` | **只有 Step 2 全部通过后,才进入 Step 3** |
| **Step 3** | M1_ASR | Step 2 通过 | 以 `voice.mp3` 调用 ASR,得到 `asr_raw.json` | **只有 Step 3 全部通过后,才进入 Step 4** |
| **Step 4** | M2_LYRICS_ALIGN | Step 3 通过 | 宿主 Agent 按 ASR 规则逐句逐字纠错,输出 `asr_corrected.json`、`lyrics_aligned.srt` | **只有 Step 4 全部通过后,才进入 Step 5** |
| **Step 5** | M3_INTRO_OFFSET | Step 4 通过 | 宿主 Agent 计算前奏与首句入口,输出 `timing_meta.json` | **只有 Step 5 全部通过后,才进入 Step 6** |
| **Step 6** | M5_STORYBOARD | Step 5 通过 | 宿主 Agent 生成分镜,输出 `storyboard.json`(含 scene/props/character 定义与描述,并在每个分镜的 image_description 中注入已确认的资产细节,如人物头饰/发型/服装、动物体型/毛色、场景结构/灯光等;依赖 asr_corrected、timing_meta、lyrics,不依赖参考图) | **只有 Step 6 全部通过后,才进入 Step 7** |
| **Step 7** | M4_IMAGE_REFERENCES | Step 6 通过 | 基于**整首歌词 / 剧本与分镜草案**设计首帧构图草案(人物/场景/道具/光线等),先与用户确认细节后,再调用 Seedream 5.0 生成首帧图 `first_frame.png` | **只有 Step 7 全部通过后,才进入 Step 8** |
| **Step 8** | M6_SHOT_VIDEOS | Step 7 通过 | 串行调用视频生成,每镜尾帧作为下一镜首帧,输出 `storyboard_updated.json` 及各镜头视频 | **只有 Step 8 全部通过后,才进入 Step 9** |
| **Step 9** | M7_MV_COMPOSE | Step 8 通过 | 拼接分镜视频与歌曲音频,可选硬编码字幕,输出 `mv.mp4` | **只有 Step 9 全部通过后,才进入 Step 10** |
| **Step 10** | M8_SUBTITLE_BURN | Step 9 通过 | 生成时间轴字幕并调用 VOD 烧录(或仅上传带字版视频) | 流程结束;可输出最终播放链接或 vid |
**整体阶段如下:**(注意:参考图在分镜之后生成,基于分镜中的 scene/props/character)
```text
[P0_PRECHECK] 环境 & 依赖 & 输入检测
↓
[M0_AV_SEPARATION] 人声 / 背景音分离(必须在 ASR 之前执行)
↓
[M1_ASR] 基于人声音轨调用 ASR 获取原始字幕(asr_raw.json)
↓
[M2_LYRICS_ALIGN] 基于歌词与语义纠错 ASR 结果(仅宿主 Agent,禁止脚本实现)
↓
[M3_INTRO_OFFSET] 计算前奏 & 歌词入口点(宿主 Agent)
↓
[M5_STORYBOARD] 分镜生成与歌词扩写(宿主 Agent)→ 产出 storyboard.json(含 scene/props/character)
↓
[M4_IMAGE_REFERENCES] 基于分镜生成首帧图
↓
[M6_SHOT_VIDEOS] 调用视频生成(首尾帧 & 风格一致性)
↓
[M7_MV_COMPOSE] 镜头拼接 + 音视频对齐输出 mv.mp4(可选本地硬编码字幕压制:基于 lyrics_aligned.srt 直接烧入视频,推荐使用 `scripts/video_mv_generate.py` 实现)
↓
[M8_SUBTITLE_BURN] 生成时间轴字幕(lyrics_aligned.srt),可继续使用 `scripts/video_mv_generate.py` 输出带字版文件,或调用 VOD 进行线上字幕烧录 / 覆盖式压制
```
执行过程中,宿主 Agent 需要**每步完成后输出检查点状态**并实时向用户汇报当前阶段,例如:
- 「Step 1 已完成:P0_PRECHECK 通过,环境与输入就绪」
- 「Step 3 已完成:M1_ASR 通过,asr_raw.json 已生成」
- 「Step 8 进行中:M6_SHOT_VIDEOS,分镜视频生成中(已完成 8/20 个镜头)」
任一步骤失败时,须**立即停止**并明确报告错误,不得继续执行后续步骤。
---
## P0_PRECHECK:环境 & 依赖 & 输入检测(必须为第一步)
在进入 ASR 或视频生成前,必须先完成以下检查:
- **配置文件检查**
- `scripts/.env` 文件必须存在且可读。
- `.env` 中建议配置:
- `DOUBAO_SPEECH_API_KEY`:大模型 ASR 访问密钥;
- `VIDEO_API_URL`、`ARK_API_KEY`、`VIDEO_MODEL`:视频生成服务(如 Seedance)的访问配置;
- `OUTPUT_ROOT`:统一输出根目录;
- `VIDEO_DEFAULT_RESOLUTION`(如 `720p`)、`VIDEO_DEFAULT_RATIO`(如 `16:9`);
- `VIDEO_STYLE_SEED`:全局风格 seed(用于画面一致性);
- `VIDEO_MODE`:`text_only` / `first_frame` / `first_and_last`。
- **环境 / 依赖安装(使用 uv)**
- 运行环境已安装 `python 3.10+` 与 `uv`;
- 所有依赖应通过 `uv` 在 `scripts/pyproject.toml` 所在目录安装,例如:
```bash
# 在 mv-production/scripts 目录下
uv sync
```
- 运行本 Skill 中的所有脚本时统一使用 `uv run`,例如:
```bash
uv --project scripts run python av_separation.py ...
uv --project scripts run python video_shot_generate.py ...
uv --project scripts run python video_mv_generate.py ...
```
- **环境 / 外部服务初步检查**
- 宿主 Agent 建议在首次调用前做一次轻量「健康检查」,例如:
- 用一个短样本音频调用 ASR,确认服务可达;
- 调用一次 Seedream / Seedance 接口确认网络连通与鉴权正常;
- **输入文件检测**
- 当前任务必须具备:
- `output_dir/song.mp3`:成品歌曲音频(或可下载 URL,需先下载到本地);
- `output_dir/lyrics.txt`:按 ASR 规范清洗后的纯歌词文本(详见 `reference/ASR_字幕生成规则.md`)。
- 若缺少上述任一文件,应提示用户先在 `song-production` 完成歌曲生成,或自行提供音频与歌词。
- **输出目录准备**
- 若配置了 `OUTPUT_ROOT`,本次任务的 `output_dir` 应为:
- `OUTPUT_ROOT/music_output/<歌曲名|6位随机数>/`
- 否则使用相对路径:
- `music_output/<歌曲名|6位随机数>/`
- 宿主 Agent 需确保该目录存在且可写。
通过检查后,宿主 Agent 应向用户说明:
> 当前阶段:P0_PRECHECK 已通过,开始进入 M0_AV_SEPARATION(人声 / 背景音分离),随后进入 M1_ASR(基于人声音轨获取原始字幕)。
---
## M0_AV_SEPARATION:人声 / 背景音分离(**必须在 ASR 之前执行**)
在调用 ASR 前,**必须先对整首歌做一次人声 / 背景音分离**,提取出更干净的「人声轨道」供 ASR 使用,可以显著减轻伴奏和环境声的干扰。
### 输入
- `output_dir/song.mp3`:原始歌曲音频。
### 脚本
本 Skill 在 `scripts/` 提供:
- `scripts/av_separation.py`:基于 Demucs 模型将输入音频拆分为:
- `voice.mp3`:人声;
- `background.mp3`:背景音。
在 `mv-production` 根目录下,典型调用示例为:
```bash
uv --project scripts run python av_separation.py \
output_dir/song.mp3 \
--output-dir output_dir
```
成功后,`output_dir` 中将新增:
- `voice.mp3`
- `background.mp3`
后续 ASR 步骤**必须**使用 `voice.mp3` 作为输入;仅当分离阶段异常失败(如文件缺失/损坏)时,才允许回退继续使用原始 `song.mp3`,并需在日志中明确记录该降级行为。
---
## M1_ASR:基于人声音轨调用 ASR 获取原始字幕(asr_raw.json)
本阶段使用 `scripts/audio_base64.py` 与 `scripts/volcengine_transcribe.py`,将**人声音轨**转为 base64 并提交给火山引擎大模型 ASR 服务。
### 步骤
1. **音频转 base64(严格优先使用人声音轨)**
- 正常流程:**始终使用 `output_dir/voice.mp3`** 作为 ASR 输入;
- 仅当 `voice.mp3` 不存在或明显异常(如 0 字节)时,才退回使用 `output_dir/song.mp3`,并在日志中明确记录已发生降级。
调用示例(假设使用人声音轨):
```bash
uv --project scripts run python audio_base64.py \
output_dir/voice.mp3 \
-o output_dir/song_base64.txt
```
输出:`output_dir/song_base64.txt`,内容为 `data:audio/...;base64,xxxxx`。
2. **提交 ASR 任务并轮询**
```bash
uv --project scripts run python volcengine_transcribe.py \
-f output_dir/song_base64.txt \
-o output_dir/asr_raw.json
```
- `volcengine_transcribe.py` 会:
- 从 `scripts/.env` 读取 `DOUBAO_SPEECH_API_KEY`;
- 向大模型录音识别接口提交任务并轮询结果;
- 在 `output_dir/asr_raw.json` 中写入完整返回,包含 `utterances` 等字段。
原始 ASR 结果结构与字段说明,可参考:
- 根目录下的 `asr使用文档.md`
- `reference/ASR_字幕生成规则.md`
---
## M2_LYRICS_ALIGN:基于歌词纠错 ASR 结果(宿主 Agent)
> **本阶段完全由宿主 Agent 实现,脚本不内置纠错逻辑。**
> **每一句都必须按 `reference/ASR_字幕生成规则.md` 完整执行**:先逐句对齐、再逐字精修,行级 `start_time_ms`/`end_time_ms` 严格取自该行 words 的最小/最大时间,再做全局禁止重叠校正;输出前必须对每一行通过「每行校验清单」,不得对部分行简化或跳过规范。
### 输入
- `output_dir/asr_raw.json`:M1 输出的原始 ASR JSON,含 `utterances`/`words`;
- `output_dir/lyrics.txt`:已清洗的纯歌词文本。
### 目标
宿主 Agent 需按照 `reference/ASR_对齐与纠错流程.md` 与 `reference/ASR_字幕生成规则.md`:
- 对比每行歌词与 ASR 中的 `words.text` 序列;
- 允许少量识别错误(口误/错字),以歌词为权威文本;
- 在不改变整体节奏的前提下,将 ASR 结果「纠错」为歌词版本:
- 为每一行歌词分配精确的 `start_time` / `end_time`;
- 记录原始 ASR 文本,便于调试。
### 输出
宿主 Agent 应在 `output_dir` 写入:
- `asr_corrected.json`,建议结构示例:
```json
{
"lines": [
{
"index": 0,
"lyric": "当年灌江口,我曾是无名少年郎",
"start_time_ms": 76580,
"end_time_ms": 80380,
"raw_text": "当年灌江口,我曾是无名少年郎",
"words": [
{
"text": "当",
"start_time_ms": 76580,
"end_time_ms": 76700
}
]
}
]
}
```
该文件将作为后续前奏判定、分镜时间轴与字幕生成的统一时间基准。
---
## M3_INTRO_OFFSET:计算前奏 & 歌词入口点(宿主 Agent)
### 目标
- 根据 `asr_corrected.json` 中**第一句实际歌词**的 `start_time_ms`,计算前奏时长;
- 确定带人口型的画面应从何时开始,避免前奏阶段出现张口却无声的画面。
### 建议策略
- 找到 `lines` 数组中第一条含非空 `lyric` 的记录,其 `start_time_ms` 记为 `t_lyric_start`;
- 前奏时长 `intro_ms = t_lyric_start`,可根据项目规则限制最大前奏长度(如若过长,可在分镜中拆出多个 intro 镜头)。
宿主 Agent 应将结果写入:
- `output_dir/timing_meta.json`,例如:
```json
{
"intro_ms": 5000,
"first_lyric_index": 0
}
```
View on GitHub