pipeline-a-song-mv.md 14 KB

产线 A · AI 单曲 MV 完整 SOP

从一句主题到成片,全程零实拍。 本文是「照着敲就能跑」的操作手册,含每步命令、预期产物、避坑点。


零、先确认环境

cd skill-mv
fmode-mv doctor          # node / ffmpeg / 凭据 / 通道
fmode-mv providers       # 能力现状(哪条通道能用)

开工前必须知道:截至 v0.1.0,平台只有 chat(文案) 与 image(关键帧) 两条通道开通。 music / video / lipsync 未开通。这不是技能的问题,是网关渠道的问题。 处理方式见 references/capability-matrix.md,本文每步都标了「通道不通时怎么办」。


一、产线全景

① 作曲填词      [chat ✅]     → work/song.json
② 分镜脚本      [chat ✅]     → work/storyboard.json
③ AI 音乐       [music ❌]    → work/audio/music.mp3(未开通,可自备音频)
④ 音轨分离      [本地 ◐]      → work/audio/vocals.wav + instrumental.wav
⑤ 人物资产      [即梦 ✅]      → out/character/{1-定妆照,2-上半身,3-全身,4-多视图}.png   ★v0.2新增
⑥ 场景图+关键帧  [即梦 ✅]      → work/scene/shot-XX.png(无人)+ work/frames/shot-XX.png(有人)★v0.2
⑦ 图生视频      [即梦 ✅]      → work/clips/shot-XX.mp4(真 AI 生成)        ★v0.2
⑧ 唇形驱动      [lipsync ❌]   → 可用即梦数字人替代
⑨ 剪辑合成      [本地 ✅]     → out/mv.mp4

一条命令跑完全程:

fmode-mv song "深夜末班地铁上的城市白领" --genre "city pop" --mood "孤独但温暖"

下面逐步拆解,方便分段调试与省钱。


二、① 作曲填词

fmode-mv lyrics "深夜末班地铁上的城市白领,加班后的疲惫与微小的温暖" \
  --genre "city pop" \
  --mood "孤独但温暖"

产物 work/song.json:

{
  "title": "末班车还亮着",
  "genre": "城市流行 City Pop",
  "mood": "孤独、温暖、夜色、治愈",
  "bpm": 92,
  "structure": ["Intro","Verse 1","Pre-Chorus","Chorus", ...],
  "lyrics": "[Intro]\n(器乐)\n\n[Verse 1]\n写字楼的灯 一盏一盏熄了\n...",
  "stylePrompt": "city pop, 92 bpm, warm analog synth pads, electric piano chords, ... female vocal ..."
}

要点:

  • structure 的结构标记是给音乐模型的分段指令,不要删——Suno 类模型靠它排段落。
  • stylePrompt 是英文的,直接投给音乐模型;改曲风就改这里。
  • 命令末尾会自动做歌词自检(有没有 Verse/Chorus 标记、正文够不够长、有没有 stylePrompt), 有问题会 ! 歌词自检提示:...,据此重跑或手改 JSON。

避坑:

  • 主题写太抽象(如「爱情」)→ 歌词会很空。给具体场景(「深夜便利店买热豆浆」)效果最好。
  • 想要固定时长,用 --style "控制在 2 分 30 秒,副歌重复 3 次"。

三、② 分镜脚本

fmode-mv storyboard --from work/song.json --shots 8 --per-shot 6

产物 work/storyboard.json(下游全部消费它)+ work/storyboard.md(人读版表格)。

关键字段:

字段 作用
appearanceAnchor ★主角外貌锚点(英文)。每个含人物的镜头都会原样复述它 → 人物一致性全靠这个
styleKeywords 全片统一影像风格,拼进每张关键帧 prompt
shots[].imagePrompt 英文,可独立投喂文生图
shots[].videoPrompt 英文运镜描述,投给图生视频
shots[].lipSync 是否做唇形驱动

避坑(实测踩过的):

  1. 镜头数跑飞:早期版本模型会给你 30 个 36 秒的镜头。现在提示词里加了硬约束 (--shots 为硬性约束、单镜钳制在 3~10 秒),且 normalizeStoryboard 会二次夹取。 若看到 ! N 个镜头的时长超出合理区间已被夹取,说明模型不听话,已被自动纠正。
  2. 模型是推理型的:deepseek-v4-flash 会把大量 token 花在推理上,8192 token 全被推理吃掉、 JSON 被截断。技能已内置自动升配(翻倍重试到 24k~32k)+ 修复式重试。 若还失败,换非推理模型:--model doubao-seed-2-1-pro。
  3. 人物一致性:不要手工改 appearanceAnchor,除非你同时接受整片人物变脸。 想换主角,改锚点后必须重生成全部关键帧。

只做几镜试跑(省钱):

fmode-mv storyboard --from work/song.json --shots 3
fmode-mv keyframe   --from work/storyboard.json --limit 3

