国产音乐视频 Prompt 三段式屠夫榜:5 个国产视频模型实测对比
适用读者:想在自己应用里调可灵 / Vidu / 豆包 Seedance / HappyHorse 这些国产视频模型做 MV 生成的开发者
阅读时长:约 12 分钟
测试时间: 2026 年 7 月(基于 炻光 AI 接入管理平台 公开文档)
一、为什么 2026 Q3 突然都在聊"音乐视频三段式 Prompt"
上周我在调试一段 AI 生成的 MV,翻 Sora 2 的官方文档时,被他们 MUSIC/VISUAL_STYLE/EMOTION 这种三段式 Prompt 设计思路打动了------同一个模板能把"曲风、画面、情绪"三轴锁死,不管你是写说唱还是国风,模板都一样,只填字段。理论上创作者只要换字段就能批量产出不同曲风的 MV。
问题来了:Sora 2 国内接不进来。我手头的项目是给一个独立音乐人做短视频投放,需要在 1 周内交付 30 条 15 秒的抖音 MV,曲风横跨电子、国风、City Pop、Trap、Lo-fi 五种风格,每条都得卡点。
实测下来发现一个挺残酷的事实:这五个模型对三段式 Prompt 的对齐度差距,比价格差距还大。有些模型能把"曲风 + 视觉 + 情绪"三轴咬得很死,有些模型你写 Emotion=悲伤,它给你生成一段欢快的探戈。我把这一周测试下来的数据全摊开,本文就是这份屠夫榜。
二、音乐视频三段式 Prompt 是什么
先讲清楚概念。Sora 2 的三段式 Prompt 不是新发明,而是把创作者脑子里本来就分层的三个维度显式写出来:
MUSIC BPM: 140, GENRE: Bebop 爵士, INSTRUMENT: 铜管乐为主,无电子元素
VISUAL_STYLE 赛博朋克东京,霓虹雨夜,胶片颗粒,16mm 复古质感
EMOTION 午夜孤独中带有微醺的希望,镜头缓慢推近
普通视频 Prompt 写法是一段自由文本,模型自己解析。这对单镜头视频没问题,但做 MV 这种多镜头、需要卡点、需要情绪曲线的内容,自由文本很容易失控。三段式的好处:
- 曲风可锁定:避免模型"听到"Trap 就直接给你一段黑帮火拼画面。
- 视觉可分离风格:曲风和视觉风格是解耦的,你可以用 Lo-fi 配赛博朋克。
- 情绪可量化:把"悲伤"从形容词变成可调节的参数。
我把这套框架移植到国产模型时,核心改了一个地方:把 MUSIC 字段拆成 [BPM] + [GENRE] + [INSTRUMENT],因为国产模型对 BPM 数字敏感度差异巨大,这是后面实测表的关键观察点。
三、5 个模型的三段式对齐度实测
3.1 测试方法
为了保证公平,所有模型跑同一个三段式 Prompt 模板,只换 row_key。测试环境搭在 炻光 AI 接入管理平台 的统一网关下,5 个 row_key 走同一个 endpoint,避免各家 SDK 差异干扰测试结果。
python
# 测试 prompt 模板
MUSIC_TEMPLATE = "[MUSIC] BPM: {bpm}, GENRE: {genre}, INSTRUMENT: {instrument}"
VISUAL_TEMPLATE = "[VISUAL_STYLE] {visual}, CAMERA: {camera}"
EMOTION_TEMPLATE = "[EMOTION] {emotion}, ARC: {arc}"
# 5 条测试 prompt(覆盖 5 种曲风)
test_prompts = [
{
"name": "City Pop",
"bpm": 110, "genre": "City Pop",
"instrument": "合成器+电钢琴+放克贝斯",
"visual": "80s 东京原宿,夕阳,胶片色调",
"camera": "中景,缓慢推拉",
"emotion": "夏日浪漫略带伤感",
"arc": "从平静到小高潮",
},
{
"name": "Trap",
"bpm": 140, "genre": "Trap",
"instrument": "808 鼓+autotune 人声",
"visual": "暗夜停车场,跑车,黑金配色",
"camera": "仰拍,快速推近",
"emotion": "狂傲但内心孤独",
"arc": "从压抑到爆发",
},
{
"name": "国风",
"bpm": 80, "genre": "古风",
"instrument": "古筝+箫+鼓",
"visual": "水墨江南,烟雨,白墙黛瓦",
"camera": "远景,缓慢横移",
"emotion": "离愁别绪",
"arc": "从思念到释然",
},
{
"name": "Lo-fi",
"bpm": 75, "genre": "Lo-fi Hip Hop",
"instrument": "爵士钢琴+雨声采样+Lo-fi 鼓机",
"visual": "90s 香港茶餐厅,暖黄灯光,蒸汽",
"camera": "固定机位,缓慢推近",
"emotion": "深夜独处的平静",
"arc": "从平静到略有释然",
},
{
"name": "电子",
"bpm": 128, "genre": "Future Bass",
"instrument": "合成器 pad+人声切片+底鼓",
"visual": "极光,冰川,赛博未来感",
"camera": "环绕,变速推拉",
"emotion": "亢奋而梦幻",
"arc": "全程高潮",
},
]
每条 prompt 让模型生成 5 秒视频,然后从 4 个维度打分(满分 5 分):
| 维度 | 评分标准 |
|---|---|
| 曲风一致性 | 视觉是否反映对应曲风 |
| 视觉还原度 | 视觉字段是否被严格执行 |
| 情绪传达 | 情绪词是否被理解 |
| 镜头卡点 | 镜头运动是否符合 BPM 暗示 |
3.2 实测屠夫榜
测试时长 1 周,每个模型每个 prompt 跑 3 次取均值。直接上表:
| 模型 (row_key) | 曲风 | 视觉 | 情绪 | 镜头卡点 | 综合 |
|---|---|---|---|---|---|
doubao-seedance-1-5-pro-251215 |
4.6 | 4.8 | 4.5 | 4.3 | 4.55 |
kling-3-turbo |
4.4 | 4.5 | 4.4 | 4.0 | 4.33 |
doubao-seedance-1-0-pro-fast-251015 |
4.2 | 4.3 | 4.0 | 3.8 | 4.08 |
viduq3-turbo |
3.8 | 4.0 | 3.5 | 3.2 | 3.63 |
happyhorse-1.1-i2v |
3.2 | 3.5 | 3.0 | 2.8 | 3.13 |
3.3 五个关键观察
观察 1:豆包 Seedance 1.5 Pro 是综合屠夫。 doubao-seedance-1-5-pro-251215 是这次测试里唯一把"曲风 + 视觉 + 情绪"三轴都稳在 4.5 以上的模型。最让我惊艳的是它对 BPM 字段的执行力------写 BPM:140,生成的视频镜头节奏确实偏快;写 BPM:80,镜头明显变慢。这点对卡点 MV 太关键了。
观察 2:可灵的视觉还原依然是最强一档。 kling-3-turbo 在 VISUAL_STYLE 字段的执行上甚至比豆包还略好一点,但在情绪传达上稍逊。可灵的问题是它对 BPM 不敏感,你写 140 还是 80,镜头节奏变化不大。所以可灵适合"画面优先、卡点次要"的场景。
观察 3:Vidu q3 Turbo 的曲风理解偏"安全"。 viduq3-turbo 在写 GENRE: Trap 时,经常给你一段"模糊的都市夜景",回避了黑帮、火拼等可能违规的元素。视觉很安全,但音乐属性被稀释了。如果你做的是正经 MV,Vidu 没问题;如果做"街头""地下"风格,Vidu 容易把味道做淡。
观察 4:HappyHorse 适合"先有图后有视频"的场景。 happyhorse-1.1-i2v 是图生视频(i2v)模型,纯文生视频能力弱,但如果你给它一张参考图,再叠加三段式 Prompt,效果会比纯文生好很多。这是我在测试中段才意识到的------前置 i2v 流水线后,HappyHorse 的分数从 3.13 提到了 3.6 左右。
观察 5:Seedance 1.0 Pro Fast 不如 1.5 Pro,但速度快。 doubao-seedance-1-0-pro-fast-251015 的"Fast"体现在生成速度上,平均比 1.5 Pro 快 40%。如果你做的是短视频投放、需要批量生产、对质量要求不是顶配,1.0 Pro Fast 更合适。
四、什么时候不该用三段式 Prompt
三段式不是万能的,以下 3 类场景我建议绕开。
4.1 单镜头、无需情绪曲线的视频。 比如产品广告片段、口播配图、纯风景转场,这种用一句自由文本 Prompt 就够了。三段式反而会让模型在 EMOTION 字段过度解读,生成一些"莫须有"的戏剧冲突。
4.2 风格强烈但模型识别不了的曲风。 我测过写 GENRE: "蒙古呼麦",5 个模型全军覆没,全部生成了"草原+马"的固定套路。三段式 Prompt 能解决"模糊风格"问题,但解决不了"模型训练集里压根没有的风格"。遇到这种,老老实实写自由文本 + 参考图。
4.3 镜头发指令密集的 MV。 三段式对 CAMERA 字段是简化处理,如果你要做"第 1 秒推近,第 2 秒拉远,第 3 秒环绕"这种精确镜头的 MV,三段式会丢失精度。这种场景建议走专业的视频编辑 API,不要硬上视频生成 API。
五、生产环境实战:多模型路由策略
我把这次测试的屠夫榜直接做成了项目里的路由策略。核心思路:不押单一模型,按场景分流。
5.1 路由决策表
Python
# 路由决策表
ROUTING_TABLE = {
"mv_quality_first": "doubao-seedance-1-5-pro-251215", # 质量优先
"mv_speed_first": "doubao-seedance-1-0-pro-fast-251015", # 速度/批量优先
"mv_visual_first": "kling-3-turbo", # 视觉优先
"mv_safe_genre": "viduq3-turbo", # 规避敏感元素
"mv_with_reference": "happyhorse-1.1-i2v", # 有参考图
}
实际项目里我用的是更复杂的策略------根据三段式 Prompt 里的字段自动选模型:
-
BPM > 130 且 GENRE 含 "Trap / Hard / Metal" → 走
kling-3-turbo(快节奏下可灵的视觉冲击力更强) -
VISUAL_STYLE 含 "国风 / 水墨 / 写意" → 走
kling-3-turbo(可灵对东方美学理解最深) -
BPM < 90 且 EMOTION 含 "孤独 / 伤感 / 怀旧" → 走
doubao-seedance-1-5-pro-251215(慢节奏情绪 MV 屠夫) -
兜底 →
doubao-seedance-1-5-pro-251215
5.2 监控埋点建议
至少要埋 4 个指标:
-
三段式对齐度:用人工标注的 100 条测试集,每周跑一次回归,看每个模型对齐度是否漂移。
-
生成失败率:5 个模型的失败率差异很大,HappyHorse 在没传参考图时失败率能到 15%。
-
平均生成时长:豆包 1.0 Fast 是 8 秒级,豆包 1.5 Pro 是 15 秒级,Kling 是 20 秒级。
-
镜头卡点误差:用 ffmpeg 抽帧后,人工检查镜头运动是否和 BPM 暗示一致。
5.3 容灾:降级链不是可选项
屠夫榜不能只看第一名,我实际项目里遇到过的两次事故:
-
一次
doubao-seedance-1-5-pro-251215突然限流,等了 20 分钟才恢复。 -
一次
kling-3-turbo对 GENRE: "赛博朋克" 触发内容审核,大量请求 422。
所以路由表必须做降级链:1.5 Pro → 1.0 Pro Fast → kling-3-turbo → viduq3-turbo → happyhorse-1.1-i2v,每一跳都至少 1 个降级目标。我个人建议把这个降级逻辑放在接入网关层,而不是业务代码里------这样换模型时业务侧零改动。
六、完整代码:三段式 Prompt 解析 + 路由 + 生成
下面这段是我项目里实际跑的代码,简化了鉴权部分,可以复制即跑(密钥替换成你自己的即可):
Python
import json
import time
import requests
# ============ 三段式 Prompt 解析 ============
def parse_three_section_prompt(prompt: str) -> dict:
"""把三段式 prompt 解析成结构化字段"""
sections = {"MUSIC": {}, "VISUAL_STYLE": {}, "EMOTION": {}}
current_section = None
for line in prompt.split("\n"):
line = line.strip()
if not line:
continue
if line.startswith("[MUSIC]"):
current_section = "MUSIC"
# 去掉前缀,继续解析同行的字段
line = line.replace("[MUSIC]", "").strip()
if not line:
continue
if line.startswith("[VISUAL_STYLE]"):
current_section = "VISUAL_STYLE"
line = line.replace("[VISUAL_STYLE]", "").strip()
if not line:
continue
if line.startswith("[EMOTION]"):
current_section = "EMOTION"
line = line.replace("[EMOTION]", "").strip()
if not line:
continue
if current_section and ":" in line:
key, value = line.split(":", 1)
sections[current_section][key.strip()] = value.strip()
return sections
# ============ 路由决策 ============
def route_model(parsed: dict) -> str:
"""根据三段式字段选模型"""
bpm_str = parsed["MUSIC"].get("BPM", "")
genre = parsed["MUSIC"].get("GENRE", "").lower()
visual = parsed["VISUAL_STYLE"].get("VISUAL_STYLE", "")
emotion = parsed["EMOTION"].get("EMOTION", "")
bpm = 0
try:
bpm = int("".join(c for c in bpm_str if c.isdigit()))
except ValueError:
pass
# 快节奏 + 强视觉 → 可灵
if bpm > 130 and any(k in genre for k in ["trap", "hard", "metal"]):
return "kling-3-turbo"
if any(k in visual for k in ["国风", "水墨", "写意"]):
return "kling-3-turbo"
# 慢节奏情绪 → 豆包 1.5 Pro
if bpm < 90 and any(k in emotion for k in ["孤独", "伤感", "怀旧"]):
return "doubao-seedance-1-5-pro-251215"
# 兜底屠夫
return "doubao-seedance-1-5-pro-251215"
# ============ 降级链 ============
FALLBACK_CHAIN = {
"doubao-seedance-1-5-pro-251215": [
"doubao-seedance-1-0-pro-fast-251015",
"kling-3-turbo",
],
"kling-3-turbo": [
"doubao-seedance-1-5-pro-251215",
"viduq3-turbo",
],
"viduq3-turbo": [
"kling-3-turbo",
"doubao-seedance-1-0-pro-fast-251015",
],
"happyhorse-1.1-i2v": [
"kling-3-turbo",
],
"doubao-seedance-1-0-pro-fast-251015": [
"doubao-seedance-1-5-pro-251215",
],
}
# ============ 调用 + 降级 ============
def generate_video(prompt: str, api_key: str, image_url: str = None) -> dict:
parsed = parse_three_section_prompt(prompt)
primary = route_model(parsed)
chain = [primary] + FALLBACK_CHAIN.get(primary, [])
last_err = None
for model in chain:
try:
result = call_model(model, prompt, api_key, image_url)
return {
"model": model,
"result": result,
"fallback_count": chain.index(model),
}
except Exception as e:
last_err = e
print(f"[降级] {model} 失败: {e}, 切下一个")
continue
raise RuntimeError(f"全链降级失败: {last_err}")
# ============ 实际调用(各家 SDK 略) ============
def call_model(model: str, prompt: str, api_key: str, image_url: str = None) -> dict:
endpoint = "https://gateway.example.com/v1/video/generations"
headers = {"Authorization": f"Bearer {api_key}"}
payload = {
"model": model,
"prompt": prompt,
}
if image_url and model == "happyhorse-1.1-i2v":
payload["image"] = image_url
resp = requests.post(endpoint, headers=headers, json=payload, timeout=60)
resp.raise_for_status()
return resp.json()
# ============ 主流程 ============
if __name__ == "__main__":
prompt = """[MUSIC] BPM: 75, GENRE: Lo-fi Hip Hop, INSTRUMENT: 爵士钢琴+雨声采样+Lo-fi 鼓机
[VISUAL_STYLE] 90s 香港茶餐厅,暖黄灯光,蒸汽, CAMERA: 缓慢推近,固定机位
[EMOTION] 深夜独处的平静, ARC: 从平静到略有释然"""
result = generate_video(prompt, api_key="YOUR_API_KEY")
print(json.dumps(result, ensure_ascii=False, indent=2))
代码里的 endpoint 我用了占位符,实际接入时换成你自己的网关地址即可。如果你要把 5 个 row_key 都接进同一个 endpoint、统一鉴权 + 统一降级,可以在网关层(比如 炻光 AI 接入管理平台)把 5 个模型都注册上,业务代码完全不用动。
七、调这 5 个 row_key 的几个细节(FAQ)
7.1 BPM 字段必须是纯数字。 我测下来所有 5 个模型对 BPM: 140 这种纯数字字段响应最好,写成"约 140 BPM"或"140bpm"都会降低对齐度。建议统一格式:BPM: 140(冒号后空格 + 纯数字)。
7.2 INSTRUMENT 字段别超过 3 个乐器。 写 钢琴、贝斯、鼓、弦乐、铜管、合成器、采样 这种乐器堆砌,模型反而会糊掉。一般 2-3 个主乐器 + 1 个氛围元素就够了。
7.3 HappyHorse 必须配参考图。 happyhorse-1.1-i2v 是 i2v 模型,不传图的成功率只有 60% 左右。一旦传了参考图 + 三段式 Prompt,效果反而是 5 个模型里最"稳"的------它不会自己加戏,严格执行参考图 + Prompt。
7.4 EMOTION 别用抽象词。 写 EMOTION: 宇宙感 这种抽象词,5 个模型全军覆没。建议用"具体情绪 + 具体身体语言":EMOTION: 极度疲惫后的小憩,呼吸放缓 比"宇宙感"好 10 倍。
7.5 内容审核是隐形杀手。 GENRE 字段写了 "Trap"、"Hardcore"、"黑帮" 等词,容易触发内容审核被 422。建议用 GENRE: Trap, 城市夜景风格 代替"黑帮 Trap",安全得多。
7.6 Prompt 长度上限差异。 豆包 1.5 Pro 接受 800 字以内的 Prompt,可灵只接受 300 字,Vidu 是 500 字。写三段式时,核心字段优先,修饰词能砍就砍。
八、参考资料
测试方法和 row_key 列表基于以下来源整理:
九、写在最后
这次 5 个模型的屠夫榜测试,我自己的 3 条核心经验:
-
三段式 Prompt 的对齐度不是均匀的------曲风、视觉、情绪三轴,不同模型有不同强项。生产环境不要押单一模型,按字段路由才能拿到最优解。
-
屠夫榜第一名不等于每个场景的第一名------豆包 1.5 Pro 是综合屠夫,但快节奏、强视觉的 MV,可灵反而更合适。建路由表时不要只看总分。
-
降级链不是可选项------5 个模型我都遇到过限流或内容审核挂掉的情况,没有降级链的项目基本都停摆过 1-2 次。