四、③ AI 音乐 ⚠️ 通道未开通

fmode-mv music --from work/song.json

现状实测:POST /suno/submit/music 返回 503 Task request failed —— 端点存在,渠道未开通。 命令会真试一次,失败后给出可操作方案,不会伪造 mp3。

三条替代路线:

方案 做法
A. 等平台开通 开通后原命令无需改动即可用
B. 自备音乐 用你的音频直接进后续流程:--music your-song.mp3
C. 对接外部 export FEME_MUSIC_ENDPOINT=https://... 指向兼容端点

自备音乐时的注意:

  • 必须是成品混音(有人声+伴奏),否则第 ④ 步分离没意义。
  • 时长最好与分镜总时长接近;assemble 会以画面轨时长为准,音频超出会被 -shortest 截断。

五、④ 人声 / 伴奏分离 ◐

fmode-mv separate work/audio/music.mp3

两级策略,脚本会自动选:

  1. demucs(若已安装)→ 真·分离,质量高。安装:pip install demucs
  2. ffmpeg 相位兜底(默认)→ 侧信号取伴奏、中置取人声。 ⚠️ 这是近似,人声/伴奏都会残留串扰。脚本会明确打印这个警告。

避坑:

  • 单声道素材无法分离 → 脚本直接报错并告诉你装 demucs,不会给你一个假结果。
  • 分离出的 vocals.wav 主要给第 ⑦ 步唇形驱动当驱动音频用;纯音乐 MV 其实可以跳过这步。
  • 兜底方案对「人声居中、乐器左右分布」的老式混音效果尚可;现代宽混音基本无效。

六、⑤ 人物资产(★v0.2 新增,不换脸的关键)

fmode-mv character-sheet --desc "25岁东亚女性,栗棕色长直发,身穿米色针织开衫和白色长裙,清冷安静" --limit 1
fmode-mv character-sheet --desc "..." --limit 4      # 完整四步

四步流水线:① 定妆照(3候选) → ② 上半身 → ③ 全身 → ④ 多视图,每步图生图参考上一步 + 锐度自动择优。

产物 out/character/{1-定妆照,2-上半身,3-全身,4-多视图}.png + candidates/ + character-sheet.json。

为什么必须有这一步:纯 AI 出片最容易翻车的就是「同一人物跨镜头换脸」。 只靠 prompt 里的 appearanceAnchor 是软约束;有了多视图做图生图参考,才是像素级硬约束。

费用:--limit 1 ¥0.60(3 张候选);完整四步 ¥1.98(9 张候选)。--dry-run 零费用。

避坑:

  • 服装请写在 --desc 里(如「身穿…」),否则会退回默认兜底并在日志里警告。
  • --single 每步只出 1 张、跳过择优(省钱,但质量靠运气)。

七、⑥ 场景图 + 关键帧 ✅(★v0.2 重构)

fmode-mv scene --from work/storyboard.json --character out/character/4-多视图.png
fmode-mv scene --from work/storyboard.json --shot 3 --limit 1     # 试跑
fmode-mv scene --from work/storyboard.json --scene-only           # 只出场景图

两步法(v0.2 的核心改进):

  1. 场景图(无人/纯环境) ← 文生图,为每镜铺环境;
  2. 关键帧(有人) ← 图生图多图参考:[场景图, 人物多视图]。

为什么拆两步:一次推理里同时解决空间/光线/人脸三件事,结果往往是背景每镜都不一样、 人物和背景光照打架。拆开后背景一致、光照统一。 相邻镜头还会把「上一镜场景描述」注入本镜 prompt 做一致性约束。

产物 work/scene/shot-XX.png + work/frames/shot-XX.png + work/scene/scenes.json。

费用:每镜 ¥0.42(场景图 ¥0.20 + 关键帧 ¥0.22)。

旧的 fmode-mv keyframe(走 /v1/images/generations)保留可用,作为即梦不可用时的回退。


八、⑦ 图生视频 ✅(★v0.2 已接通真实通道)

fmode-mv video --from work/storyboard.json                       # auto:走即梦真通道
fmode-mv video --from work/storyboard.json --limit 1             # 先试 1 镜(≈¥1.41)
fmode-mv video --from work/storyboard.json --mode still          # 零费用:Ken Burns 兜底

实测:/getVideoV3_720p,121 帧(5 秒),实扣 ¥1.41,返回 h264 mp4(2.4MB)。 旧通道 /v1/video/generations 仍是 503,已由即梦替代。

--mode 三种模式:

模式 行为
auto(默认) 探活;通就走即梦真通道,不通自动降级为 Ken Burns 兜底
jimeng 只走即梦,不通即失败(用于强制验证)
still 强制用关键帧做 Ken Burns 运镜(零 API 费用)

三条硬约束(v0.2 实测修正,KB 未记载):

  1. frames 必须 ∈ {121,145,169,193,217,241}(既在 [121,241] 内,又要 ≡1 (mod 24))。 → 单镜只能是 5/6/7/8/9/10 秒的整数秒。分镜阶段就按时长设计最省事。
  2. method=3(首尾帧)需要 2 张同比例图;第一镜用下一镜的关键帧作尾帧。
  3. method=3 失败会自动降级 method=2,返回带 degraded: true 并在日志写明(不静默)。

避坑:

  • 场景跨度大时别用 method=3(室内→室外、人物→空镜这类两帧会崩坏)—— 硬规则:首尾帧只用于同场景连续动作 / 相似场景过渡 / 状态渐变。
  • 首帧图长边/短边 ≤ 3,否则被拒。
  • 兜底片段体积偏大(低 CRF 编码静态图)。
  • 真通道开通/重新开通后一键替换:fmode-mv video --from work/storyboard.json --force。

九、⑧ 唇形驱动 ❌ → 改用即梦数字人 ✅

fmode-mv lipsync --probe    # 先看通道状态

现状:网关没有 /lipsync/generations 这条路由(返回前端兜底页)。

v0.2 的替代(实测可用):

fmode-mv jimeng digital-human \
  --ref out/character/3-全身.png \
  --audio work/audio/vocals.wav \
  --prompt "固定机位,头部随节奏轻微摆动,神情投入,眼神直视镜头"

走即梦数字人 v1.5 三步流程,¥1/秒,是真人对口型。

其余替代路线(按推荐度):

方案 做法 观感
即梦数字人 上面那条命令 最好(¥1/秒)
C. 纯空镜 + 字幕 不标 lipSync,全片走 B-roll 纯音乐 MV 最常见,零风险
B. 表情微动镜头 演唱镜头走图生视频(表情/头部微动),不严格对口型 成片观感可接受
A. 自建服务 部 Wav2Lip / SadTalker / LatentSync,export FEME_LIPSYNC_ENDPOINT=... 需部署

避坑:

  • 唇形镜头全片别超过 4 个:每个都需要人脸正脸关键帧 + 人声干声,成本和翻车率都高。
  • 分镜里的 lipSync: true 只对 perf/talking 类型生效,给 broll 标了也会被忽略。

十、⑨ 剪辑合成 ✅

## 十、⑨ 剪辑合成 ✅

bash fmode-mv assemble \ --from work/storyboard.json \ --music work/audio/music.mp3 \ --beat-sync


**这一步做的事(全在本地 ffmpeg)**:

1. 按 `shot-XX` 序号收集片段(缺 `shot-XX.mp4` 时自动用 `shot-XX.fallback.mp4` 顶上)
2. 统一分辨率/帧率后拼接
3. `--beat-sync`:能量包络节拍检测 → 把镜头时长吸附到节拍点
4. 从分镜的 `subtitle` 字段生成 SRT,烧硬字幕
5. 混音(音乐 + 可选配音/背景乐),片尾淡出
6. 响度归一化到 I=-14 LUFS(两遍 loudnorm)

**产物**:`out/mv.mp4` + `out/manifest.json`(含兜底片段数、BPM、音轨信息)。

**避坑**:

- **卡点检测对纯音无效**。实测用正弦波测出「0 个节拍点」——
  脚本会明确告诉你「未检出节拍点,跳过卡点对齐」,**不会假装对齐了**。
  要卡点必须有鼓点/瞬态的成品编曲。
- **字幕字号自适应**:按分辨率算 `fontSize = h/36`,改分辨率不用手调。
- **字幕烧入失败不会中断成片**:会降级为「成片不带字幕,SRT 文件仍在 work/」并打印警告。
  常见原因是字体缺失,装 `fonts-noto-cjk` 即可。
- 片段缺失或损坏时 `assemble` 会直接报错告诉你缺哪段,不会给你一个静默残缺的成片。

---

## 十一、端到端速查

bash

全自动(能跑的都跑,跑不了的如实跳过并降级)

fmode-mv song "主题" --genre "city pop"

分段调试(推荐首次使用)

fmode-mv lyrics "主题" --genre "city pop" fmode-mv storyboard --from work/song.json --shots 6 fmode-mv keyframe --from work/storyboard.json --dry-run # 先看 prompt fmode-mv keyframe --from work/storyboard.json --shot 1 # 只做首镜 fmode-mv keyframe --from work/storyboard.json # 满意后批量 fmode-mv video --from work/storyboard.json # 自动兜底 fmode-mv assemble --from work/storyboard.json --music your-song.mp3 --beat-sync ```

开工前的三个好习惯:

  1. --dry-run 看 prompt,别一上来就批量烧钱。
  2. 先 --limit 2 跑通全链路,再放开全部。
  3. 每步的产物 JSON 都在 work/,不满意只重跑那一步,不用从头来。