对外提供视频生成、任务查询与账户余额查询能力 · 兼容 OpenAI 风格的 REST 接口
版本 v3.16 · 更新日期 2026-10-24(新增 §18 星河字画(文字 PV)CD 模板:template_id=xinghe-cd-001,把歌词直接渲染成文字 PV 成片(服务端浏览器内编码,不占渲染机队列)。素材只要 line_lyrics(歌词)+ original_vocal(原唱音频),歌词也可用 song_info.lyrics 内嵌传;成片 H.264 + AAC,画幅 16:9,可选 720P / 1080P / 2K / 4K,时长≈音频时长。同版修复模板列表接口三处问题:status=all 此前恒返回空、category 大小写敏感、样片地址拼成死链)
版本 v3.15 · 更新日期 2026-10-22(新增 §17 字幕(歌词)· 字体 · 转场 提交规范:把甲方最常问的三件事一次定版 —— ① 歌词三种给法(line_lyrics / word_lyrics / song_info.lyrics)+ 优先级 + 时间基准口径(时间戳从音频 0 秒起算,前置封面/海报偏移由平台加,甲方禁止自己加) + 覆盖要求 + 六类常见错误;② 字体随歌词、不单独指定(已定版不做任务级字体,无字段、无预留草案:CD 走星光1号内置卡拉OK样式——微软雅黑 60px / 未唱金 #FFD878、已唱白;MV 走所选歌词插件样式;要换字体只能换插件/模板);③ 转场声明位置与优先级、per_shot 下标语义、取值夹取规则,明确 MV(ffmpeg)49 项全量生效 / CD(melt)只生效时长与硬切、视觉统一交叉溶解。配套服务端变更:交付包 manifest.transitions 此前只在文档里写着、服务端从未读取(甲方声明被静默丢弃),本版已修复为真正生效并优先于转场插件)
版本 v3.14 · 更新日期 2026-10-19(海报镜尾帧口径修正 · 重要,此前口径作废:① 海报镜与普通分镜同权,必须自带首尾帧 —— endImageUrl 必填,缺尾帧一律打回(error_code=MATERIAL_MISSING_END_FRAME),平台不做任何自动补齐/兜底(此前「海报为开场独立镜头、不参与首尾帧衔接 / 尾帧不下发」的表述已作废,T504/505/510/511 四单即因该口径海报文字缺失);② 尾帧上的文字由生成模型依据 videoPrompt 的描述生成,不是「首帧无字渐变显现到尾帧」的文字动效 —— 想让画面出现什么字,直接在 videoPrompt 里写明文字内容与版式,不要在提示词里写「淡入/渐显/文字出现动画」;③ 平台自动插入的海报镜仍为首尾同图(首帧=尾帧=海报图),该设计不变。见 §15.4.2)
版本 v3.13 · 更新日期 2026-10-14(自带海报镜口径修正 + 甲方接入范例:① §15.4.2 规则③修正为 timeline.durationMs 与 shotCount 必须包含海报镜(与自检闸门实际比对口径一致,避免被 MV_SELFCHECK_FAILED 打回);② 新增可直接照抄的 mv-shots.json 接入范例(海报镜 + 歌曲镜 + 成片时间轴对账表 + 推包前 60 秒自查,见 §15.4.2 三);③ 海报镜独立音画口径明确:海报段静音无字幕,歌曲音频/歌词由平台自动整体后移,甲方文件零改动)
版本 v3.7 · 更新日期 2026-10-07(定妆照快速整改指引 + 打回主动通知:近期多单反复卡在「缺少主角定妆照」被打回 —— 本版在 §15.4.1 顶部新增「推包前 30 秒自查清单」(定妆照三种给法 + 四环自查 + 打回原因查询方式,见 §15.4.1);并新增 material_rejected 打回主动回调:素材被闸门打回(status=awaiting_materials)时平台主动推送签名回调,payload 含 issues 结构化整改清单(invalid_materials / missing_materials / 24h 时效),无需轮询即可知道被打回及原因。查询接口 GET /v1/video/generations/{id} 的 error / invalid_materials / missing_materials 字段口径不变)
版本 v3.6 · 更新日期 2026-10-06(交付规格变更(经双方确认):MV 镜头生成降档为 960×544 @ 24fps(生成提速 50%+),经 AI 超分回 1920×1080 后按 24fps 交付 —— 分辨率不违约、全片 24fps 无 judder(不做 30fps 帧重采样)、交付最快;仅帧率偏离契约原 30fps。物料包内若声明 1920×1080@30 将按本口径统一交付(timeline.frameRate 缺省值同步改为 24,见 mv-shots.schema.json)。如需回退原口径请线下沟通)
版本 v3.5 · 更新日期 2026-10-03(本版新增:§15.4.1 MV 一致性核验链 —— 核验单覆盖完整链条「MV 脚本 → 主角定妆照 → MV 镜头表(含首帧)→ 镜头首尾帧」;物料包 mv 节点新增三字段 dressImageUrl / dressAvailable(主角定妆照地址与可用性)/ tailFrameReadyCount(尾帧就绪数,与 shots[].endImageUrl 对应);行为变化:定妆照设为 required —— 未定妆的作品推送接单会被核验闸门拦下(提示先生成定妆照),已定妆作品不受影响。机器可读规范同步 openapi v1.3.3)
版本 v3.4 · 更新日期 2026-10-03(本版变更:首尾帧 shots[].endImageUrl 由可选增强升级为硬要求:zip 包须包含每一镜尾帧图;包内缺失、上传失败或仅给包内相对路径,任务直接打回报错,不再静默退化为单首帧;同时取消「下一镜首帧兜底」,严格按契约首尾帧生成。见 §15.3)
版本 v3.3 · 更新日期 2026-10-02(本版新增:§15.6.1 镜头级状态查询增加双鉴权——甲方现有 API 凭据 Authorization: Bearer <api_key> 可直接调用,按作品归属隔离(仅能查询自己客户名下的作品);原 worker 管理令牌 x-mv-admin-token 通道不变,仍可查全部作品。机器可读规范同步 openapi v1.3.2)
版本 v3.2 · 更新日期 2026-10-01(本版新增:镜头脚本 shots[].endImageUrl 尾帧字段 —— 与 imageUrl 配对构成首尾帧生成,锚定每镜结束画面、使相邻镜头接得更顺;自适应:提供才启用,不提供则完全按现行单首帧管线生成,与改造前一致、不受影响。见 §15.3 镜头脚本;机器可读规范同步 openapi.yaml v1.3.1 / mv-shots.schema.json)
版本 v3.1 · 更新日期 2026-09-24(文档合并:原《MV 视频制作对接文档》已并入本文档 §15 MV 视频制作对接,甲方只需保存本页一个地址;原 /mv-api-docs.html 保留为跳转页。内容变更:MV 物料契约 · 渲染前自检闸门 · 整改对照 R1–R9 · 联调回归 · 哈希口径,详见 §15 与 §13 变更记录;并新增机器可读规范(openapi.yaml v1.3.0 含 MV 契约与全量 schema)、镜头脚本 JSON Schema 与本地自查脚本,见 §15.3+ 校验工具)
🎬 需要制作 MV(图生视频 + 拼接成片)?直接看本文档 §15 MV 视频制作对接(含物料包契约、自检闸门、交付规格、联调回归)
input/mv-shots.json——每镜的时长 durationMs 与提示词 videoPrompt。
只有镜头底图、或只附 edit-script.md(剪辑概述,不含每镜时长与提示词)都会被打回为 awaiting_materials,24 小时内未补齐将自动取消并退款。
→ 格式规范与打包自查shotCount = 分镜图张数;Σ durationMs = timeline.durationMs(±200ms);max(endMs) ≤ 音频时长(建议提供 audioDurationMs)。
任一不符 → MV_SELFCHECK_FAILED 打回(message 附四个实测数值),不消耗算力、不出片。→ §14.4 时间轴硬校验
https://video.livepartner.fans
所有接口统一使用该域名(HTTPS,nginx 反向代理至视频工厂服务),路径前缀为 /v1。文档中的「<你的域名>」占位符会自动替换为当前访问域名。
API_KEY,格式示例 ck_live_xxxxxxxx)。GET /v1/templates 获取可用模板,记下目标模板的 code(作为后续 template_id)与 material_spec.required 素材清单。POST /v1/video/generations 提交 template_id(可带 external_task_id 做幂等),返回 task_id。若未携带素材包,任务进入 awaiting_materials 并返回 missing_materials 缺失清单。POST /v1/video/materials(multipart 直传)或 POST /v1/video/materials/presign + confirm(OSS 预签名直传)。POST /v1/video/generations/{task_id}/commit 使任务进入 queued;也可不调用,素材齐全后任务会自动入队。GET /v1/video/generations/{task_id}(或配置 callback 接收终态回调),等待 status 变为 done。result.url 直接下载,或由平台直传至 delivery_url / result_upload 指定地址。创建 → awaiting_materials(等待素材) → queued(排队中) → rendering(渲染中) → done(完成)
├→ failed(失败,自动退款)
└→ cancelled(取消,自动退款)
素材齐全自动入队:awaiting_materials → queued
缺料提交被拒: commit → 409 + missing_materials(不入队)
MV 缺镜头脚本被拒: commit → 409 + missing_materials + declared_slots(不入队)
解析失败/超时打回: 自动回到 awaiting_materials,GET 返回 error,补齐后重新 commit
超时回收: awaiting_materials 超 24h → 自动取消并退款
status_version 每次变更自增,可用于对账与并发控制。所有终态(done/failed/cancelled)均可通过 GET /v1/video/generations/{task_id} 反复查询,结果长期有效。以下资源清单页与接入文档同域公开、无需登录,可直接发给甲方/接入方查阅选型:
| 清单 | 链接 | 说明 |
|---|---|---|
| LUT 调色滤镜库 | /lut-library.html | 204 款滤镜的黑底效果图、实测风格与参数、创作者来源;点击编号复制(详见 §16) |
| 歌词样式清单 | /lyrics-catalog.html | 156 款歌词插件的真实引擎实时预览;点击插件编号复制(plugin_id) |
| 字体库清单 | /fonts-catalog.html | 65 款字体按真实字体文件渲染样例(含中文字形标注),可下载字体文件打样 |
| 转场库 | /transition-catalog.html | 49 种转场的 ffmpeg 真实渲染动效预览、分组筛选与后端支持矩阵(详见 §15.4.3) |
以上页面数据与平台实时一致;转场/歌词清单随插件库自动更新,字体清单在字体库变更后由平台重建。
所有接口均通过 Authorization 请求头携带你的客户 API Key(即「连接码」):
Authorization: Bearer <你的_API_KEY>
未携带或无效的 Key 将返回 401 authentication_error。你可以在「设置 → 客户设置」中查看每个客户的连接码。
ck_live_ 开头,例如 ck_live_40af5b765f1b90789f4c0000。quota(可用额度);失败 / 取消自动全额退款。可通过 GET /v1/balance 实时查询。鉴权失败统一返回 401,响应体为 OpenAI 风格错误结构,请以 error.type 判断错误类型、error.code 判断 HTTP 状态码:
{ "error": { "type": "authentication_error", "code": "401",
"message": "缺少 Authorization 请求头或格式不正确",
"retryable": false, "request_id": "req-xxxxxxxx" } }
401(type=authentication_error):未携带 Authorization 请求头、格式不正确、Key 不存在 / 已被禁用 / 客户状态非正常。后端不再细分,统一以该错误类型返回。409(type=invalid_request_error):缺料提交(详见「创建生成任务」),响应体附带 missing_materials 缺失清单;MV 任务缺少镜头脚本时同样返回 409,并额外给出 declared_slots(实际收到的槽位,便于自查漏交项)。error_code 取值:MISSING_SHOT_SCRIPT(MV 缺镜头脚本)、MATERIAL_PARSE_TIMEOUT(素材解析超时 > 5 分钟)、MATERIAL_PARSE_FAILED(素材解析失败)、QUEUE_TIMEOUT(排队 30 分钟无人认领,自动退款)、MISSING_MATERIALS(素材不齐)。前两者属「可补件后重提交」,任务停在 awaiting_materials。查询当前账户可用的视频生成模型(OpenAI 风格模型列表)。/models 为兼容别名,不同第三方客户端对 Base URL 拼接方式不同,两者效果一致。
curl https://<你的域名>/v1/models \ -H "Authorization: Bearer <API_KEY>"
{
"object": "list",
"data": [
{
"id": "xinghe-cd-c1",
"object": "model",
"created": 0,
"owned_by": "xinghe",
"description": "星光1号 · 宣传片(CD)"
},
{
"id": "xinghe-mv-m1",
"object": "model",
"created": 0,
"owned_by": "xinghe",
"description": "星光1号 · 音乐MV(MV)"
}
]
}
xinghe-cd-c1 对应 CD 类模板(宣传片/纪录片),xinghe-mv-m1 对应 MV 类模板(音乐视频)。创建任务时可选择不传 model,服务端按所选模板的类别自动匹配对应模型。查询当前账户可用的视频模板及其素材要求。创建任务时必须指定一个模板的 code 作为 template_id。支持查询参数:category(模板类别,如 cd / mv)、status(上架状态,默认 enabled,仅返回已上架模板)。
curl https://<你的域名>/v1/templates \ -H "Authorization: Bearer <API_KEY>" curl https://<你的域名>/v1/templates/CD-2024-005 \ -H "Authorization: Bearer <API_KEY>"
{
"object": "list",
"data": [
{
"object": "template",
"id": "CD-2024-005",
"code": "CD-2024-005",
"name": "星光 1 号",
"category": "CD",
"status": "enabled",
"version": "1.0.0",
"ratio": "16:9",
"resolution": "1080P",
"desc": "...",
"description": "...",
"materials": "...",
"duration": "...",
"cover": "https://<你的域名>/uploads/templates/starlight-1.png",
"cover_url": "https://<你的域名>/uploads/templates/starlight-1.png",
"thumbnail": "https://<你的域名>/uploads/templates/starlight-1.png",
"sample": "https://<你的域名>/uploads/templates/sample.mp4",
"sample_url": "https://<你的域名>/uploads/templates/sample.mp4",
"preview": "https://<你的域名>/uploads/templates/sample.mp4",
"default_plugin": "plugin-001", // 可选:模板默认渲染插件编号,任务未指定 plugin_id 时使用
"template_type": "generator", // generator=生成式 / project=工程模板(含工程文件,可经 AI 翻译官适配)
"renderer": "kdenlive", // 渲染后端:kdenlive / ffmpeg(工作机按 capabilities.render_backends 匹配认领)
"ai_mode": "template-direct", // template-direct=模板直接渲染 / ai-assisted=AI 辅助
"design_resolution": { "width": 1920, "height": 1080, "fps": 30 },
"supported_resolutions": [ { "width": 1920, "height": 1080, "fps": 30 } ], // 模板支持的分辨率列表:创建任务传 output_resolution 必须命中其中一项
"decorations_schema": { "decorations": {}, "requires_plugins": [] }, // 模板装饰 schema(五项 intro/ending/watermark/corner_tl/corner_tr)
"material_spec": {
"version": "1.0.0",
"ratio": "16:9",
"default_resolution": "1080P",
"required": [
{ "key": "poster", "name": "海报图", "desc": "主视觉海报", "constraints": { "format": ["jpg","png","webp"], "max_size_mb": 10, "min_dimension": "1000x1000", "count": 1, "order": 1 } },
{ "key": "original_vocal", "name": "原唱", "constraints": { "format": ["mp3","wav","flac"], "max_size_mb": 50, "count": 1, "order": 3 } },
{ "key": "album_images", "name": "相册图", "constraints": { "format": ["jpg","png"], "max_size_mb": 20, "count": { "min": 10 }, "order": 7 } }
]
}
}
]
}
code 用于创建任务时的 template_id。category 为模板类别(cd / mv),status 为上架状态(enabled 可用 / disabled 停用,停用模板创建任务会返回 4007)。version、ratio、resolution 为模板的版本号、画幅比例、默认分辨率。material_spec.required 列出该模板渲染必需的素材清单,每个元素的 key 对应上传素材时的 type;constraints 描述该素材的文件格式(format)、大小上限(max_size_mb)、最小尺寸(min_dimension,可选)、数量(count,可为 1 或 { "min": N } 表示至少 N 份)与排序(order)。任务只有在所有 required 素材齐全后才进入 queued。注意:「海报」与「海报图」已确认为同一项物料,统一收敛为 poster,不再单独出现 poster_images。
CD-2024-005(星光1号:相册图轮播 + 卡拉OK 字幕,走渲染机)与
xinghe-cd-001(星河字画:歌词直出文字 PV,服务端编码,素材只要「歌词 + 原唱音频」,见 §18)。
查询参数口径:status 传 enabled(默认,仅已上架)或 all(含停用);
category 大小写不敏感(cd / CD 等价),cd 与 mv 均可。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
template_id | string | 是 | 工作流模板编号,如 CD-2024-005 |
prompt | string | 否 | 任务名称 / 描述 |
cust_user_id | string | 否 | 调用方业务侧的用户标识,用于关联对账,原样透传保存 |
model | string | 否 | 指定模型,如 xinghe-cd-c1;不传时服务端按模板类别自动匹配 |
resolution | string | 否 | 输出分辨率,默认 1080P(720P / 1080P) |
watermark | boolean / object | 否 | 水印配置(含独立开关)。省略或 false=无水印;true=使用客户默认水印(后台配置);对象={enabled, type:"image"|"text", ...},图片水印与文字水印二者选其一,详见「水印 / 片头片尾 / 播放器标签」 |
intro | object | 否 | 片头独立开关与资源:{enabled:true, url, type:"image"|"video"};enabled:false=关闭(用模板默认片头)。省略=按模板默认片头 |
ending | object | 否 | 片尾独立开关与资源:{enabled:true, url, type:"image"|"video"};enabled:false=关闭(用模板默认片尾)。省略=按模板默认片尾 |
labels | object | 否 | 播放器标签独立开关与覆盖文本:{player1:{enabled,title?,author?}, player2:{enabled,user_name?,platform_name?,level?}}。player1=左上角歌名标签,player2=右上角会员卡标签,enabled:false 隐藏该标签 |
song_info | object | 否 | 歌曲与用户元数据(歌名/词曲作者/歌词/用户昵称/会员等级/平台名),用于播放器卡片渲染,详见「水印 / 片头片尾 / 播放器标签」 |
plugin_id | string | 否 | 渲染插件编号(plugin-001 格式),任务级覆盖模板的 default_plugin;两者皆无时使用平台内置播放器。插件库由客户端从服务器拉取,按编号取用 |
decorations | object | 否 | 装饰组件(阶段一 P5)。固定五项 intro / ending / watermark / corner_tl / corner_tr,每项 {plugin, enabled, params}。仅需覆盖模板默认时可省略;配置合并顺序:平台全局默认 < 模板 decorations_schema < 任务 decorations。未知装饰项 / 结构非法均返回 4008。示例:{"watermark": {"plugin":"plugin-001","enabled":true,"params":{"text":"版权所有"}}} |
output_resolution | object | 否 | 动态输出规格 {width, height, fps?}(阶段一 P1)。width/height 必填正整数,fps 可选正整数。必须命中模板 supported_resolutions 中某一项(可从 GET /v1/templates 查看),否则返回 4008。省略时用 resolution 或模板默认分辨率 |
callback | string / object | 建议必配 | 生成终态(done / failed / cancelled)时的回调通知地址。可传 URL 字符串或 {"url": "..."}。配置了 api_secret 时发 HMAC-SHA256 签名回调(X-Signature / X-Timestamp / X-Nonce 防重放);未配 api_secret 时降级为无签名回调(X-Unsigned: 1)仍照常投递。投递失败按退避序列自动重试,可用 POST /v1/video/callbacks/replay 重放或用 GET /v1/video/generations/{task_id} 轮询兜底。详见「回调签名与重试」 |
priority | int | 否 | 任务优先级 1-5,默认 3 |
delivery_url | string | 否 | 客户提供的成品交付地址(支持 PUT 直传)。任务完成后成品直传该地址;平台下载地址同时返回作为兜底 |
external_task_id | string | 否 | 调用方业务侧的任务唯一标识,用于对账与幂等。若与历史任务重复且请求体一致,服务端返回已存在任务(不重复计费);若请求体不一致则返回 409 idempotency_conflict |
material_package | object | 否 | 甲方对象存储的素材包地址(结构见下方说明),服务端接收并按需拉取素材 |
result_upload | object | 否 | 甲方对象存储的成品上传地址(结构见下方说明),任务完成后成品直传该地址 |
materials | object | 否 | 内联素材(键为 type,值为文件 URL),创建时一并提交 |
片头、片尾、水印、左上角歌名标签(播放器1)、右上角会员卡标签(播放器2)都提供用户级独立开关,甲方通过 /v1/video/generations 的 intro / ending / watermark / labels 四个字段控制,无需后台介入。
{
"watermark": {
"enabled": true, // 独立开关:true=显示;false=关闭水印;省略默认 true(只要传了对象即启用)
"type": "image", // "image"=图片水印 或 "text"=文字水印,二者选其一
"image_url": "https://cdn.example.com/wm.png", // type=image 必填:http(s) 地址,服务端下载并做安全策略校验,下载失败任务将报错
"text": "星光音乐相册 · 版权所有", // type=text 必填:水印主文字
"sub_text": "video.livepartner.fans", // type=text 可选:次行文字(如网址),两行显示
"position": "bottom-right", // 可选:top-left/top-right/bottom-left/bottom-right 固定角位;省略=按模板漂浮动画
"opacity": 0.6 // 可选:0-1 透明度,省略=模板默认
},
"intro": { "enabled": true, "url": "https://cdn.example.com/intro.mp4", "type": "video" }, // 片头:enabled=false 关闭(用模板默认片头);省略=按模板默认
"ending": { "enabled": true, "url": "https://cdn.example.com/end.png", "type": "image" }, // 片尾:enabled=false 关闭(用模板默认片尾)
"labels": { // 播放器标签独立开关 + 可选覆盖文本
"player1": { // 左上角歌名标签(播放器1)
"enabled": true, // false=隐藏该标签
"title": "《星河入梦》", // 可选覆盖:歌名主标题
"author": "词:林晚 曲:陈默" // 可选覆盖:作者行
},
"player2": { // 右上角会员卡标签(播放器2)
"enabled": true, // false=隐藏该标签
"user_name": "星晴", // 可选覆盖:会员昵称
"platform_name": "星光音乐", // 可选覆盖:平台名
"level": "一级音乐人" // 可选覆盖:会员等级
}
},
"song_info": { // 若不传 labels 覆盖,则播放器标签文本取此处
"song_name": "《星河入梦》", // 歌名(labels.player1.title 缺省时显示)
"lyricist": "林晚", // 词作者 → 显示为"词:林晚"
"composer": "陈默", // 曲作者 → 显示为"曲:陈默"
"user_name": "星晴", // 用户昵称(labels.player2.user_name 缺省时显示)
"member_level": "一级音乐人", // 会员等级
"platform_name": "星光音乐" // 平台名称
}
}
说明:
watermark 兼容旧布尔语义——省略或 false=无水印;true=使用客户默认水印(后台客户资料中配置的文本或图片 URL);对象形式下 enabled:false 同样关闭。type 省略时自动推断——有 image_url→图片,有 text→文字,都没有则默认图片水印(走后台客户默认水印的图片)。type=image 需 image_url(http(s),服务端下载校验);type=text 需 text(主文字)+ 可选 sub_text(次行)。position 固定角位生效;opacity 0-1 控制透明度。type=image 的 image_url)只用于水印叠加层,绝不会被当作封面、头像、平台 Logo 等其他用途;系统内部按素材槽位严格隔离(水印固定为 watermark.png,与封面 cover.png、头像 avatar.png 互不相干)。intro / ending 传 {enabled:true, url, type:"image"|"video"} 启用并指定资源;enabled:false 关闭(退回模板默认片头/片尾);省略则按模板默认。song_name);下方文字 = 词作者 / 曲作者(lyricist→"词:X"、composer→"曲:Y",词曲整体用 songwriter→"词曲:X")。下方文字严格限定为作者信息,绝不显示演唱者/昵称。avatar 素材,缺失时用模板占位头像,绝不用封面/海报/Logo 顶替);上方文字 = 用户昵称(user_name);下方文字 = 平台标识名(platform_name,如"星光音乐")。labels.player1 / labels.player2 各自 enabled:false 即可单独隐藏对应标签;覆盖文本(player1.title/author、player2.user_name/platform_name/level)可选,不传则按上述固定归属取 song_info 对应字段。400 code=4008;labels 结构非法或对应必填项缺失均返回 4008。customer_requirements),查询任务接口原样回显(watermark / intro / ending / labels 字段)。song_info 缺省或字段不足,服务端会从 prompt 的 ```json 代码块中提取 params 自动填补(title→song_name、artist→user_name、platformName→platform_name、lyricist/composer/songwriter/memberLevel→同名或对应字段)。显式传入优先,仅缺失字段被填补;画面作品名/作者/平台名必须通过结构化字段下发。歌词可通过 song_info.lyrics 传入,也可作为素材上传(type=line_lyrics 逐行歌词 / type=word_lyrics 逐字歌词,见第 5 节)。服务端与渲染端自动识别以下三种格式,无需声明:
[mm:ss.xx] 时间戳 + 文本,支持 <mm:ss.xx> 逐字时间标签。{ "time": 秒, "end": 秒, "text": "..." }(时间单位为秒,浮点)。逐字时间缺失时按字均分。{ "word": "字", "start_s": 秒, "end_s": 秒, "_yiqiLineBreakAfter": true }(_yiqiLineBreakAfter 可选,标记该字之后换行;缺省时按每行连续字自动断行)。JSON 歌词示例(逐字,与甲方"逐字对齐 JSON"格式一致):
[
{ "word": "那", "start_s": 16.197, "end_s": 16.277 },
{ "word": "年", "start_s": 16.277, "end_s": 16.4 },
{ "word": "夏", "start_s": 16.4, "end_s": 16.6, "_yiqiLineBreakAfter": true },
{ "word": "天", "start_s": 16.6, "end_s": 16.9 }
]
行级 JSON 歌词示例:
[
{ "time": 16.197, "end": 20.146, "text": "那年夏天蝉鸣声声," },
{ "time": 20.146, "end": 24.3, "text": "风穿过旧时光" }
]
prompt 的 ```json params 中,服务端也会自动提取补入 song_info,确保画面文字出处规范、准确(prompt 本体仅作为任务描述,不直接渲染进画面)。当甲方通过自己的对象存储交换素材包与成品时,可传入以下结构。字段原样保存并透传返回,便于双方对账:
{
"material_package": {
"mode": "object_storage",
"schema_version": "cd-material-package/1.0",
"external_task_id": "admin_cd_video_test_xxx",
"package_sha256": "<ZIP_SHA256>",
"archive_sha256": "<ZIP_SHA256>",
"manifest_sha256": "<MANIFEST_SHA256>",
"package_bytes": 123456789,
"expires_at": 1786900000000,
"materials_zip": {
"method": "GET",
"object_key": "temp/cd-video/admin_cd_video_test_xxx/input/materials.zip",
"url": "https://<SIGNED_GET_URL>",
"sha256": "<ZIP_SHA256>",
"content_type": "application/zip"
},
"manifest": {
"method": "GET",
"object_key": "temp/cd-video/admin_cd_video_test_xxx/input/manifest.json",
"url": "https://<SIGNED_GET_URL>",
"sha256": "<MANIFEST_SHA256>",
"content_type": "application/json"
},
"objects": [
{
"slot": "poster",
"object_key": "temp/cd-video/admin_cd_video_test_xxx/input/objects/poster.jpg",
"url": "https://<SIGNED_GET_URL>",
"sha256": "<FILE_SHA256>",
"bytes": 245760,
"content_type": "image/jpeg"
}
]
},
"result_upload": {
"method": "PUT",
"object_key": "temp/cd-video/admin_cd_video_test_xxx/output/final.mp4",
"url": "https://<SIGNED_PUT_URL>",
"content_type": "video/mp4",
"expires_at": 1786900000000
}
}
material_package(直接兼容甲方嵌套契约):ZIP 下载地址读取优先级固定为 materials_zip.url → url → download_url → object_url;ZIP SHA-256 按 materials_zip.sha256 → archive_sha256 → package_sha256 → sha256 强校验(不匹配则 material_package_status=failed);manifest 独立从 manifest.url 下载(甲方 manifest.json 不在 ZIP 内),SHA 按 manifest.sha256 → manifest_sha256 校验;objects 原样保存透传(用于逐文件核验与单文件补取),不报未知字段错误;expires_at 为 Unix epoch 毫秒。也兼容旧的扁平写法 { "url": "...", "sha256": "..." }。
manifest 槽位映射:有 manifest 时以 materials[].slot 为准(poster / original_audio / accompaniment / album_image:{index} / platform_logo / intro_video / outro_video),album_image:{index} 按数值 index 排序;无 manifest 时才启用文件名智能推断作为人工应急兜底。
result_upload:PUT 上传地址,任务完成后成片直传该地址,PUT 请求头 Content-Type 取自 result_upload.content_type(默认 video/mp4),仅写入 url 指定的对象;HTTP 200/201/204 视为成功,回写 sha256/size/mime/width/height。进度经 result_upload_status(pending/delivering/done/failed)可查。
签名过期恢复:下载/上传的签名 URL 过期时,任务标记为「等待地址刷新」(addr_refresh),不判永久失败、不重新渲染、不重复扣费;甲方通过 POST /v1/video/generations/{task_id}/refresh 更新地址后,任务从原阶段续跑(素材下载过期只重下缺失对象,成片上传过期只重传成片)。
materials 已覆盖全部必需素材、或携带了 material_package 素材包契约,则直接进入 queued;否则一律进入 awaiting_materials(模板默认素材包仅供平台内部测试,不会替代甲方素材),待你通过第 5 节上传/登记素材齐全后才进入 queued。Idempotency-Key 或请求体 external_task_id 保证幂等。同一幂等键 + 相同请求体命中历史任务时直接返回该任务(HTTP 200),不重复计费;同一幂等键 + 不同请求体返回 409 idempotency_conflict。curl -X POST https://<你的域名>/v1/video/generations \ -H "Authorization: Bearer <API_KEY>" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: 3f2b8c9a-4d1e-4f2a-9b3c-<唯一键>" \ -d '{ "template_id": "CD-2024-005", "prompt": "周年庆主题曲", "resolution": "1080P", "watermark": { "enabled": true, "type": "text", "text": "星光音乐相册 · 版权所有", "position": "bottom-right" }, "intro": { "enabled": true, "url": "https://cdn.example.com/intro.mp4", "type": "video" }, "ending": { "enabled": true, "url": "https://cdn.example.com/end.png", "type": "image" }, "labels": { "player1": { "enabled": true }, "player2": { "enabled": true } }, "song_info": { "song_name": "《星河入梦》", "lyricist": "林晚", "composer": "陈默", "user_name": "星晴", "member_level": "一级音乐人", "platform_name": "星光音乐" }, "external_task_id": "PO-20260816-0001" }'
{
"object": "video.generation",
"id": "JH3OOFVHYNQXN0K0",
"display_id": 47,
"created": 1786257420,
"model": "xinghe-cd-c1",
"status": "awaiting_materials",
"status_version": 1,
"template_id": "CD-2024-005",
"plugin_id": "plugin-001", // 可选:实际使用的渲染插件编号(任务级覆盖,否则为模板默认值)
"resolution": "1080P",
"watermark": { "enabled": true, "type": "text", "text": "星光音乐相册 · 版权所有", "position": "bottom-right" },
"intro": { "enabled": true, "url": "https://cdn.example.com/intro.mp4", "type": "video" },
"ending": { "enabled": true, "url": "https://cdn.example.com/end.png", "type": "image" },
"labels": { "player1": { "enabled": true }, "player2": { "enabled": true } },
"song_info": { "song_name": "《星河入梦》", "lyricist": "林晚", "composer": "陈默", "user_name": "星晴", "member_level": "一级音乐人", "platform_name": "星光音乐" },
"callback": null,
"external_task_id": "PO-20260816-0001",
"delivery_url": null,
"material_package": null,
"result_upload": null,
"missing_materials": [
{ "key": "poster", "name": "海报图", "desc": "" },
{ "key": "original_vocal", "name": "原唱音频", "desc": "" }
],
"material_acceptance": {},
"estimate_seconds": 420,
"usage": { "quota": 5000, "used": 3403, "remaining": 1597, "balance": 1598.0 }
}
id 为任务编号(16 位大写字母/数字),后续查询、上传素材、轮询进度均使用该编号作为 task_id。display_id 为平台内部数字 ID,仅供对账展示,不作为接口主键。每次成功创建任务会扣除 1 次账户额度并写入账单流水(可取消/退款)。status 含义:awaiting_materials 等待素材(尚未可渲染,超过 24 小时自动取消并退款) · queued 排队中 · rendering 渲染中 · done 已完成 · failed 失败(自动退款) · cancelled 已取消(退款)。status_version 为状态版本号,每次状态变更自增,用于对账与并发控制。missing_materials 列出当前仍缺失的必需素材(对象数组,每个元素含 key/name/desc;为空数组表示已齐全)。material_acceptance 记录已上传素材的类型 → 数量映射(如 {"poster":1,"original_vocal":1};空对象表示尚无素材)。estimate_seconds 为预计等待/处理时长(秒),基于近 20 个已完成任务的中位纯处理时长(finished_at − started_at,不含排队)与当前排队数动态估算;无人排队时即接近单任务真实处理时长,无历史样本时兜底 420 秒。所有视频生成任务均由本平台大模型驱动,响应中通过 model 字段标识所使用的模型:
"model": "xinghe-cd-c1"
模型按模板类别拆分(与 /v1/models 返回的模型 ID 一致):CD 类模板使用 xinghe-cd-c1,MV 类模板使用 xinghe-mv-m1。客户端可在请求中通过可选字段 model 指定模型;不传时服务端按所选模板的类别自动匹配。
为指定任务上传自定义素材(图片 / 音频 / 视频),multipart/form-data 上传。任务渲染时将完全使用该客户上传的素材,不再使用默认素材库。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
task_id | string | 是 | 创建任务返回的任务编号(如 JH3OOFVHYNQXN0K0) |
type | string | 是 | 素材类型(canonical key):poster 封面/海报 · cover 封面(别名) · original_vocal 原唱 · accompaniment 伴奏 · word_lyrics 逐字歌词 · line_lyrics 逐行歌词 · album_images 相册图(多张) · user_avatar 用户头像 · edit_script 剪辑脚本 · intro 片头 · ending 片尾 · platform_logo 平台Logo/多行水印。兼容旧别名(original/audio→original_vocal,lyrics/lrc→line_lyrics,album/photo→album_images,logo/watermark→platform_logo,opening→intro,outro→ending,poster_image/poster_images→poster 等),服务端自动归一化。歌词类素材(word_lyrics/line_lyrics)内容支持标准 LRC 或 JSON 数组两种格式(JSON 结构见第 4 节「歌词格式」),文件扩展名不限(.lrc/.txt/.json 均可),内容自动识别 |
file | file | 是 | 素材文件。相册图可多次上传多张,按文件名排序。 |
curl -X POST https://<你的域名>/v1/video/materials \ -H "Authorization: Bearer <API_KEY>" \ -F "task_id=JH3OOFVHYNQXN0K0" \ -F "type=poster" \ -F "file=@/path/to/cover.png"
{
"object": "video.material",
"id": "JH3OOFVHYNQXN0K0",
"display_id": 47,
"type": "poster",
"filename": "poster_1786257420.png",
"url": "/uploads/<cust_id>/tasks/47/materials/poster_1786257420.png",
"size": 245760,
"task_status": "awaiting_materials",
"missing_materials": [
{ "key": "original_vocal", "name": "原唱音频", "desc": "" },
{ "key": "album_images", "name": "相册图片", "desc": "" }
],
"message": "素材已接收;仍缺 original_vocal、album_images,补齐后任务自动进入队列"
}
album_images)可多次调用本接口上传多张;封面/海报(poster)、原唱、伴奏、歌词、片头、片尾、Logo 等每类上传最新的一份即覆盖。任务只有在模板 material_spec.required 列出的所有必需素材齐全后才自动进入 queued(可渲染);否则保持在 awaiting_materials,响应中的 missing_materials 会列出仍缺失的类型。补齐后可调用 POST /v1/video/generations/{task_id}/commit 显式提交,或继续上传素材,齐全时自动入队。本接口为素材上传的首选方案。仅当本接口不可用、上传超时或文件过大导致失败时,才改用下方 OSS 预签名直传作为兜底方案。素材上传有两条等价受理的路径(2026-09-27 口径统一):
① POST /v1/video/materials(multipart 表单直传)—— 适合小文件、实现最简单;
② POST /v1/video/materials/presign + PUT + POST /v1/video/materials/confirm —— 大文件推荐:申请一个 对象存储预签名直传地址(PUT 方法),客户端拿到 put_url 后直接 PUT 上传,不经过服务器、不占服务器带宽,传完后调 confirm 登记。
两条最终都落到同一份任务素材目录与同一套验收规则上,任选其一即可。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
task_id | string | 是 | 任务编号(如 JH3OOFVHYNQXN0K0) |
type | string | 是 | 素材类型,canonical key 与上方 multipart 一致(poster/cover/original_vocal/accompaniment/word_lyrics/line_lyrics/album_images/user_avatar/edit_script/intro/ending/platform_logo,兼容旧别名,自动归一化) |
filename | string | 否 | 原始文件名(用于登记与排序,可选) |
curl -X POST https://<你的域名>/v1/video/materials/presign \ -H "Authorization: Bearer <API_KEY>" \ -H "Content-Type: application/json" \ -d '{"task_id":"JH3OOFVHYNQXN0K0","type":"poster","filename":"cover.png"}'
{
"object": "video.material.presign",
"task_id": "JH3OOFVHYNQXN0K0",
"type": "poster",
"oss_key": "materials/<cust_id>/tasks/47/poster_1786257420_cover.png",
"put_url": "https://longsir-singleaz-1304349840.cos.ap-guangzhou.myqcloud.com/materials/...?...&Signature=...",
"content_type": "任意(签名不校验该请求头)",
"expires_in": 86400,
"expires_at": "2026-09-28T00:30:00.000Z"
}
curl -X PUT "<put_url>" \ -H "Content-Type: video/mp4" \ --data-binary "@/path/to/file.bin"
put_url 有效期 24 小时(expires_in: 86400,另有 expires_at 绝对时间);直传时 Content-Type 不校验,按实际文件类型填写或省略均可(历史上曾要求 application/octet-stream,已取消)。若地址确实过期(403),重新调用一次本接口即可拿到新地址。直传完成后请调用下方 confirm 接口登记,否则素材不会进入任务。直传完成后,调用本接口登记素材。服务端会校验对象存在,并把素材拉取到任务素材目录、更新任务状态(awaiting_materials → queued)。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
task_id | string | 是 | 任务编号 |
oss_key | string | 是 | presign 响应返回的 oss_key |
type | string | 是 | 素材类型(与 presign 时一致) |
filename | string | 否 | 文件名(可选,用于登记与排序) |
curl -X POST https://<你的域名>/v1/video/materials/confirm \ -H "Authorization: Bearer <API_KEY>" \ -H "Content-Type: application/json" \ -d '{"task_id":"JH3OOFVHYNQXN0K0","type":"poster","oss_key":"materials/<cust_id>/tasks/47/poster_1786257420_cover.png"}'
{
"object": "video.material",
"id": "JH3OOFVHYNQXN0K0",
"display_id": 47,
"type": "poster",
"filename": "poster_1786257420_cover.png",
"url": "/uploads/<cust_id>/tasks/47/materials/poster_1786257420_cover.png",
"size": 245760,
"task_status": "awaiting_materials",
"missing_materials": [
{ "key": "original_vocal", "name": "原唱音频", "desc": "" },
{ "key": "album_images", "name": "相册图片", "desc": "" }
],
"message": "素材已登记;仍缺 original_vocal、album_images,补齐后任务自动进入队列"
}
4006 错误。相册图可多次 presign/confirm 上传多张。与 multipart 一致:只有模板 material_spec.required 列出的所有必需素材齐全后,任务才进入 queued。task_id 使用创建任务返回的任务编号(如 JH3OOFVHYNQXN0K0);为兼容历史数据,数字形式的历史任务内部 id 也仍可查询。
{
"object": "video.generation",
"id": "JH3OOFVHYNQXN0K0",
"created": 1786257420,
"status": "done",
"status_version": 3,
"template_id": "CD-2024-005",
"resolution": "1080P",
"progress": 100,
"external_task_id": "PO-20260816-0001",
"missing_materials": [],
"error": null,
"error_code": null,
"material_acceptance": { "poster": 1, "original_vocal": 1 },
"retry_count": 0,
"material_package_status": "ingested",
"result_upload_status": "done",
"callback_status": "sent",
"result": {
"url": "https://<你的域名>/uploads/CD-2024-005/47.mp4",
"duration": "04:15",
"size": 195035136,
"sha256": "9f2c...(成片 SHA-256 十六进制)",
"mime": "video/mp4",
"width": 1920,
"height": 1080,
"expires_in": 604800
},
"created_at": "2026-08-09 09:00:00",
"finished_at": "2026-08-09 09:07:00"
}
result.url 为成片下载地址(平台同域名下的 /uploads 路径,可直接 HTTP GET 下载)。若创建任务时提供了 delivery_url(支持 PUT 直传),任务完成后平台会优先把成品直传到该地址(失败时兜底回平台下载地址)。甲方需及时下载并转存到自己的文件桶;平台成品下载地址 expires_in 为 7 天(604800 秒),过期后重新调用本接口即可获取新的下载地址。result.sha256/mime/size/width/height 为成片完整性字段,供甲方下载后核对。material_package(甲方素材包)已实现全链路自动拉取:下载 → SHA-256 校验 → 解压(tar.gz/zip)→ manifest 验收 → 登记素材,进度经 material_package_status(pending/downloading/ingested/failed)与 ingest_note 可查。result_upload(甲方成品回传)已实现任务完成后自动 PUT 回传,回写 sha256/size/mime,进度经 result_upload_status(pending/delivering/done/failed)可查。callback_status 为终态(done/failed/cancelled)回调投递状态:sent(签名回调已投递成功)/ sent_unsigned(未配 api_secret,无签名回调已投递)/ failed(投递失败,将退避重试)/ blocked(回调地址缺失,未投递)/ 空(未到终态或未配回调);callback_attempts 为尝试次数、callback_next_at 为下次重试时间、callback_last_code/callback_last_error 为最近投递结果。 retry_count 为任务重跑次数。
当 status 不为 done 时,result 为 null。
error / error_code 在任务 failed 或 awaiting_materials(打回待补件)时给出原因,调用方可即时感知,不必等到终态;missing_materials 列出仍缺的素材项。durationMs + videoPrompt);③ 素材解析失败或超过 5 分钟未完成。打回后可通过 POST /v1/video/materials 补齐素材(或用新的 material_package 重传),再 POST /v1/video/generations/{task_id}/commit 重新入队;已生成的镜头产物会保留,只补未完成部分。pending / queued 超过 30 分钟无人认领会判失败(error_code=QUEUE_TIMEOUT,自动退款并回调);MV 任务在「素材解析 + 图生视频」阶段不适用该规则(该阶段由图生视频工作机推进,进度见镜头明细接口)。commit 会同步读取交付包清单做合规校验(缺镜头脚本立即 409,不入队、不占额度);而素材包的下载/解压/解析是后台异步完成的,其失败会以「打回待补件」+ error 的形式体现在本接口。返回当前 API Key 所属账户下最近的任务。 limit 可选,1-100,默认 20。每条记录的 id 为任务编号。
{ "object": "list", "data": [ { "id": "JH3OOFVHYNQXN0K0", "object": "video.generation", "status": "done", "template_id": "CD-2024-005", "resolution": "1080P", "progress": 100 } ] }
以下接口均使用 task_id(任务编号或数字内部 id)定位任务,请求头鉴权同其它接口。任务状态流转:awaiting_materials → queued → rendering → done / failed / cancelled。
显式提交:客户端声明素材已就绪,主动把 awaiting_materials 任务提交进入 queued。提交不绕过素材完整性校验——缺必需素材仍返回 409 并附 missing_materials,任务不得入队。
MV 模板额外校验:MV 任务必须有镜头脚本(每镜 durationMs + videoPrompt)。只提供镜头底图、没有时长与提示词的交付包无法开工,提交时会返回 409 + missing_materials,并在 declared_slots 里列出实际收到的槽位(便于自查漏交了什么)。详见 §15 MV 视频制作对接。
缺镜头脚本时的 409 响应示例:
{
"error": {
"type": "invalid_request_error",
"code": "409",
"message": "MV 素材不齐全:缺少「镜头脚本」(每镜时长与提示词)。仅提供镜头底图无法开工——每镜时长决定生成时长、提示词决定画面内容。",
"retryable": false,
"request_id": "req-xxxxxxxx"
},
"missing_materials": [
{ "key": "shot_script", "name": "镜头脚本",
"desc": "mv-shots.json:每镜 segmentIndex / shotIndex / imageUrl / videoPrompt / durationMs" },
{ "key": "shot_script_csv", "name": "或 01-镜头图/ + 02-镜头脚本.csv",
"desc": "每镜提示词 + 时长(秒)" }
],
"declared_slots": ["poster", "cover", "original_audio", "mv_shot:1", "…", "edit_script"]
}
declared_slots 全是图片/音频/剪辑脚本,没有镜头脚本类槽位(如 shot_script / mv-shots.json / 02-镜头脚本.csv)——这就是被拒的原因。注意 edit_script(剪辑脚本,概述性 md)不能替代镜头脚本。curl -X POST https://<你的域名>/v1/video/generations/JH3OOFVHYNQXN0K0/commit \ -H "Authorization: Bearer <API_KEY>"
成功返回任务详情(含 status=queued、status_version、missing_materials)与 message。错误:404 任务不存在;409 任务已结束 / 已在处理中 / 必需素材不齐全(响应体含 missing_materials 清单)。
现象:POST /v1/video/generations 返回 200(任务已创建、额度已扣),但任务随后被打回 awaiting_materials,查询接口返回 error_code=MISSING_SHOT_SCRIPT。任务不会开工,且 24 小时内未补齐会自动取消并退款。
原因:包里已有 manifest.json(其 materials[] 已声明 mv_shots_json 槽位、mv.shots_object 也写明路径 input/mv-shots.json),也有全套镜头底图 input/objects/shot/00N.jpg,但打包时漏掉了这个 JSON 文件本身。manifest 里的声明与 script_sha256 不会自动把文件补齐。
注意:edit-script.md(剪辑脚本,通常只有几行作品概述)不能替代镜头脚本——它不含每镜时长与提示词。
input/mv-shots.json{
"timeline": { "frameRate": 30, "durationMs": 134000, "audioDurationMs": 133944, "shotCount": 52, "shotMaxSeconds": 15 },
"script": {
"type": "story",
"tone": "暖橙与霓虹青蓝对撞,黄昏逆光加海雾柔化(全片风格锚,会作为前缀注入每一镜提示词)"
},
"shots": [
{
"segmentIndex": 1,
"shotIndex": 1,
"segmentType": "verse",
"lyricLine": "",
"imageUrl": "input/objects/shot/001.jpg",
"videoPrompt": "女孩站在雨夜街头,霓虹灯牌倒映在积水里,她缓缓抬头看向镜头,发丝随风微动",
"camera": "push",
"startMs": 0,
"endMs": 2576,
"durationMs": 2576
}
]
}
上面只列了 1 条示意,实际需按 manifest.mv.shot_count 给满(例如 52 条)。
| 字段 | 必填 | 说明 |
|---|---|---|
timeline.durationMs | 是 | 甲方声明的全片时长(毫秒);Σ shots[].durationMs 必须与之相等(±200ms)。缺失或为 0 会被自检闸门拦截 |
timeline.audioDurationMs | 建议 | 音频实测时长(我方对轴的首选基准)。durationMs 常为整秒取整(如 122000 vs 实测 122376),提供本字段可让双方口径完全一致 |
timeline.shotCount | 是 | 镜头数,必须 = shots.length = 包内分镜图张数 |
shots | 是 | 非空数组;整个文件唯一的硬性要求 |
shots[].videoPrompt | 是 | 该镜画面怎么动:人物动作 + 环境变化,越具体越好(空镜不得引入人物主体) |
shots[].durationMs | 是 | 该镜时长(毫秒)。缺失时回退用 endMs-startMs,两者都没有按 0 处理会导致生成异常 |
shots[].startMs / endMs | 建议 | 逐镜在音频中的起止(毫秒)。用于越界校验:max(endMs) 必须 ≤ 音频时长 |
shots[].shotIndex / segmentIndex | 否 | 镜号 / 段号,缺省分别为数组下标 / 0 |
shots[].camera | 否 | 运镜:push / pull / orbit / pan / tilt / static / front / side / closeup;也可写中文,系统会自动归一为规范相机语言 |
shots[].segmentType | 否 | 段类型(intro / verse / chorus / interlude / outro 等)。【2026-10-09 新增】poster = 甲方自带的海报分镜(占用镜头 0)——平台检测到后不再自动插入海报分镜;自带时必须遵守镜号顺延与时长规则,见 §15.4.2 |
shots[].hasPerson | 否 | 【2026-10-09 新增】本镜是否含人物。明确 false(纯风景/物件镜头)时,平台对该镜注入全镜禁人硬禁令(no people, no silhouettes, no shadows or reflections of people — landscape and objects only),防止纯风景画面里凭空幻觉出人影;未声明时按首帧画面与提示词自动判断 |
shots[].imageUrl | 否 | 会被包内 shot/NNN.jpg 按镜号覆盖(NNN = 下标+1);填写时须与包内图同源同内容,建议省略 |
shots[].endImageUrl | 是 | 【2026-10-01 新增 · v3.4 起硬要求 · 2026-10-19 覆盖海报镜】尾帧底图,与 imageUrl 配对构成首尾帧生成,用于锚定本镜的结束画面(相邻镜头接得更顺)。★ 硬要求:zip 包须包含每一镜尾帧图;包内缺失 / 上传失败 / 仅给包内相对路径 → 任务直接打回,不再静默退化为单首帧(原「自适应、不提供则照旧」口径已于 v3.4 作废)。 ★ 海报镜同样必填(2026-10-19): segmentType:"poster" 的镜头必须自带尾帧,缺帧按 MATERIAL_MISSING_END_FRAME 打回,平台不自动补齐;原「海报为开场独立镜头、不参与首尾帧衔接」表述已作废。★ 画面中的文字由模型依据 videoPrompt 生成:需要什么字就写在提示词里(内容 / 字形 / 版式),尾帧图作为构图与收束的参照。包内若单独提供尾帧,请放在 end/ · shot-end/ · lastframe/ 目录(按镜号取值),必须与 shot/ 严格分开 —— 尾帧文件也常命名为 NNN.jpg,混入首帧映射会导致首帧被尾帧覆盖 |
script.tone | 否 | 全片风格锚,作为前缀注入每一镜提示词,用于统一全片观感 |
script.style | 否 | 【2026-10-01 新增】画面制作风格约束(比 tone 更硬,如「赛博朋克霓虹夜景,高对比低饱和暗部,胶片颗粒,无柔光」)。注入每一镜提示词最前(优先级最高,附「本镜必须严格遵循、全片统一不得漂移」硬约束措辞);平台并按它做抽帧风格质检:生成后本地抽帧检查镜头内风格跳动、偏离首帧基准的色调偏移、上下黑边、过曝/欠曝,任一超标自动换 seed 重生成(指标落 score_json 可查)。不提供则一切照旧 |
shots[] 顺序必须与 input/objects/shot/001.jpg ~ 0NN.jpg 一一对应(底图按顺序配对)durationMs 应等于 timeline.durationMs(建议同时提供 timeline.audioDurationMs = 音频实测时长)max(shots[].endMs) 必须 ≤ 音频时长(任何镜头都不得越过音频终点)durationMs ≤ shotMaxSeconds(默认 15 秒),超过请拆成多个镜头manifest.mv.shot_count = 包内分镜图张数vocalUrl / originalVocalUrl),不得只给伴奏awaiting_materials、error_code=MV_SELFCHECK_FAILED,
message 内附四个实测数值(镜头数 / Σ镜头时长 / timeline.durationMs / max(endMs) / 音频实测),不消耗算力、不产出成片:
shots.length == timeline.shotCount == 包内分镜图张数|Σ shots[].durationMs − timeline.durationMs| ≤ 200msmax(shots[].endMs) ≤ 音频实测时长timeline.durationMs 与音频实测的偏差仅告警(durationMs 常为整秒取整,如 122000 vs 实测 122376;时间轴以音频实测对轴)shots[].durationMs 排布(±1 帧),不按模板默认时间轴/固定节奏,不自行补齐;Σ镜头比音频短 ≤2s 由末镜铺满,长于音频 >2s 直接打回。
input/mv-shots.json 文件真实存在(不能只有 manifest 里的声明)shots 数组非空,且每条都带 videoPrompt 与 durationMsshots 条数 = 镜头图张数 = timeline.shotCount,且顺序与文件名序号一致Σ durationMs = timeline.durationMs(±200ms),且 max(endMs) ≤ 音频时长vocalUrl / originalVocalUrl),不是伴奏若已被打回:按 error_code/message 补齐后重新提交(或调用 POST /v1/video/generations/{task_id}/commit)即可续跑;超过 24 小时任务会被自动取消并退款,重新提交即可。同一份物料包重推时,已完成的镜头成果会保留。
取消任务并自动退款(退回 1 次额度)。仅 awaiting_materials / queued / pending 状态可取消;已进入渲染阶段不可取消。
curl -X POST https://<你的域名>/v1/video/generations/JH3OOFVHYNQXN0K0/cancel \ -H "Authorization: Bearer <API_KEY>"
{
"object": "video.generation",
"id": "JH3OOFVHYNQXN0K0",
"status": "cancelled",
"message": "任务已取消,额度已退还",
"usage": { "quota": 5000, "used": 3403, "remaining": 1597, "balance": 1598.0 }
}
错误:404 任务不存在;409 已进入处理阶段无法取消。
对失败或已取消任务退还额度(failed 任务失败时会自动退款,本接口用于手动补退款场景)。每个任务仅可退款一次,重复调用返回 409。
curl -X POST https://<你的域名>/v1/video/generations/JH3OOFVHYNQXN0K0/refund \ -H "Authorization: Bearer <API_KEY>"
{
"object": "video.generation",
"id": "JH3OOFVHYNQXN0K0",
"display_id": 47,
"status": "failed",
"refunded": true,
"message": "退款成功",
"usage": { "quota": 5000, "used": 3403, "remaining": 1597 }
}
错误:404 任务不存在;409 已退款不可重复、或状态非失败/已取消。
对失败或已取消任务重新进入队列,并重新校验素材齐全度(齐全 → queued,否则 → awaiting_materials)。计费规则:已退款任务重跑重新扣费(额度不足返回 402,账单流水类型 retry_charge);未退款任务重跑沿用原扣费(流水类型 retry、金额 0)。每次重跑 retry_count +1。
curl -X POST https://<你的域名>/v1/video/generations/JH3OOFVHYNQXN0K0/retry \ -H "Authorization: Bearer <API_KEY>"
成功返回任务详情(含 retry_count)与 message(任务已重跑(原任务已退款,本次已重新扣费) 或 任务已重跑(沿用原扣费))。错误:404 任务不存在;409 状态非失败/已取消;402 已退款任务重跑时额度不足。
签名地址过期续跑:当素材包下载或成片回传的签名 URL 过期(任务详情 addr_refresh 非空、ingest_note 含「等待甲方刷新地址」),甲方用此接口更新原任务的 material_package 或 result_upload 地址后,任务从原阶段续跑——素材下载过期只重下缺失对象,成片上传过期只重传已渲染成片。不重新渲染、不重新扣费,task_id 与账单状态保持不变。
curl -X POST https://<你的域名>/v1/video/generations/JH3OOFVHYNQXN0K0/refresh \ -H "Authorization: Bearer <API_KEY>" \ -H "Content-Type: application/json" \ -d '{ "result_upload": { "method": "PUT", "object_key": "temp/cd-video/.../output/final.mp4", "url": "https://<NEW_SIGNED_PUT_URL>", "content_type": "video/mp4", "expires_at": 1786900000000 } }'
至少提供 material_package 或 result_upload 其一,二者可同时更新。成功返回刷新后的任务详情(addr_refresh 清空、对应状态回 pending)。
回调人工重放:按 event_id 重新投递一次终态回调(用于甲方漏收后的补投)。请求体:{ "event_id": "evt_xxx" }。
curl -X POST https://<你的域名>/v1/video/callbacks/replay \ -H "Authorization: Bearer <API_KEY>" \ -H "Content-Type: application/json" \ -d '{ "event_id": "evt_xxx" }'
secret 配置(建议必配,支持降级):回调签名密钥使用账户的 api_secret(在平台客户配置中维护,可轮换)。平台采用「两层兜底 + 降级兼容」:
第 1 层(签名回调)——配置了 api_secret 时发送 HMAC-SHA256 签名回调(见下方签名算法);
第 2 层(降级兼容)——若甲方未配置 api_secret,平台降级为无签名回调仍照常投递(带 X-Unsigned: 1 头明确标记,callback_status=sent_unsigned),保证甲方能收到作品回执,甲方可据此识别非签名投递并自行决定信任级别。
为安全防伪造,强烈建议甲方配置 api_secret 并校验签名。
签名算法:HMAC-SHA256(api_secret, timestamp + "\n" + nonce + "\n" + raw_body),经请求头 X-Signature / X-Timestamp(秒级时间戳)/ X-Nonce 传递。甲方需校验:签名、时间戳新鲜度(过期拒绝)与 nonce 去重(重复拒绝)。
回调体(终态 done/failed/cancelled 触发,event_id 同一任务稳定不变,便于幂等去重):
{
"event_id": "evt_xxx",
"event_type": "video.generation.done",
"task_id": "JH3OOFVHYNQXN0K0",
"external_task_id": "admin_cd_video_test_xxx",
"status": "done",
"status_version": 9,
"occurred_at": "2026-08-16T20:08:00+08:00",
"result": { "sha256": "...", "size": 12345678, "mime": "video/mp4", "width": 1920, "height": 1080, "url": "https://..." },
"error": null
}
重试策略:回调失败采用退避重试 1m → 5m → 15m → 1h → 6h → 24h(超过后保持 24h),任务详情可查 callback_attempts(尝试次数)、callback_next_at(下次重试时间)、callback_last_code(最后 HTTP 状态)与 callback_last_error(错误摘要)。同一 event_id 重复投递不重复归档,甲方按 event_id 幂等去重。
素材包验收不通过被打回时(status=awaiting_materials),平台主动推送 event_type=video.generation.material_rejected —— 甲方无需轮询即可知道被打回及原因,按 issues 逐条整改后直接重新推送(24 小时内续跑不取消)。
{
"event_id": "evt_rej_xxx",
"event_type": "video.generation.material_rejected",
"task_id": "5PTQYNVVWTATBOPD",
"status": "awaiting_materials",
"error_code": "MATERIAL_SPEC_REJECTED",
"issues": {
"invalid_materials": ["缺少主角定妆照(mv.dressImageUrl / mv.dressAvailable 均未就绪)..."],
"missing_materials": [...],
"ingest_note": "拉包/解压阶段备注,无则为 null",
"deadline_hours": 24
}
}
evt_rej_* 按「任务 + 状态版本 + 错误摘要」生成 —— 同一次打回的重试投递同 id;整改后重推再次被打回内容变化 → 新 event_id;随后终态回调各自独立。callback.url(未带则无法主动通知,甲方以轮询查询接口兑底)。查询当前账户的扣费 / 退款流水记录。limit 可选,1-200,默认 50。
{
"object": "list",
"data": [
{
"id": 1001,
"task_id": "JH3OOFVHYNQXN0K0",
"display_id": 47,
"type": "charge",
"amount": 0,
"balance_before": 1597,
"balance_after": 1596,
"note": "创建任务扣费",
"created_at": "2026-08-16 10:00:00"
},
{
"id": 1002,
"task_id": "JH3OOFVHYNQXN0K0",
"display_id": 47,
"type": "cancel_refund",
"amount": 0,
"balance_before": 1596,
"balance_after": 1597,
"note": "取消任务退款",
"created_at": "2026-08-16 10:05:00"
}
],
"has_more": false
}
type 取值:charge 创建任务扣费 · refund 失败任务退款 · cancel_refund 取消任务退款 · retry 未退款任务重跑(金额 0)· retry_charge 已退款任务重跑重新扣费。amount 为该笔流水的金额(元,当前按次计费、模板价格未配置时金额为 0);balance_before / balance_after 为扣费/退款前后的次数余额快照(扣费 1 次 / 退款 1 次),便于双方对账。视频渲染完成后存于平台存储,甲方按以下流程获取成品:
status = done;GET /v1/video/generations/{task_id},读取 result.url;result.url 为平台同域名下的成品下载地址,直接用 HTTP GET 下载即可;delivery_url(支持 PUT 直传),平台会在任务完成后优先把成品直传到该地址,失败时兜底回平台下载地址;result_upload(甲方对象存储成品地址)已上线:任务完成后成片自动 PUT 直传甲方指定对象键(携带 result_upload.content_type 请求头,仅写入 url 指定对象),失败仅重传成片、不重新渲染、不重复扣费。
{
"object": "balance",
"quota": 5000,
"used": 3403,
"remaining": 1597,
"currency": "次"
}
/v1/me 返回账户整体信息(OpenAI Organizations 风格):
{
"object": "organization",
"id": "<cust_id>",
"name": "<账户名称>",
"balance": { "quota": 5000, "used": 3403, "remaining": 1597 },
"status": "active"
}
| HTTP | type | code | 说明 |
|---|---|---|---|
| 401 | authentication_error | 401 | 缺少或无效的 API Key |
| 403 | permission_error | 403 | 账户已停用 |
| 429 | rate_limit_error | 429 | 请求过于频繁,已触发限流(响应头 Retry-After 指示可重试秒数) |
| 400 | invalid_request_error | 4001 | 参数缺失或无效(template_id / task_id / type / file 等),或文件上传失败 |
| 400 | invalid_request_error | 4006 | oss_key 与任务不匹配,或 OSS 对象不存在 |
| 400 | invalid_request_error | 4007 | 模板已停用(status=disabled) |
| 404 | not_found_error | 4041 | 模板不存在 |
| 402 | quota_error | 4029 | 账户额度不足 |
| 404 | not_found_error | 404 | 任务不存在或不属于当前账户 |
| 409 | idempotency_conflict | 409 | 幂等冲突:同一 Idempotency-Key 但请求体不一致 |
| 409 | invalid_request_error | 409 | 状态冲突:任务当前状态不允许该操作(已处理中无法取消 / 不可重复退款 / 非失败不可重跑等) |
| 503 | server_error | 503 | 存储后端未配置或暂不可用 |
| 500 | server_error | 5000 | 服务端内部异常 |
error_code(查询任务接口回传,配合 status=awaiting_materials / failed)| error_code | 含义 | 整改方式 |
|---|---|---|
MV_SELFCHECK_FAILED | 渲染前自检闸门不通过(MV 时间轴硬校验,v3.0 起):镜头数与分镜图/脚本不符、Σ镜头时长与 timeline.durationMs 偏差 >200ms、最末镜头越过音频时长等。任务转 awaiting_materials,message 内含四个实测数值,不消耗算力、不产出成片 | 按 message 数值修正包:补齐/对齐 shots[]、令 ΣdurationMs = timeline.durationMs、确保 max(endMs) ≤ 音频时长,然后 refresh 或重推 |
MATERIAL_SPEC_REJECTED | 素材包不符合分类标准(CD 需照片 / MV 需视频),或音频与镜头脚本时长不一致等硬性问题 | 按 message / invalid_materials 逐条整改后重推 |
MISSING_SHOT_SCRIPT | 包内缺少镜头脚本本体(mv-shots.json):只有镜头底图、没有每镜时长与提示词,无法开工 | 补 input/mv-shots.json(见下方「镜头脚本格式规范」) |
MATERIAL_PARSE_TIMEOUT | 素材包解析超时(下载慢、包异常) | 确认包体积 / 下载地址可用后重试 |
MATERIAL_PARSE_FAILED | 素材包解析失败(清单与内容不符、字段非法等) | 按 message 修正后重推 |
{
"error": {
"type": "authentication_error",
"code": "401",
"message": "缺少 Authorization: Bearer <API_KEY> 请求头",
"retryable": false,
"request_id": "req-20260816-a1b2c3"
}
}
retryable 表示该错误是否可通过重试解决;request_id 为本次请求的追踪 ID,便于双方对账排查。xinghe-cd-001 ——
① 歌词 + 原唱音频直接出文字 PV 成片,服务端浏览器内编码(不占渲染机队列,30s 成片实测约 2 分钟);
② 素材只要 line_lyrics + original_vocal,歌词也可用 song_info.lyrics 内嵌传;
③ 成片 H.264 + AAC(引擎原生 Opus 自动转 AAC,兼容 iOS/Safari/微信)、16:9、720P/1080P/2K/4K@30fps;
④ 歌词由引擎按节拍自动排轴,LRC 时间戳不参与对时(与 §17.2 的逐句对时口径不同,逐句卡点仍走 CD-2024-005);
⑤ 缺歌词 → awaiting_materials + MISSING_LYRICS,补料后自动回队;编码失败自动重试 2 次。
详见 §18。同版修复模板列表接口三处缺陷:status=all 此前返回空列表、
category 大小写敏感(传 cd 查不到 CD 模板)、样片地址被拼成
https://<域名>/oss://... 死链(现按对象存储现签返回,可直接播放)。timeline.durationMs 与 shotCount
必须包含海报镜(= Σ 全部镜头时长 / 总镜数;自检闸门②按甲方原值直接比对,少写海报时长会被
MV_SELFCHECK_FAILED 打回——此前文档写「无需修改」与闸门实际口径不符,已修正);
② 新增可直接照抄的 mv-shots.json 接入范例:海报镜(segmentType=poster,0→5000)+ 歌曲镜(自 5000 起顺延)+
成片时间轴对账表(0→5s 静音无字幕 / 5s→末尾 音画同步 / 总时长 = 海报段 + 音频实测)+
推包前 60 秒自查清单;
③ 明确音画口径:海报镜期间静音、无歌词字幕,歌曲音频与歌词由平台自动整体后移海报时长,甲方音频/歌词文件零改动。
渲染端配套 scripts-patch v110(一致性校验按「歌曲镜总长 = 脚本总长 − 海报段」与音频比对,海报段不再造成误拦)。
机器可读规范同步:openapi.yaml v1.3.5(segmentType 枚举新增 poster 并写明音画口径)、
mv-shots.schema.json(枚举同步 + 新增海报镜完整范例)。metadata.poster_independent_seconds 可观测字段。shots[].transition = {type, duration} 已核准全链路落地(逐镜声明 → 交付包透传 → 构建解析 → 渲染端 xfade 执行)。
文档补齐:① 声明层级改为三级(补交付包全局默认 manifest.transitions.default/per_shot,per_shot 数组下标即镜头序号);
② 转场目录数量修正为 49 项(ffmpeg 原生 46 + 预留/自研 3);③ rectopen/rectclose/fx_sparkle 标注
「当前按 fade 呈现、变体就绪后自动生效」;④ 非法 type 与 duration 超限行为明确(忽略/截断,不报错)。详见 §15.4.3。delivery.lutCode 取值口径统一(编号型) ——
本文档 §15 交付示例曾出现名称型 "TEAL_ORANGE_01",与 §16 及实际实现(滤镜库按「编号.cube」存取)矛盾;
最终口径统一为三位数字编号(001–204,含前导零,如 007),名称型取值将因库中无同名文件
按「不调色」处理并记录告警(不阻断出片)。不填 lutCode = 保持原片色彩(合法状态)。
滤镜总览与编号清单见 LUT 调色滤镜库(附 CSV 清单)。详见 §16。watermark.png(= 甲方 platform_logo 的水印副本)因文件名为英文、未被相册池排除逻辑命中,
会按字母序排在相册图之后被当成最后一张照片全屏轮播;已修复照片池排除逻辑并发布渲染补丁(v104),
水印图只以左下角小水印形式出现,不再进相册轮播。受影响时段(10-01 之后带图片水印的 CD 单)如需重制可联系重跑。segmentType=poster,默认 5000ms):
平台默认自动插入(首帧取包内海报/封面图做「海报动态化」,甲方包无需任何改动),
delivery.posterShot 可开关(enabled=false 禁用)与覆盖(durationMs / imageUrl / prompt);
成片总时长 = 原时长 + 海报时长(音轨整体延迟海报时长开场,前奏为纯画面,歌词-音乐对齐关系不变);
② 甲方也可在 mv-shots.json 自带海报镜:镜号必须顺延(海报镜占 (0,0),原镜头 shotIndex 依次 +1,不得与原镜头撞号)、
durationMs 必填、timeline.durationMs 无需修改;平台检测到自带海报镜即不再自动插入(防双海报);
③ 主体锁定(甲方口径「背景风景可以变化,主体不能变、不能出现新的人」):每一镜提示词逐镜注入
5 处人物硬约束——最高优先级主体锁定前置(提示词开头)+ 正向构成声明 + 甲方 videoPrompt 原文约束保留 +
末尾完整版收束 + hasPerson=false 镜头全镜禁人(连影子/倒影/背景人影都不允许);纯提示词约束,无任何检测环节。
详见 §15.4.2。06-视频生成要求.txt / manifest.delivery 若声明
1920×1080@30,平台按本口径统一交付,不再按原文执行;
③ 镜头脚本 schema 的 timeline.frameRate 缺省值 30 → 24(见
mv-shots.schema.json);
④ 回退通道:平台侧环境变量开关可整体恢复原文口径(需线下沟通)。material_rejected 打回主动回调:素材验收打回(status=awaiting_materials)时主动推送签名回调
(event_type=video.generation.material_rejected),payload 含 issues 结构化整改清单
(invalid_materials / missing_materials / deadline_hours=24),失败自动退避重试;
③ 查询接口 GET /v1/video/generations/{id} 的 error / invalid_materials / missing_materials 口径不变。awaiting_materials(不消耗算力、不产出成片),备注以「【素材包不予受理,请整改后重新推送】」开头逐条列明;
② 新增字段(乙方拉包即可见):mv.dressImageUrl / mv.dressAvailable(主角定妆照地址与可用性)—— 定妆照的用途是换脸依据(是否需要换脸由甲方的换脸开关决定,我方已支持 mv.faceSwap 系列字段与说明句两种形态)、mv.tailFrameReadyCount(尾帧就绪数,与 shots[].endImageUrl 对应);包内定妆照(dress/·定妆/ 目录或图)会被转存为我方可下载地址;
③ 行为变化(请注意):定妆照设为 required —— 未定妆的作品推送接单会被核验闸门拦下(提示先生成定妆照),已定妆的作品不受影响;
④ 尾帧链交叉核验:tailFrameReadyCount 与包内实际匹配到的尾帧数不一致 → 打回(堵住「声明有尾帧、包里缺图」的漏网);
⑤ 可观测:作品详情接口新增 mv_consistency,镜头级明细每镜带 end_frame_status('' 未声明/ok 可下发/blocked 地址不可下载)与 end_frame_used(生成机实际用上的尾帧字段);本地自查脚本 validate-mv-shots.mjs 同步增加「⑥ 定妆照」「⑦ 尾帧完整性」两项(与平台闸门同口径);
⑥ 机器可读规范同步:openapi.yaml 升 v1.3.3(MvMaterialResponse.mv 加上述三字段)。shots[].endImageUrl 由「可选增强」升级为硬要求 —— zip 包必须包含每一镜尾帧图(input/objects/shot-end/NNN.jpg);包内缺失、上传失败或仅给包内相对路径 → 任务直接打回报错,不再静默退化为单首帧;同时取消「下一镜首帧兜底」,严格按契约首尾帧生成。见 §15.3 镜头脚本。Authorization: Bearer <api_key> 可直接调用,按作品归属隔离(仅能查询自己客户名下的作品);原 worker 管理令牌 x-mv-admin-token 通道不变,仍可查全部作品。机器可读规范同步 openapi.yaml v1.3.2。shots[].endImageUrl(首尾帧生成,可选) ——
① 用途:与 imageUrl(首帧)配对,锚定本镜的结束画面,使相邻镜头接得更连贯,也进一步约束模型不得脱离分镜源图自由创作;
② 自适应(重要):提供该字段才启用首尾帧模式;不提供则完全按现行单首帧管线生成,行为与本次改造前完全一致、不受任何影响 —— 甲方可按需逐步接入,不提供不会造成任何兼容性问题;
③ 包内图:若单独提供尾帧图,请放 end/ · shot-end/ · lastframe/ 目录(按镜号取值),必须与 shot/ 严格分开(尾帧文件也常命名为 NNN.jpg,混入首帧映射会导致首帧被尾帧覆盖);
④ 机器可读规范同步:openapi.yaml 升 v1.3.1(MvShot 加 endImageUrl)、mv-shots.schema.json 同步。
script.style(可选)—— 全片统一的画面制作风格约束(如「赛博朋克霓虹夜景,高对比低饱和暗部,胶片颗粒」),注入每一镜提示词最前(优先级最高);平台并按它做生成后本地抽帧风格质检:镜头内风格跳动(相邻帧色度突变)、画面偏离首帧基准、上下黑边、过曝/欠曝,任一超标自动换 seed 重生成(阈值可调、指标全量留档 score_json)。不提供 style 则一切照旧(tone 与既有质检行为不变)。
mv_worker_admin_token)调用
GET /api/mv/works/{workId}/shots,查询任意作品的逐镜头生成状态、种子与质检指标(含风格抽帧检查);只读、独立令牌、不与接单/回传凭据混用。/mv-api-docs.html 保留为跳转页(旧锚点自动映射到 §15 对应小节),甲方只需保存本页一个 URL;§14 素材验收与 §15 相互交叉引用,不再出现两份文档口径不一致的情况。openapi.yaml 升级 v1.3.0,补全 MV 契约 —— 新增 POST /api/mv/inbound(接单入口)与三个需甲方实现的接口(GET /v1/mv-video/materials/{workId}、returns/complete、returns/refresh,以 x-implemented-by: provider 标注、servers 用 {api_base} 变量,可直接生成服务端骨架)、10 个组件 schema(MvMaterialResponse / MvTimeline / MvShot / MvDelivery / MvProviderReturn / MvCompleteRequest 等),并给任务 schema 补齐 error_code / mv_stage / mv_shot_done / mv_shot_total 等字段、修正 invalid_materials 为字符串数组;新增 docs/mv-shots.schema.json(镜头脚本 JSON Schema)与 docs/validate-mv-shots.mjs(零依赖本地自查脚本,与自检闸门同口径),甲方可在打包环节提前发现问题,见 §15.3+。shots.length == timeline.shotCount == 分镜图张数;|Σ shots[].durationMs − timeline.durationMs| ≤ 200ms;max(endMs) ≤ 音频实测时长;durationMs 与音频实测偏差仅告警),任一不通过即转 awaiting_materials + error_code=MV_SELFCHECK_FAILED(message 附四个实测数值),不消耗算力、不产出成片;
② 时间轴口径:全片时长以音频实测为准(新增字段 timeline.audioDurationMs 为首选基准),逐镜严格按 shots[].durationMs(±1 帧),不再使用模板默认时间轴/固定镜头节奏,Σ镜头 > 音频 + 2s 一律拦停打回;
③ 音轨基准:MV 只用原唱轨(media.vocalUrl / originalVocalUrl),不再与伴奏混播,音画同步以该轨为准;
④ 根治「素材错配」根因:素材包未就绪时禁止使用模板自带测试素材顶替(此前导致成片尾部 46.3s / 68.1s 冻结空帧:测试包 44 镜脚本覆盖了甲方 23/27 镜脚本)——现在一律打回等待;
⑤ 哈希口径(§14.6):确认我方 ingest 会重新打包 materials.zip,双方验收统一改为逐素材 sha 比对。awaiting_materials、error_code=MATERIAL_SPEC_REJECTED、message 给出可读原因),不出片、不交付;查询接口新增 invalid_materials(结构化整改问题项)、ingest_note、material_package_status 回传,便于甲方自查整改。② 交付规格:修复「登记 1080P、成片实际 720P」的链路缺陷(素材包清单未下发目标规格,且共享素材包长期复用旧包);现在渲染前强制下发目标规格,渲染端交付前用 ffprobe 校验成片规格,不符即阻止交付并自动重跑,平台侧另做交付审计(delivery_spec_ok / delivery_spec_mismatch)。已实测:登记 1080P 的任务,成片实测 1920×1080 通过审计后才入库。manifest.json 与全套 shot/00N.jpg,但漏打 input/mv-shots.json 文件本身(manifest 里声明了槽位与 script_sha256,容易误判为"已提供")。本次明确:① edit-script.md(剪辑概述)不能替代镜头脚本;② 给出 mv-shots.json 完整字段、示例与硬约束(shots[] 非空、每镜 videoPrompt + durationMs、ΣdurationMs = timeline.durationMs、单镜 ≤ shotMaxSeconds、与 shot/NNN.jpg 顺序一一对应);③ 附「打包自查 3 步」;④ 文档顶部与「任务管理」章节加醒目提示。后端同版本一并修复 mv-shots.json 解析路径的两个潜伏缺陷(videoPrompt 组装变量未定义、运镜描述二次归一化叠加重复)。callback_status 未初始化导致终态回调永不触发的缺陷(终态任务回调扫描放宽至 NOT IN ('sent','sent_unsigned','blocked'),兼容存量 none);② 任务进入终态时主动立即回调(不再等 30s 扫描),接入 done/成片回传/最终失败/取消各路径;③ 降级兼容:甲方未配置 api_secret 时降级为无签名回调仍照常投递(带 X-Unsigned: 1 头,callback_status=sent_unsigned),不再 blocked 不发,保证甲方必能收到作品回执;④ callback 字段支持 URL 字符串或 {"url":...},callback_status 状态扩展为 sent/sent_unsigned/failed/blocked;⑤ 回执投递失败按退避序列自动重试(1/5/15/60/360/1440 分钟),可用 POST /v1/video/callbacks/replay 重放 + GET /v1/video/generations/{id} 轮询双兜底。建议甲方创建任务时强制配置 callback + api_secret(签名防伪造)。estimate_seconds 由固定值改为动态估算(近 20 个已完成任务的中位纯处理时长 + 排队任务分摊并发槽位,创建任务响应同步新增 estimate_note),无人排队时不再虚报约 4400 秒;② 修复无时间戳歌词导致成品无歌词字幕的问题——纯文字歌词按歌曲总时长自动均分生成逐字卡拉OK字幕、歌词编码(GB18030/BOM)兼容、规范 .lrc 优先;③ CD 模板生成核验单移除「换脸」校验(换脸在生成海报时已完成),仅保留提示词生成校验;④ 修复用户头像兜底链路——用户头像仅采用 user_avatar 素材,缺失时使用模板内置占位头像(member.jpg),不再错误回退到封面/海报/平台 LOGO(避免平台 LOGO 被当成用户头像渲染);平台 LOGO(platform_logo)仅用于品牌感位置,封面兜底同样排除 logo/水印/poster/海报 等品牌与版式文件。watermark 支持图片水印(type=image + image_url,服务端下载并安全策略校验)与文字水印(type=text + text/sub_text/position/opacity)二选一,兼容旧布尔语义(true=客户默认水印);新增 song_info(歌名/词曲作者/歌词/用户昵称/会员等级/平台名)用于播放器卡片渲染;字段白名单校验 + 4008 错误码;随任务落库、查询回显、并写入 work 端渲染清单 customer_requirements。https://video.livepartner.fans(nginx 转发至 video-studio:8780);新增「快速开始 / 接入指引」章节与任务状态机说明;联调回归全绿(SMOKE 27 项 / FULL 90 项),含「不带素材创建 → awaiting_materials + 缺失清单 → 补齐素材 → 排队 → 出片」全链路验证。material_package(materials_zip.url + 独立 manifest.url + objects 透传,ZIP/manifest SHA 分别校验,下载地址按 materials_zip.url→url→download_url→object_url 优先级);manifest 以 slot 为准、album_image:{index} 按数值 index 排序;成片 PUT 携带 result_upload.content_type、200/201/204 视为成功;签名 URL 过期标记 addr_refresh 等待刷新 + 新增 POST /v1/video/generations/{task_id}/refresh 原任务续跑(不重新渲染、不重复扣费);回调增加稳定 event_id 幂等 + 标准回调体(event_type/status/status_version/occurred_at/result/error)+ 未配置 secret 不降级发送 + 退避重试(1m/5m/15m/1h/6h/24h)+ POST /v1/video/callbacks/replay 按 event_id 重放;远程下载 SSRF 与压缩包路径穿越/绝对路径/盘符/层级防护;账单类型补充 retry/retry_charge。material_package_status 全程可查);成片回传(result_upload PUT + 回写 sha256/size/mime/width/height,result_upload_status 可查);退款后重跑重新扣费(retry_charge);commit 不得绕过素材校验(缺料 409);签名回调(HMAC-SHA256 + timestamp + nonce 防重放,callback_status 可查);429 限流 + Retry-After;poster_image/poster_images 合并为 poster;错误码 4004→4001 统一。material_spec.required 齐全才 queued」;新增取消 / 退款 / 重跑 / 账单流水接口;创建任务接收 material_package / result_upload;补齐 status_version / missing_materials / material_acceptance 等对账字段;模板目录补充 status / version / ratio / resolution;错误码细分 4001 / 4006 / 4007 / 4041 / 409。/v1/video/generations、/v1/video/materials、/v1/templates、/v1/billing 等接口;支持 multipart 上传与 OSS 预签名直传兜底。| 分类 | 相册素材(成片画面主体) | 不满足时 |
|---|---|---|
| CD | 照片(jpg / jpeg / png / webp / bmp / tif) | 打回:相册里出现视频即视为包不合规 |
| MV | 视频片段(mp4 / mov / mkv / webm / avi / m4v) | 打回:MV 的每个镜头须完成「图生视频」并产出视频片段后才可进入渲染 |
任务状态变为 awaiting_materials,同时回传以下字段(均为可程序化处理的整改依据):
| 字段 | 含义 |
|---|---|
error | 整段整改备注,形如「【素材包不予受理,请整改后重新推送】1. … 2. …」,逐条列出问题与整改方向 |
invalid_materials | 上述备注的结构化问题项(字符串数组),便于展示与自动处理 |
error_code | MATERIAL_SPEC_REJECTED 表示「分类与媒体类型不符」;其余素材类错误码见 §1 |
missing_materials | 按模板 material_spec.required 判定仍缺的素材项 |
material_package_status | 素材包拉取与验收状态:downloading(拉取中)/ ingested(已入库)/ failed(拉取或验收失败);任务未收到素材包时为 null |
ingest_note | 包级备注(SHA-256 校验失败、下载地址过期、包内容不合规等) |
POST /v1/video/generations/{task_id}/refresh 刷新素材地址并按新包重新验收;或在创建任务时传入新的 material_packagequeued;已完成的镜头成果会保留,只补跑未完成的部分MV 任务在任何生成动作之前执行下列四条校验;任一不通过 → 任务转 awaiting_materials、error_code=MV_SELFCHECK_FAILED,
error(message)内附四个实测数值(镜头数 / Σ镜头时长 / timeline.durationMs / max(endMs) / 音频实测),
不消耗算力、不产出成片(对齐甲方整改报告 R2 / R5)。
| # | 校验项 | 口径 |
|---|---|---|
| ① | 镜头数一致 | shots.length == timeline.shotCount == 包内分镜图张数 |
| ② | 总时长对齐 | |Σ shots[].durationMs − timeline.durationMs| ≤ 200ms |
| ③ | 无越界镜头 | max(shots[].endMs) ≤ 音频实测时长(建议直接提供 timeline.audioDurationMs) |
| ④ | 声明值与实测差异 | 仅告警不拦截:durationMs 常为整秒取整(如 122000 vs 实测 122376),全片时长一律以音频实测对轴 |
成片保证:全片时长 = 音频实测(与 durationMs 偏差 ≤200ms,符合 R1 口径);逐镜按 shots[].durationMs 排布(±1 帧);
Σ镜头 比音频短 ≤2s 由末镜铺满,Σ镜头 比音频长 >2s 直接打回;成片内不存在冻结段/空画面。
| 现象 / error_code | 原因 | 整改 |
|---|---|---|
MV_SELFCHECK_FAILED | 镜头数与分镜图/脚本不一致、Σ时长与 durationMs 偏差 >200ms、镜头越过音频终点 | 按 message 里的四个数值修正 mv-shots.json 后重推 |
MISSING_SHOT_SCRIPT | 包内只有镜头底图,漏打 input/mv-shots.json 本体 | 补上脚本文件(含每镜 videoPrompt + durationMs) |
MATERIAL_SPEC_REJECTED | 媒体类型不符(MV 用照片 / CD 用视频),或音频与脚本时长不是同一版 | 换成视频片段(MV)/ 照片(CD);音频与镜头脚本对齐后重推 |
| 成片尾部出现静止/空画面 | 历史缺陷:镜头数或时长与音频不一致(本次已由自检闸门永久拦截) | 按 §14.4 自查;若仍复现请提供任务 ID,我方按 message 中四数值定位 |
我方 ingest 会重新打包 materials.zip(并可能改写清单),因此整包 sha256 不可复现;
我方对素材包的 SHA 校验仅用于「下载是否完整」,不作为拒收成片依据。双方验收统一以 逐素材 sha 比对 为准。
mv-shots.json)的格式规范、硬约束与打包自查 5 步,见
「MV 交付包:镜头脚本格式规范与打包自查」;
完整对接契约(物料包字段、自检闸门、音频基准、交付规格、联调回归 752/757/683、哈希口径)见
§15 MV 视频制作对接。
一句话说明:甲方提供 物料包(分镜图 + 镜头脚本 + 音乐)与 成片回传通道;我方负责把每张分镜图做成视频片段、严格按 shots[].durationMs 逐镜排布、以原唱轨合成音画,并把成片回传给甲方。
平台 Base URL:https://video.livepartner.fans(任务提交 / 查询接口见 §4、§6)
#339 / #340 两支成片尾部出现 46.3s / 68.1s 冻结空帧(占全片 26% / 38%)。
根因是我方在「甲方素材包尚未落地」的瞬间,把模板自带的测试素材包当成了甲方素材解析:测试包的 44 镜脚本(Σ=184950ms、另一首歌的歌词与音轨)覆盖了甲方正确的 23 / 27 镜脚本,
于是整片按 184.95s 铺、末镜被排到音频之外、音频结束后无素材填充 → 输出静止帧直到文件结束。
甲方在整改报告中「该时间轴并非来自我方物料包」的判断完全正确,我方已按下列条目逐条修复并上线。
| 甲方条款 | 要求 | 我方落地(已上线) | 甲方如何验证 |
|---|---|---|---|
| R1 | 镜头逐条按 mv.shots[] 执行;全片时长 = timeline.durationMs(±200ms);禁止模板默认时间轴、禁止自行推算/补齐 |
① 逐镜严格取 shots[].durationMs(±1 帧);② 全片时长以 timeline.audioDurationMs(缺失时取我方实测原唱时长,再缺失才用 durationMs)为准;③ 已移除「模板固定片长/固定镜头节奏」兜底路径;④ Σshots > 音频 + 2s 一律拦停打回,不出片 |
成片实测总时长与 audioDurationMs 偏差 ≤200ms;逐镜可按 startMs/endMs 抽帧核对 |
| R2 | 渲染前增「自检闸门」,不通过即停止并回报(附四个数值),不得渲染、不得兜底 | 已实现服务端自检闸门(见 §15.4),任一条件不通过 → 任务转 awaiting_materials、error_code=MV_SELFCHECK_FAILED,message 内附四个实测数值,不消耗 GPU、不出片 |
查询接口读 error_code / message;通过时我方在任务时间轴回写「MV 自检闸门通过」+ 四数值 |
| R3 | 音频必须以 media.vocalUrl(或 originalVocalUrl)为唯一基准轨,不得使用伴奏;音画严格同步 |
MV 只下发/使用原唱轨(优先取名含 original/vocal/原唱 的文件,且只认入库登记的甲方文件,避免目录内混入其它音轨被误选);全片时长与音画对齐均以该轨实测时长为基准 |
成片音轨应与 vocalUrl 内容一致(无伴奏叠加);歌词落点/口型不偏移 |
| R4 | 空镜(intro/interlude/outro)不得引入人物主体,按 videoPrompt 做氛围/空镜运动 |
空镜的镜头类型判定沿用甲方 segmentType;该镜 videoPrompt 未描述人物时,我方不额外注入人物描述 |
抽查空镜片段画面(无人脸/人物主体) |
| R5 | timeline.durationMs 缺失/为 0、shots 与分镜图数量不一致、清单与包内容不符 → 停止并回报,不得猜测或用默认值 |
自检闸门把「缺字段/数量不符/越界」一律判为不通过并打回;并新增:任务素材目录未就绪时一律打回等待,绝不再用模板测试素材顶替(本次事故根因) | 故意提交缺 timeline 或缺镜头的包,应收到 MV_SELFCHECK_FAILED / MISSING_SHOT_SCRIPT 而非废片 |
| R6 | (建议)模板侧声明「必须遵循包内 timeline.durationMs 与 shots[]」,移除固定片长/固定镜头节奏的默认值 |
已在模板侧声明该约束(material_spec 说明 + 本文档 §15.4 / §15.5),并移除固定片长/固定节奏兜底 |
模板列表 material_spec 与本文档可见 |
| R7 | 确认我方 ingest 会重新打包 materials.zip(整包 sha256 不可复现),甲方验收改为逐素材 sha 比对 |
确认:我方 ingest 会重新打包(ZIP/manifest SHA 仅用于「下载完整性」校验,不作为拒收依据);双方验收统一改为逐素材 sha 比对(见 §15.9) | 按逐素材 sha 比对即可对账一致 |
| R8 | 保持 result_upload(PUT)+ sha256/bytes 校验;启用回调时按 mv_video_material_provider_return_secret 验签 |
保持不变(见 §15.9);回调签名算法、重试与幂等 eventId 照旧 |
回传后查 result_upload_status;回调验签失败会记录并重试 |
| R9 | 用甲方测试作品走完整链路并回报:自检闸门四个数值 + 成片实测总时长 | 已接入(见 §15.8):752 / 757 / 683 逐条回报 | 对照 §15.8 的期望值与验收口径 |
{ 757 → timeline.durationMs=122000ms shots=23 Σ=122000ms max(endMs)=122000ms 原唱实测=122376ms → 闸门通过,预期成片 122.376s
752 → timeline.durationMs=100000ms shots=27 Σ=100000ms max(endMs)=100000ms 原唱实测=100536ms → 闸门通过,预期成片 100.536s }
甲方包内 durationMs 为整秒取整值(122000 / 100000),与其 audioDurationMs(122376 / 100536)差 376 / 536ms —— 属正常(见 §15.4 条件④),我方一律以音频实测对轴,不会因为这几百毫秒把成片切短。
接入凭据(3 项):
| 项 | 说明 | 示例 |
|---|---|---|
access_key | 甲方平台签发的访问密钥,我方以 Authorization: Bearer <accessKey> 调用物料接口 | mv_xxxxxxxx |
api_base | 甲方 API 基址(HTTPS,公网可达) | https://api.example.com |
work_id | 作品 ID(一个作品 = 一条 MV) | 757 |
三种交付方式(任选其一):
| 方式 | 谁主动 | 契约 | 适用 |
|---|---|---|---|
| ① 接单入口 推荐 | 甲方推送作品 ID → 我方拉物料 | POST /api/mv/inbound | 甲方物料接口已就绪、可被公网拉取 |
| ② 推素材包 | 甲方把物料包推给我方 | 创建生成任务时传 material_package(ZIP / manifest / objects[],见 §4) | 物料文件不便公网长期暴露,或按作品一次性投递 |
| ③ 线下登记 | 双方人工对接 | 把 work_id / api_base / access_key 给我方运营登记 | 联调初期、少量作品 |
方式① 接单入口契约(甲方推送 → 我方自动拉物料并投产):
# 请求头
x-mv-inbound-token: <接单令牌> # 由我方提供(平台设置项 mv_inbound_token)
# 请求体
{
"work_id": "757", // 必填(兼容 workId / id)
"api_base": "https://api.example.com", // 可选:拉取物料用的甲方基址;省略时用双方约定的默认值
"access_key": "mv_xxxxxxxx" // 可选:同上;省略时用默认值
}
# 响应
{
"code": 0,
"data": {
"work_id": "757",
"duplicated": false, // true = 已登记(幂等,复用并更新凭据)
"shot_total": 23, // 解析到的镜头数(0 = 物料未就绪或缺镜头脚本)
"pull_error": null, // 拉物料失败原因(失败不抛错,我方记录并重试)
"started": true, // 是否已自动进入生产管线
"status": "ready" // registered(登记成功但物料未就绪)/ ready(已就绪)
}
}
work_id 重复推送不会重复建作品,只更新凭据并重新拉物料。503 / 5031),不会裸奔接收;令牌错误返回 401。物料包下发(我方调用,必配)。返回结构:
{
"ready": true, // false 时我方记录待就绪并在刷新后重试(不会用其它素材顶替)
"work": { "id": 757, "title": "燃烧的十月", "artist": "某某" },
"media": {
"vocalUrl": "https://.../original-audio.mp3", // ★ 唯一音轨基准(R3)
"originalVocalUrl": "https://.../original-audio.mp3", // 二选一提供即可
"bgmUrl": "https://.../bgm.mp3" // 仅参考,MV 不使用伴奏
},
"lyrics": { "lrcUrl": "https://.../line-lyrics.lrc", "wordLrcUrl": "https://.../word-lyrics.json" },
"mv": {
"timeline": {
"frameRate": 30,
"durationMs": 122000, // 甲方声明的全片时长(整秒取整常见)
"audioDurationMs": 122376, // ★ 建议提供:实测音频时长,供我方直接对轴(首选基准)
"shotCount": 23,
"shotMaxSeconds": 15
},
"shots": [
{
"segmentIndex": 0, "shotIndex": 0,
"segmentType": "intro", // intro / lyric / interlude / outro
"lyricLine": "",
"startMs": 0, "endMs": 8857, "durationMs": 8857,
"camera": "front",
"imageUrl": "https://.../shot-001.jpg", // 图生视频输入(与包内 shot/NNN.jpg 同源同内容)
"videoPrompt": "街灯下的空镜,光影缓慢流动" // ★ 该镜视频提示词
}
// … 共 shotCount 条
]
},
"delivery": {
"aspectRatio": "16:9", "resolution": "1920x1080", "frameRate": 30,
"lutCode": "007", // ★ 2026-10-14 口径统一:滤镜编号(三位数字、含前导零,001–204,见 §16)
// 历史示例 "TEAL_ORANGE_01"(名称型)已废弃——实现/滤镜库/校验均只认编号型,
// 名称型取值会因库中无同名文件而不调色(记录告警)
"watermarkUrl": "https://.../wm.png", "watermarkPosition": "bottom-right",
"introEnabled": false, "outroUrl": "https://.../outro.mp4"
},
"providerReturn": {
"returnToken": "rt-xxx", // 回传票据(7 天有效)
"completeEndpoint": "/v1/mv-video/materials/757/returns/complete",
"allowedContentType": "video/mp4", "maxFileSizeBytes": 104857600
}
}
字段硬性要求(缺一项即被打回,我方不猜测、不兜底):
| 字段 | 必填 | 说明 / 校验口径 |
|---|---|---|
mv.timeline.durationMs | 是 | 全片时长(ms)。缺失或为 0 → 自检闸门拦截(R5) |
mv.timeline.audioDurationMs | 建议 | 音频实测时长,我方对轴的首选基准(缺失时我方自行 probe 原唱轨) |
mv.timeline.shotCount | 是 | 镜头数,须与 shots.length 和包内分镜图张数三者一致 |
mv.shots[] | 是 | 非空数组,顺序即成片顺序(按 segmentIndex → shotIndex),我方不增不减不重排 |
shots[].durationMs | 是 | 该镜时长;这是「每镜在成片里占多久」的唯一依据 |
shots[].endMs | 建议 | 用于越界校验:max(endMs) 必须 ≤ 音频时长 |
shots[].imageUrl | 建议 | 与包内 shot/NNN.jpg 同源同内容(包内图优先,按镜号取值) |
shots[].endImageUrl | 否 | 【2026-10-01 新增】尾帧底图,与 imageUrl 配对构成首尾帧生成,锚定本镜结束画面(相邻镜头接得更顺)。★ 自适应:提供了才启用首尾帧;不提供则完全按现行单首帧管线生成,与本次改造前完全一致、不受影响(无需担心兼容性)。 包内单独提供尾帧时请放 end/ · shot-end/ · lastframe/ 目录,与 shot/ 严格分开(避免尾帧覆盖首帧) |
shots[].videoPrompt | 是 | 该镜画面怎么动;空镜(intro/interlude/outro)不得引入人物主体(R4) |
media.vocalUrl(或 originalVocalUrl) | 是 | MV 的唯一基准音轨(R3)。仅提供伴奏、或音频与脚本不是同一版,会导致打回 |
delivery.resolution / frameRate | 建议 | 缺省 1920×1080 / timeline.frameRate |
我方把 MP4 以 Content-Type: video/mp4 PUT 到甲方提供的预签名地址,随后调用 complete。
{
"objectKey": "temp/mv-video/757/output/final.mp4",
"sha256": "64位小写hex(与实际文件逐字节一致)",
"bytes": 58741233,
"eventId": "evt-20260924-0001" // 幂等 ID,重复提交返回 idempotent
}
请求头需带 X-MV-Return-Token(取自物料包 providerReturn.returnToken)。
票据过期时我方调用,不新建任务。
| 文件 | 地址 | 用途 |
|---|---|---|
| 可交互接口页 推荐先看这个 | /docs/swagger.html | 浏览器打开即可按 tag 浏览全部接口(Try it out 直接发真实请求、Authorize 填 Key / 接单令牌),数据来自同一份 /openapi.yaml,无需安装任何工具 |
| 机器可读规范 | /openapi.yaml | OpenAPI 3.0 规范(v1.3.0)。已含 MV 契约:接单入口 + 三个需甲方实现的接口(标注 x-implemented-by: provider,Base URL 用 {api_base} 变量)+ 物料/回传全量 schema。可直接用 openapi-generator 等工具生成客户端 SDK或服务端骨架 |
| 镜头脚本规范 | /docs/mv-shots.schema.json | mv-shots.json 的 JSON Schema(draft 2020-12):字段类型、必填、枚举、取值范围。可接入打包 CI 做结构校验 |
| 本地自查脚本 | /docs/validate-mv-shots.mjs | 零依赖 Node 脚本,与平台「渲染前自检闸门」同一口径(含跨字段求和/越界检查,JSON Schema 表达不了的部分) |
| 示例文件 | /docs/mv-shots.example.json | 可直接拷贝改写的 mv-shots.json 样例 |
# 本地自查(打包前跑一次,提前发现会被打回的包)
node validate-mv-shots.mjs input/mv-shots.json \
--shots-dir=input/objects/shot \
--audio=input/objects/original-audio.mp3
# → 输出平台同款四数值 + 逐条问题清单;退出码 0=通过 / 1=会被打回 / 2=用法错误
# 已知音频时长时也可直接 --audio-ms=122376;加 --json 得到机器可读结果
# 生成客户端 SDK(平台接口:提交任务、查询进度) openapi-generator-cli generate -i https://video.livepartner.fans/openapi.yaml -g python -o ./sdk # 生成服务端骨架(甲方需实现的物料接口,含 DTO 与字段名) openapi-generator-cli generate -i https://video.livepartner.fans/openapi.yaml -g python-flask -o ./mv-provider \ --global-property apis=MvMaterials,MvReturns生成器会按规范里的字段类型/必填性产出强类型模型,避免手写字段名出错;把
servers[].url 的 {api_base} 替换为甲方自己的基址即可。
awaiting_materials,不消耗算力、不产出成片。
| # | 条件 | 不通过时 |
|---|---|---|
| ① | shots.length == timeline.shotCount,且等于包内分镜图张数(shot/NNN.jpg 去重计数) | awaiting_materialserror_code=MV_SELFCHECK_FAILEDmessage 内含:「MV 自检闸门不通过(已停止出片):<失败项>|实测:镜头数=N Σ镜头=Xms timeline.durationMs=Yms maxEnd=Zms 音频实测=Wms(<音轨文件>)」 |
| ② | |Σ shots[].durationMs − timeline.durationMs| ≤ 200ms | |
| ③ | max(shots[].endMs) ≤ 音频实测时长(无镜头越过音频终点) | |
| ④ | timeline.durationMs 与音频实测的偏差 只告警不拦截(甲方 durationMs 为整秒取整,常差 300–500ms;时间轴一律以音频实测为准) |
闸门通过时我方会做什么
MV 自检闸门通过:镜头数=N Σ镜头=Xms timeline.durationMs=Yms maxEnd=Zms 音频实测=Wms(<音轨文件>)(可用 GET /v1/video/generations/{id} 的 material_package_status / 时间轴查证);timeline.audioDurationMs,缺失时我方 probe 原唱轨,再缺失才用 durationMs);shots[].durationMs 排布(±1 帧),不循环、不重复、不重排、不按模板节奏;Σshots 比音频短(差值 ≤2s)时,由末镜铺满这点差值(观感连续,不产生空帧);Σshots 比音频长超过 2s → 视为脚本与音频不同版,拦停打回,不会出现「镜头被挤到音频之外」的空画面。shots[]);durationMs / 镜头数(缺则打回并回报)。node validate-mv-shots.mjs input/mv-shots.json --shots-dir=input/objects/shot --audio=input/objects/original-audio.mp3 # 退出码 0 = 通过(平台不会因此被拦);1 = 会被打回(列出逐条问题);2 = 用法错误
甲方自查伪代码(与闸门口径一致,可在提交前自跑):
assert len(shots) == timeline.shotCount == len(shot/*.jpg) assert abs(sum(s.durationMs for s in shots) - timeline.durationMs) <= 200 assert max(s.endMs for s in shots) <= audio_duration_ms # 音频实测(或 timeline.audioDurationMs) # ④ 仅提示:abs(timeline.durationMs - audio_duration_ms) 允许几百毫秒(整秒取整)
awaiting_materials,不消耗算力、不产出成片),
打回原因以「【素材包不予受理,请整改后重新推送】」开头并逐条列出。
mv.dressImageUrl 填一个可公网下载的定妆照 URL(jpg/png,单人正面半身/全身均可);
② 清单 mv.dressAvailable=true 且 zip 包内 dress/(或 定妆/)目录放主角定妆图;
③ 只在包内 dress/ 目录放图也可(我方会自动转存并回填地址)。
常见错误:清单里这两个字段留空 / null —— 留空即视为未定妆,接单被拦。input/mv-shots.json(每镜 durationMs + videoPrompt)。input/objects/shot/NNN.jpg 与镜号一一对应。input/objects/shot-end/NNN.jpg,数量与 mv.tailFrameReadyCount 声明一致。GET /v1/video/generations/{task_id} ——
status=awaiting_materials 即被打回,error 为整段整改备注、invalid_materials 为逐条问题项;
已配置回调的甲方会自动收到 material_rejected 事件(含 issues 整改清单)。整改后直接重新推送即可续跑(24 小时内不取消)。| # | 环节 | 核验内容 | 不通过时 |
|---|---|---|---|
| ① | MV 脚本 | 包内必须含 input/mv-shots.json(每镜 durationMs + videoPrompt) | 打回 awaiting_materials,备注含逐条原因 ( missing_materials / error 可查) |
| ② | 主角定妆照 | mv.dressAvailable=true,或提供可下载的 mv.dressImageUrl;包内定妆照(dress/、定妆/ 目录或图)会被转存到我方存储 | |
| ③ | MV 镜头表(含首帧) | 每一镜都必须能取到首帧画面(包内 input/objects/shot/NNN.jpg,或 shots[].imageUrl) | |
| ④ | 镜头首尾帧 | 声明 mv.tailFrameReadyCount=N 时,包内必须能匹配到 N 个尾帧图(input/objects/shot-end/NNN.jpg),与 shots[].endImageUrl 一一对应 |
| 字段 | 类型 | 说明 |
|---|---|---|
mv.dressImageUrl | string | 主角定妆照地址。包内给图时我方会转存并替换为可下载地址(cos:// / https)。用途:换脸依据 —— 是否需要换脸以换脸开关为准(见下方「定妆照的用途」) |
mv.dressAvailable | boolean | 定妆照可用性。true = 已定妆(可接单);缺失或 false 且无可下载地址 → 未定妆,接单被拦下 |
mv.faceSwap | boolean | 换脸开关(甲方提供):true = 用定妆照做换脸;false = 不换脸(不使用定妆照);未提供 = 未声明。已兼容 faceSwap / face_swap / enableFaceSwap / useDressImage / dressSwap 等别名,取值兼容布尔与 on/off、启用/不启用、是/否 |
mv.tailFrameReadyCount | integer | 尾帧就绪数,与 shots[].endImageUrl 对应。我方用它做交叉核验:声明数与包内实际匹配数不一致即打回(防止「声明有尾帧、包里缺图」) |
mv.faceSwap 系列字段,字段名冻结后无需再改;validate-mv-shots.mjs 已增加
⑥ 定妆照与⑦ 尾帧完整性两项检查(与平台核验链同一口径),建议接进打包流程,别等推过来被打回。
mv_consistency(dressImageUrl / dressAvailable / tailFrameReadyCount / tailFrameReady),
镜头级明细每镜带 end_frame_status('' 未声明尾帧|ok 可下发|blocked 声明了但地址不可下载)与 end_frame_used(生成机实际用上的尾帧字段,空 = 实际未用首尾帧)。| 项 | 默认行为(平台自动插入,甲方包无需改动) |
|---|---|
| 触发 | MV 模板默认开启,平台在镜头表构建时自动插入分镜 0;包内找不到海报图时不插入、不打回(成片结构与原来一致) |
| 首帧 | 自动取包内文件/目录名含 poster / cover / 封面 / 海报 的图片(排除 logo/头像/水印),按文件名排序取第一个 |
| 时长 | 5000ms;其他所有镜头时长严格按甲方 shots[].durationMs 不变 |
| 提示词 | 平台默认「海报动态化」模板:缓慢推近 + 光效流动 + 氛围粒子;画面有人物时保持人物身份/服装/姿态一致仅自然微动,禁止新增人物/换景/切镜 ★ 2026-10-19:画面上的文字由模型依据提示词描述生成——想出现什么字就在提示词里写明(内容/字形/版式),不要写「文字淡入 / 渐显 / 从无字显现」这类动效描述(会诱导模型拼字造字) |
| 尾帧 | 有 —— 平台自动插入的海报镜为首尾同图(尾帧 = 首帧 = 海报图),用于锚定收束画面 ★ 2026-10-19 修正:此行原写「无(海报为开场独立镜头,不参与首尾帧衔接)」已作废。海报镜参与首尾帧设计;甲方自带的海报镜必须自行提供 endImageUrl,缺尾帧直接打回(平台不补齐) |
| 音画 | 成片总时长 = 音频实测时长 + 海报时长;音轨整体延迟海报时长开始(adelay)——海报段纯画面无声开场,音轨完整不截断,歌词-音乐-画面对齐关系不变(★ 2026-10-14 起渲染端已完整实现:此前音频/歌词未后移,短前奏歌曲的歌词会压到海报画面上;平台歌词字幕层同样整体后移海报时长,海报镜期间无字幕) |
| 自检闸门 | 甲方包仍按原口径校验(Σ shots[].durationMs = timeline.durationMs ±200ms);海报时长由平台在内部两侧同步放大,不会因海报分镜触发 MV_SELFCHECK_FAILED |
| 开关与覆盖 | delivery.posterShot.enabled=false 禁用;durationMs / imageUrl / prompt 可逐项覆盖;未声明 = 默认开启 |
| 可观测 | 任务诊断 _diagnostics.posterShot:inserted 5000ms(已插入)/ not-inserted(未插入,含原因) |
对甲方的影响清单:
segment_type=poster、段号 0,原镜头段号整体顺延;(segmentIndex 0, shotIndex 0) 后,原镜头的 shotIndex 必须顺延(原第一镜改 shotIndex 1,依次类推)。
撞号会导致镜号去重丢镜(成片少一段开场、其后画面整体前移 → 画面与歌词全部错位);平台现在会对撞号镜头自动顺延兜底,但请从源头写对镜号;durationMs 必填:海报镜时长缺失/为 0 时平台按 5000ms 兜底,但请明确填写;timeline.durationMs 与 shotCount 必须包含海报镜(2026-10-14 修正,以此为准):自带海报镜时
timeline.durationMs = Σ 全部镜头 durationMs(含海报镜,±200ms)、timeline.shotCount = 总镜数(含海报镜)。
自检闸门②按甲方 timeline.durationMs 原值直接与 Σ镜头时长比对——少写海报时长会被 MV_SELFCHECK_FAILED 打回(此前文档写「无需修改」与闸门实际口径不符,已修正);startMs/endMs 建议写绝对时间轴:海报镜 0 → P,歌曲镜自 P 起依次顺延;末镜结束 ≤ 音频实测时长 + 海报段(自检闸门③上限);imageUrl(首帧)+ endImageUrl(尾帧)+ videoPrompt 三者缺一不可。
缺尾帧 → 解析阶段直接打回(status=awaiting_materials、error_code=MATERIAL_MISSING_END_FRAME),平台不做任何自动补齐 —— 既不会拿包内海报图代替,也不会用首帧「首尾同图」代替
(尾帧是本镜收束画面的锚点,也是 QA 末帧符合度校验的参照;平台代补等于替甲方编造交付内容);
尾帧上希望出现的文字,请写进 videoPrompt 由模型生成,不要写成「从首帧渐变显现」的文字动效。imageUrl / videoPrompt / hasPerson 按普通镜头格式声明;海报镜通常 5s(略低于 §15.4.4 生成甜点区下限 5.2s,属正常、不影响出片)。以下是一份可直接照抄的 mv-shots.json(海报 5s + 歌曲 3 镜示意,其余镜头同理顺延)。
核心口径一句话:海报镜排第 0 位且声明 segmentType:"poster";timeline.durationMs = 全部镜头时长之和(含海报镜);海报段静音无字幕,歌曲音画从海报结束后开始、相对关系与甲方声明完全一致。
{
"timeline": {
"durationMs": 36900, // ★ = 5000 + 6200 + 6000 + 19700(全部镜头之和,闸门② ±200ms)
"shotCount": 4, // ★ 含海报镜
"audioDurationMs": 31900, // 纯歌曲音频实测时长(不含海报段)
"frameRate": 24
},
"shots": [
{
"segmentIndex": 0, "shotIndex": 0,
"segmentType": "poster", // ★ 识别位:平台看到后不再自动插入海报镜
"durationMs": 5000,
"startMs": 0, "endMs": 5000, // 海报镜占绝对时间轴 0 → 5000
"imageUrl": "input/objects/shot/001.jpg", // 海报图首帧(与包内 shot/001.jpg 同源同内容)
"endImageUrl": "input/objects/shot-end/001.jpg", // ★ 2026-10-19 必填:海报镜尾帧(缺帧直接打回,平台不补齐)
"videoPrompt": "海报动态化:缓慢推近,光效流动,氛围粒子;保持画面主体与构图不变" +
";画面中央的标题文字『xxx』与右下角小字『xxx』随镜头缓慢推进保持清晰可读",
// ★ 文字内容直接写在提示词里,由模型生成;不要写「淡入/渐显」
"hasPerson": true // 海报含人物如实声明;纯文字/风景海报写 false
},
{
"segmentIndex": 1, "shotIndex": 1, // ★ 自带海报镜后,原第一镜镜号顺延为 1
"segmentType": "intro",
"durationMs": 6200,
"startMs": 5000, "endMs": 11200, // 自海报结束后顺延(绝对时间轴)
"imageUrl": "input/objects/shot/002.jpg",
"endImageUrl": "input/objects/shot-end/002.jpg", // 尾帧(硬要求,见 §15.3)
"videoPrompt": "(本镜画面描述,含人物约束原文)",
"hasPerson": false,
"transition": { "type": "fadeblack", "duration": 0.6 } // 与上一镜(海报镜)的衔接,见 §15.4.3
}
// … 其余歌曲镜同理:startMs/endMs 依次顺延,durationMs 建议落在 5.2~6.5s 甜点区(§15.4.4)
]
}
交付后成片时间轴(验收对账口径):
| 成片时间区间 | 画面 | 歌曲音频 | 歌词字幕 |
|---|---|---|---|
0 → 5000 | 海报镜(动态海报,segmentType=poster) | 静音(音轨延迟 5s 开始) | 无(歌词层整体后移) |
5000 → 36900 | 歌曲分镜按甲方 shots 1..N 顺延,逐镜对齐 durationMs(±1 帧) | 从 0s 起完整播放,与画面/歌词严格同步 | 从第一句起完整铺设 |
| 成片总时长 | = 海报段 + 音频实测(本例 ≈ 5000 + 31900 = 36900ms;歌曲部分与甲方声明偏差 ≤200ms) | ||
推包前 60 秒自查(自带海报镜版,全过即一次接对):
shots[0].segmentType == "poster",镜号 0/0,原镜头镜号已顺延、无撞号;timeline.durationMs == Σ shots[].durationMs(±200ms)、timeline.shotCount = 含海报镜的总镜数;timeline.audioDurationMs 填纯歌曲音频实测(不含海报段);endImageUrl 尾帧 —— 海报镜同样必带(§15.3 硬要求);海报镜缺尾帧直接打回(MATERIAL_MISSING_END_FRAME),平台不自动补齐;durationMs 落在 5.2~6.5s 甜点区;delivery.posterShot.enabled=false 关闭平台自动插入;只要包内有海报图且未声明 poster 镜,平台默认自动插入 5s 海报镜(甲方包口径不变,见上表)。口径(甲方原话):背景风景可以随镜头运动自然变化,但主体人物绝对不能变、不能出现新的人。
每镜下发给生成模型的提示词中,人物约束共 5 处、覆盖开头/中段/结尾:
| # | 位置 | 内容 |
|---|---|---|
| ① | 提示词开头(模型注意力最高处) | 【最高优先级 · 主体锁定】本镜画面从头到尾只允许出现首帧里已有的人物(首帧无人则全程无人):the video contains exactly the same person as the first frame — one and only one;除首帧已有人物外,任何新出现的人(路人、行人、背景人群、半张脸、远处人影)都是不合格画面 |
| ② | 开头(紧跟 ①) | 正向构成声明:把「禁止新人」翻转为正向画面描述(模型对正向描述遵循度远好于负面禁令)——zero additional humans in any frame |
| ③ | 中段 | 甲方 videoPrompt 原文约束逐字保留(如 No new characters, do not change scene, subject or wardrobe) |
| ④ | 结尾(80–90% 处) | 主体锁定完整版 + 【画面构成】收束句:「每一帧都只有首帧里的那个人(或无人),没有任何其他人」;背景与风景可以随镜头运动自然变化;只允许主体的自然动作与背景/光影变化,禁止切换场景/人物、禁止转场到他人画面 |
| ⑤ | 条件注入 | hasPerson=false 的镜头追加全镜禁人:no people, no human figures, no silhouettes, no shadows or reflections of people — landscape and objects only |
shots[].hasPerson 为甲方在镜头脚本中声明「本镜是否含人物」;明确 false 时平台按纯风景/物件镜头处理(注入 ⑤ 的全镜禁令)。未声明时按首帧画面与提示词自行判断(注入 ①–④)。"type":"cut" 或 "none" 可强制硬切。
| 层级 | 写法 | 说明 |
|---|---|---|
| ① 逐镜声明 (优先级最高) | mv-shots.json:{"shotIndex":2, "transition":{"type":"wipeleft","duration":0.8}, ...} | 本镜与上一镜之间的转场;duration 单位秒(0.2~1.0,超出按重叠余量自动截断,不报错) |
| ② 交付包全局默认 | manifest.json:"transitions": {"default": {"type":"fadeblack","duration":0.6}, "per_shot": [ {"type":"fadewhite"}, ... ]} | 整包统一默认转场;per_shot 按数组下标 = 镜头序号(第 N 项对应第 N 镜)对单镜覆盖;逐镜声明(①)存在时本层对该镜失效 |
| ③ 平台默认 | — | 以上均未声明时:fade 0.5s 溶解 |
| 强制硬切 | "transition":{"type":"cut"} 或 "none" | 该衔接点不做任何转场(优先级高于 ②③,低于 ① 的存在本身——① 写 cut 即硬切) |
| 非法 type | 如拼错 "wipelft" | 自动忽略(按未声明处理 → 走 ②③ 默认),不报错、不阻断出片;声明时长不保留 |
duration 上限 1.0s;过大不会损坏成片,会被自动截断到可用余量。| 分组 | type 值 | 效果 |
|---|---|---|
| 溶解类 | fade | 交叉溶解(默认) |
dissolve | 像素抖动溶解 | |
fadeblack | 经黑场过渡(段落分隔) | |
fadewhite | 经白场过渡(副歌情绪点) | |
fadegrays | 经灰度过渡 | |
fadefast / fadeslow | 快/慢溶解节奏变体(ffmpeg 7.x;旧版本自动降级 fade) | |
| 线性擦除 | wipeleft | 新画面自右向左擦入 |
wiperight | 自左向右 | |
wipeup / wipedown | 向上 / 向下擦入 | |
wipetl / wipetr | 左上角 / 右上角斜擦 | |
wipebl / wipebr | 左下角 / 右下角斜擦 | |
smoothleft / smoothright | 柔和左/右擦除(渐变边缘) | |
smoothup / smoothdown | 柔和上/下擦除 | |
distance | 距离场渐变擦除 | |
| 滑动类 | slideleft / slideright | 新画面整体滑入(左/右) |
slideup / slidedown | 滑入(上/下) | |
| 滑动类适合同场景换镜头位、歌词分段切换 | ||
| 几何开合 | circleopen | 圆形展开(开场/强调) |
circleclose | 圆形收拢 | |
rectopen / rectclose | 矩形开/合 (⚠ 预留项:当前 ffmpeg 无此原生变体,声明后自动按 fade(同声明时长)呈现,变体就绪后自动生效) | |
circlecrop / rectcrop | 圆形/矩形裁切跳变 | |
radial | 径向扫过 | |
zoomin | 推近转场(衔接海报镜/强调主体) | |
| 开合变体 | vertopen / vertclose | 垂直开/合(幕布感) |
horzopen / horzclose | 水平开/合 (⚠ 2026-10-21 拼写修正:ffmpeg xfade 的真实变体名是 horz*,此前文档写的 horizopen/horizclose 在 ffmpeg 中不存在,声明后会被静默降级为 fade;旧写法平台仍按别名兼容,新包请改用 horz*) | |
diagtl / diagtr / diagbl / diagbr | 四角对角擦除 | |
hlslice / hrslice | 水平条带擦入(左半/右半) | |
vuslice / vdslice | 垂直条带擦入(上/下) | |
| 开合类适合段落切换、情绪转折 | ||
| 特效类 | pixelize | 像素化过渡 |
hblur | 模糊过渡(梦境感) | |
squeezeh / squeezev | 水平/垂直挤压 | |
fx_sparkle | 自研粒子闪光遮罩(复用平台闪光光斑素材)(⚠ 未完成项:当前版本声明后自动按 fade(同声明时长)呈现,粒子管线接入后自动生效) | |
| 项 | 说明 |
|---|---|
| 歌词对位 | 转场只消耗每镜尾部预留的 1s 重叠余量,每镜可见时长严格等于脚本时长,画面-歌词对位零影响 |
| 版本兼容 | 渲染端启动时解析本机 ffmpeg 支持的 xfade 变体集;不支持的类型自动降级 fade(保留声明时长):如 fadefast/fadeslow 需 ffmpeg 7.x、rectopen/rectclose 为预留项、fx_sparkle 待自研管线接入——任何一项都不会报错或阻断出片 |
| 渲染引擎 | ffmpeg GPU 后端(NVENC)为主实现;kdenlive(melt) 后端兼容路径为统一溶解(样式等价扩展排期中) |
| 默认值 | 逐镜未声明且交付包无全局默认 = fade 0.5s;平台侧可配置兜底默认与 per-shot 覆盖 |
| 回退 | 声明 cut/none 保持硬切;非法 type 自动忽略(按未声明处理,走下一级默认) |
| 时长对齐(2026-10-14 核准) | 转场按声明时长精确消耗重叠余量,成片总时长严格等于音频时长(此前重叠余量固定 1s 导致逐镜累积膨胀、歌词越往后越不齐的问题已根治) |
| 单镜时长 | 生成方式 | 生成耗时(单镜实测) | 画面稳定性 | 建议 |
|---|---|---|---|---|
| < 5.2s | 按模型 124 帧下限强制补足后裁剪 | 与 5.2s 相同(多生成的部分被裁掉) | 稳定 | ⚠️ 避免白耗算力,请 ≥ 5.2s |
| 5.2 ~ 6.5s | 单段生成(124~156 帧) | 3.5 ~ 7 分钟(最快) | 最优(首尾帧锚定全覆盖) | ✅ 甜点区,强烈推荐 |
| 6.5 ~ 6.9s | 单段生成 | ~7 分钟 | 良好 | 可用 |
| 6.9 ~ 13s | 自动分段续接(2~3 段,段间真实末帧衔接) | 单段的 2~3 倍 | 稳定(无漂移窗口),带 ≤1.4× 变速 | 可用;叙事允许时建议拆成多个分镜 |
| 13 ~ 15.1s | 单段生成(模型上限 362 帧) | 最长 | ⚠️ 漂移高风险区 | 不建议;质检会拦截重做 |
| > 15.1s | 超模型单次上限,平台强制拼接 | — | — | ❌ 请拆分镜 |
| 场景 | 建议 |
|---|---|
| 主歌/副歌叙事镜头 | 5.2 ~ 6.5s/镜,按歌词乐句切分 |
| 开场 intro / 结尾 outro | 可用 7~9s 长镜(平台自动分段),或拆成 2 个 5~6s 镜(更快更稳) |
| 情绪转折 / 段落分隔 | 配合 转场 fadeblack / fadewhite,镜头各自保持甜点区时长 |
| 快节奏段落 | 3~4s 短镜可行(成片由平台裁剪),但生成耗时仍按 5.2s 计——密集短镜会拉长总生成时间 |
| 项 | 规格 |
|---|---|
| 封装 / 编码 | MP4,H.264 视频 + AAC 音频 |
| 分辨率 | 按 delivery.resolution(默认 1920×1080),等比缩放居中补边,不拉伸变形 |
| 帧率 | 按 mv.timeline.frameRate(默认 30fps) |
| 时长 | 等于 音频实测时长 + 海报前置段时长(海报分镜为独立静音开场,见 §15.4.2);歌曲部分与甲方声明的 durationMs 偏差 ≤200ms(durationMs 为整秒取整时按音频实测对齐);逐镜对齐 durationMs(±1 帧,全片累计 <200ms) |
| 画面素材 | 逐镜图生视频片段(不是静态图);按 shots[] 顺序逐镜排布,不循环、不重复、不拉伸(每镜只出现一次) |
| 无空帧保证 | 成片内不存在冻结段/空画面段:镜头始终覆盖「封面 → 主片 → 片尾」全区间;任何越界情况在闸门阶段就被打回 |
| 音频 | 以 media.vocalUrl / originalVocalUrl 为唯一基准轨(不使用伴奏),与画面严格同步(口型、歌词落点不偏移) |
| 调色 | 全片套用 delivery.lutCode,无镜头间色调跳变(缺 LUT 文件时自动降级跳过并记日志) |
| 水印 / 片头片尾 | 按 delivery 配置叠加(watermarkUrl / watermarkPosition / introEnabled / outroUrl) |
| 大小上限 | ≤ 100MB(超出会中止并报错,不产出不合格成片) |
作品状态机(mv_works.status):
registered → pulling → ready → processing → returning → completed
↘ awaiting_materials(自检闸门/素材问题打回,补齐后可续跑,24h 未补齐自动取消退款)
↘ failed(含失败原因,可修正后继续)
阶段明细:pulling / importing / ready / shots 3/23 / concat / lut:CODE / watermark / uploading / completed。
我方管理端接口(需管理员令牌 x-admin-token),供运营监控与问题处理:
x-admin-token / x-mv-admin-token 等管理令牌不随本文档公开、不设任何默认值,仅由乙方通过线下安全渠道(加密通信/密管系统)向指定对接人发放;甲方日常对接无需这些令牌——接单/回传用物料包内的一次性票据,镜头状态查询用甲方自己的 API Key(见 §15.6.1)。凭据泄露或人员变动时联系乙方作废重发。
| 方法 | 接口 | 说明 |
|---|---|---|
| POST | /api/mv/works | 登记作品(work_id / api_base / access_key,pull:true 立即拉物料) |
| GET | /api/mv/works | 作品列表(含镜头完成度 shot_done/shot_total) |
| GET | /api/mv/works/{workId} | 详情:状态、阶段、进度、交付规格、镜头级状态 |
| POST | /api/mv/works/{workId}/start | 启动 / 继续(幂等,已完成镜头自动跳过) |
| POST | /api/mv/works/{workId}/pull | 重新拉取物料(票据过期或脚本更新后) |
| POST | /api/mv/works/{workId}/shots/{seg}/{idx}/reset | 重置单个镜头重做(片段不满意时) |
| POST | /api/mv/delivery/preview | 交付包解析预览(不入库,用于提交前核对解析结果) |
甲方可凭乙方 worker 管理令牌(向星河索取后配置到甲方系统的 mv_worker_admin_token)直接查询任意作品的逐镜头生成状态与质检指标:
鉴权(二选一):
| 方式 | 凭据 | 可见范围 |
|---|---|---|
| worker 管理令牌 | 请求头 x-mv-admin-token: <乙方提供的令牌>(甲方系统配置于 mv_worker_admin_token) | 全部作品 |
| 现有 API 凭据 | 请求头 Authorization: Bearer <api_key>(即调用 /v1 接口的同一把 key) | 仅限自己客户名下的作品(按任务归属校验;查他人作品与不存在同样返回 404,不给枚举空间) |
未携带凭据返回 401;管理令牌未配置且无凭据返回 503。
响应(data.work 概要 + data.shots[] 逐镜明细,按段号→镜号排序):
| 字段 | 说明 |
|---|---|
work.shot_total / shot_done / shot_failed | 镜头总数 / 已完成 / 失败 |
shots[].status | pending / generating / done / failed |
shots[].durationMs / segmentIndex / shotIndex | 与镜头脚本一致 |
shots[].seed / attempts / regenAttempts | 生成种子(可复现)与重试次数 |
shots[].error | 失败原因(如有) |
shots[].score | 质检指标:首帧一致性 ssim、清晰度 sharp、运动量 motion、黑帧占比 black_ratio,以及风格抽帧检查 style(帧间色度跳变 jump_uv / 偏离首帧基准 dev_uv / 黑边 / 过曝欠曝,超标镜头已自动换 seed 重生成) |
curl -H "x-mv-admin-token: <令牌>" \
"https://video.livepartner.fans/api/mv/works/{workId}/shots"
MV 相关错误码与 §12「任务级 error_code」一致,这里给出 MV 场景下的整改动作:
error_code | 含义 | 整改方式 |
|---|---|---|
MV_SELFCHECK_FAILED |
自检闸门不通过(§15.4 四条件之一):镜头数与分镜图/脚本不符、Σ时长与 timeline.durationMs 偏差 >200ms、最末镜头越过音频等。message 内含四个实测数值 |
按 message 里的数值修正包:补齐/对齐 shots[]、令 ΣdurationMs = timeline.durationMs、确保 max(endMs) ≤ 音频时长,然后 refresh 或重推 |
MATERIAL_SPEC_REJECTED | 素材包不符合分类标准(CD 需照片 / MV 需视频),或音频与镜头脚本不是同一版 | 按 message / invalid_materials 逐条整改后重推 |
MISSING_SHOT_SCRIPT | 包内缺少镜头脚本本体(mv-shots.json):只有镜头底图、没有每镜时长与提示词,无法开工 | 补 input/mv-shots.json(格式见 MV 交付包镜头脚本格式规范) |
MATERIAL_PARSE_TIMEOUT / MATERIAL_PARSE_FAILED | 素材包解析超时 / 解析失败(清单与内容不符、字段非法等) | 确认下载地址与包体完整后重试;按 message 修正后重推 |
401 票据无效/过期 → 走 returns/refresh 换票;400 sha256/bytes 与文件不一致 → 重新上传;回传 PUT 支持 200/201/204 视为成功。按甲方要求,用甲方提供的测试作品走完整链路,并回报「自检闸门四个数值 + 成片实测总时长」。
| 作品 ID | 期望 durationMs | 期望镜头数 | 我方回报内容 | 验收口径 |
|---|---|---|---|---|
| 752 | 100536 | 27 | ① 镜头数(含包内分镜图张数) ② Σ shots[].durationMs(含与 timeline.durationMs 偏差)③ max(shots[].endMs) 与音频实测时长④ 音频实测时长(原唱轨) ⑤ 成片实测总时长 / 分辨率 / 帧率 | 成片总时长 == durationMs(±200ms)镜头数 == 分镜图数 == shotCount无冻结段/空画面 音画同步(歌词落点不偏移) |
| 757 | 122376 | 23 | ||
| 683 | 133944 | 52 |
{ 757 → 镜头数 23 = shotCount 23 = 包内分镜图 23;Σ=122000ms = durationMs 122000ms(偏差 0)
max(endMs)=122000ms ≤ 原唱实测 122376ms → 闸门通过,预期成片 122.376s
752 → 镜头数 27 = shotCount 27 = 包内分镜图 27;Σ=100000ms = durationMs 100000ms(偏差 0)
max(endMs)=100000ms ≤ 原唱实测 100536ms → 闸门通过,预期成片 100.536s }
683 待甲方物料接口就绪后走同一链路回归。
| 项 | 口径 |
|---|---|
| 素材包整包 sha256 | 不可复现:我方 ingest 会重新打包 materials.zip(并可能改写清单),因此双方验收不使用整包 sha,改为逐素材 sha 比对 |
| 下载完整性校验 | 我方仍按甲方提供的 ZIP/manifest SHA 校验「下载是否完整」,校验失败视为传输问题并重试(不作为拒收成片依据) |
| 成片回传 | PUT result_upload.url(Content-Type: video/mp4)→ 调 returns/complete(objectKey + sha256 + bytes + eventId) |
| 回调验签 | 启用回调时按 mv_video_material_provider_return_secret 验签;校验失败会记录并进入退避重试(1/5/15/60/360/1440 分钟) |
MV_SELFCHECK_FAILED,附四个数值),不再产出带空尾的成片。durationMs 差了几百毫秒? A:正常。甲方 durationMs 常为整秒取整(如 122000),实测音频为 122376;我方一律以音频实测对轴,偏差仍在 R1 允许的 ±200ms 口径内(以 audioDurationMs 为准)。vocalUrl(或 originalVocalUrl)为唯一基准轨;仅提供伴奏会导致音画/歌词落点对不上,我方会打回。shots.length、timeline.shotCount、包内分镜图张数三者必须一致,否则闸门拦截(MV_SELFCHECK_FAILED),不会「按经验补」。awaiting_materials 等待(不会用任何其它素材顶替开工);补齐后 refresh 或重推即可续跑,已完成的镜头成果保留。成片调色由平台统一完成,你只需在交付里给编号(lutCode),不需要提供滤镜文件。滤镜总览(每个滤镜的黑底效果预览图、实测风格与参数、创作者来源)在此公开查看,无需登录:
→ 打开 LUT 调色滤镜库 (可搜索、按风格/创作者筛选、点编号复制)
| 调用字段 | delivery.lutCode(随交付文件下发) |
| 取值 | 滤镜库中的「编号」,纯数字(001–204),例如 007 |
| 套用方式 | 对成片整体套用一次(全片一致,镜头之间无色偏跳变) |
| 一致性要求 | 编号须与库中完全一致(三位数字,含前导零,如 007);写错或库中不存在 → 该片不调色并记录告警,不阻断出片 |
| 不调色 | 不填 lutCode 即保持原片色彩(合法状态) |
| 选型提示 | 标注「LOG/平面专用」的滤镜是为 LOG/平面素材设计的,直接套常规成片会发灰,慎用;「饱和」为负表示整体降饱和(胶片感) |
口径变更记录(2026-10-14):lutCode 最终统一为编号型(三位数字、含前导零,001–204,如 007)——与滤镜库、渲染校验实现一致。本文档 §15 示例曾出现名称型 "TEAL_ORANGE_01",属早期遗留,已废弃;名称型取值将因库中无同名文件而按「不调色」处理并记录告警。
如需完整清单(含缩略图与参数)的表格文件(Excel / CSV),可向对接人索取;线上总览页即上述链接。
2026-10-22 定版。本节把甲方最常问的三件事一次讲清楚:歌词怎么带、字体能不能指定、转场怎么声明。每项都标注了实现状态,请按状态列判断能否在本期使用。
line_lyrics / word_lyrics)+ 平台自动加前置段偏移;转场走交付包 manifest.transitions(包级)或 MV 的 mv-shots.json → shots[].transition(逐镜);字体随歌词——由歌词样式整体决定(CD 内置卡拉OK / MV 歌词插件),不单独指定、也无预留字段(见 §17.3)。
| 维度 | 甲方怎么带 | 字段 / 位置 | 适用 | 状态 |
|---|---|---|---|---|
| 歌词(行级) | 作为素材上传,类型 line_lyrics |
.lrc(标准 LRC 或 <mm:ss.xx> 增强逐字)/ 行级 JSON | CD + MV | ✅ 已生效 |
| 歌词(逐字) | 作为素材上传,类型 word_lyrics |
逐字 JSON(word / start_s / end_s);CD 用它做逐字扫色,MV 供歌词插件驱动 | CD + MV | ✅ 已生效 |
| 歌词(内嵌文本) | 创建任务时直接传文本 | song_info.lyrics(传文本内容,不是 URL;落成 lyrics.txt,无时间轴、优先级最低) | CD + MV | ✅ 已生效 |
| 逐镜歌词文案 | 物料包内声明 | mv-shots.json → shots[].lyricLine(该镜画面期的歌词文案) | MV | ✅ 已生效 |
| 转场(逐镜) | 物料包内声明 | mv-shots.json → shots[].transition = {type, duration} | MV | ✅ 已生效 |
| 转场(包级) | 交付包 manifest.json 顶层 |
transitions.default = {type,duration}、transitions.per_shot = [...] | CD + MV | ✅ 已生效 (CD 生效范围见 §17.4) |
| 字体 | — | 无字段,字体随歌词:由歌词样式整体决定(CD 内置卡拉OK / MV 歌词插件),见 §17.3 | CD + MV | — 不单独指定 (已定版不做) |
① 三种给法(任选其一,不要重复上传互相矛盾的两份):素材上传 line_lyrics(行级)/ word_lyrics(逐字)/ 创建任务时 song_info.lyrics 内嵌文本(纯文本,平台自行断句,无时间轴,只适合不需要精确对时的场景)。
② 优先级(同一包内多份并存时):word_lyrics(逐字 JSON)> line_lyrics(行级 .lrc)> 文件名含 lrc 的其它文件 > 纯文本兜底(含 song_info.lyrics —— 平台会把它落成 lyrics.txt,优先级最低)。建议同时给 line_lyrics 与 word_lyrics:行级管文案与断行,逐字管逐字高亮。
③ 时间基准(最高频的错,必看):所有时间戳一律是歌曲音频自身的时间轴,从音频第 0 秒起算。平台负责把歌词整体后移到画面上对应位置:
| CD(相册) | 前置封面 5s → 歌词整体 +5s。首句 [00:18.13] 实际出现在成片 23.13s |
| MV | 前置海报镜 P 秒(shots[0].durationMs / 1000)→ 歌词与音频一起整体 +P 秒 |
| 甲方禁止 | 不要自己加偏移(不要把 18.13 写成 23.13)。加了就整体晚一段,且平台无法识别 |
④ 覆盖要求:LRC 时间戳须连续覆盖到音频结束。渲染口径:每句显示到下一句开始为止;最后一句按自身时长结束(≈ 每字 0.38s,「别急着」3 字 ≈ 1.5s),平台不会把末句延长到音频/片尾,之后到音频结束为空白无词区。中间缺行同理会出现空白窗。(实测案例:某 CD 单 LRC 仅 11 行、末句 [00:55.22]别急着 → 成片 61.7s 后到片尾 80.6s 全部无词;平台不补句。)若末尾空窗明显(> 3s),请甲方自查补齐。
⑤ 编码:UTF-8(可带 BOM)优先;GB18030 自动兜底。请勿用 UTF-16(会整包解析失败)。
⑥ 常见错误
| 现象 | 原因 / 处理 |
|---|---|
| 整片无歌词 | 包内没有 line_lyrics/word_lyrics 类型素材(只放了 lyrics.txt 且创建任务也没传 song_info.lyrics)→ 该片按「无歌词」渲染,不报错 |
| 歌词整体早/晚 N 秒 | 时间戳基准错(见 ③)。整段等差偏移 = 甲方自己加了/漏了前置段偏移 |
| 中间某段没歌词 | LRC 该段缺行(常见于间奏后漏行),平台不会补 |
| 后半段没歌词 | LRC 提前结束(见 ④) |
| 歌词乱码 / 整包解析失败 | UTF-16 或 GBK 存成了 UTF-8 声明,重存为 UTF-8 |
| MV 某镜没有该镜文案 | shots[].lyricLine 未填(该字段是画面文案,与音频对时无关;不填则只显示 LRC 对应行) |
① 各产出的字体来源(固定)
| 产出 | 字体与版式(固定) |
|---|---|
| CD(星光1号) 卡拉OK字幕 |
字体 Microsoft YaHei(微软雅黑)· 字号 60px(设计分辨率 1920×1080,其它输出分辨率等比缩放)· 未唱=金色 #FFD878、已唱=白色 #FFFFFF(逐字扫色)· 黑色描边 3px + 阴影 · 粗体 · 字距 5px · 底部居中(左右留白 55px、下边距 48px)· 单行不换行(WrapStyle=2) |
| MV 歌词 | 由所选歌词插件决定(如 plugin-023「多彩手写」:手写体 + 逐词多彩 + 三行 + 黄金分割锚点)。字体、字号、配色、入场动画都是插件样式的一部分,从平台字体库取 |
| 片名 / 歌手卡 (播放器样式) |
由模板(player 模板)决定,与歌词字体互不影响 |
② 平台字体库:内置 65 款(原始 51 + 开源替代 14),可按编号 / 平台 ID 查阅与下载,公开清单页:字体清单。字体库的用途是给歌词插件/模板用,不是给甲方按任务指定——同一作品所有集数的字体由所选歌词样式一致决定。
③ 想换字体怎么办:换歌词插件(MV)或换模板(CD),即「换整套歌词样式」。不支持只换字体(只换字体必然带字号/行距/描边一起变,属于新样式)。需要新样式走平台侧新增插件/模板,之后甲方按编号选择即可。
变更说明:v3.15 初稿曾给出 typography 任务级覆盖草案(font_family / font_id / size_px / 颜色 / 边距)。评估结论为不实现:自定义字体必须以 ASS [Fonts] 内嵌方式下发才能保证渲染机可用(仅靠文件名匹配时 libass 会回退),成本与稳定性都不划算,且会与插件样式规范冲突。该草案已删除,文档不再保留,避免甲方误以为可传。
完整类型目录(49 项,含 fade / wipeleft / slideup / circleopen …)与各类型观感说明见 §15.4.3 转场系统,线上可搜版:转场库。
① 声明位置与优先级(高 → 低)
| 层级 | 位置 | 适用 |
|---|---|---|
| 逐镜声明(最高) | mv-shots.json → shots[i].transition = {type, duration} | MV |
| 包级 per_shot | manifest.json → transitions.per_shot[k] | CD + MV |
| 包级 default | manifest.json → transitions.default | CD + MV |
| 转场插件 / 后台默认 | 平台侧配置(甲方无需关心) | CD + MV |
| 兜底 | fade 0.5s | CD + MV |
② 下标语义:per_shot[k] 是第 k 个镜头(图片)与它前面那个的衔接,下标从 1 开始有效(k=0 无前镜,忽略)。CD 的 k = 相册图序号;MV 的 k = 镜头序号(含海报镜)。
③ 取值规则(两端一致):type 必须是目录内名称,写错/库中不存在 → 该处忽略并回落自定义,不阻断出片;duration 单位秒,夹取 0.2–1.0s;type 为 cut / none 或 duration ≤ 0 = 硬切(不重叠、不淡化)。
④ CD 与 MV 的能力差异(重要)
| 后端 | 类型(type) | 时长 / 硬切 |
|---|---|---|
| MV(ffmpeg) | ✅ 49 项全部生效(真实 xfade) | ✅ 生效 |
| CD(kdenlive/melt) | ⚠ 视觉统一为交叉溶解(擦除/开合/几何类样式不体现) | ✅ 生效 |
即:CD 只能控「转场多久、要不要硬切」,控不了「用什么花样」;需要 CD 使用真实 xfade 样式属后端切换事项,未在本期范围内。
⑤ 示例(CD,包级)
"transitions": {
"default": { "type": "fade", "duration": 0.8 },
"per_shot": [
null, // k=0 无前镜,忽略
{ "type": "wipeleft", "duration": 0.6 }, // 第 1→2 张
{ "type": "cut" }, // 第 2→3 张:硬切
{ "type": "fade", "duration": 1.0 } // 第 3→4 张
]
}
⑥ 示例(MV,逐镜)
{ "shots": [
{ "index": 0, "durationMs": 5000, "segmentType": "poster", "transition": { "type": "cut" } },
{ "index": 1, "durationMs": 6000, "transition": { "type": "fade", "duration": 0.5 } },
{ "index": 2, "durationMs": 5000, "transition": { "type": "wipeleft", "duration": 0.6 } }
] }
| 情况 | 平台行为 |
|---|---|
| 歌词缺失(整片无歌词素材) | 不阻断,渲染无歌词成片;任务正常完成 |
| 歌词时间戳错位(甲方加了偏移) | 不阻断,按错位渲染;需甲方重推修正 |
误传字体字段(如 typography) | 忽略,按歌词样式渲染,不报错、不告警 |
转场 type 写错 | 不阻断,该处按默认/自定义转场渲染,记录日志 |
转场 duration 超范围 | 夹取到 0.2–1.0s 后使用 |
| MV 逐镜声明与包级冲突 | 逐镜优先 |
□ 歌词:包内有 line_lyrics(.lrc)或 word_lyrics(逐字 JSON),UTF-8 □ 歌词:时间戳从音频 0 秒起算(不加封面/海报偏移),且覆盖到音频结尾 □ 转场:manifest.json(或 MV 的 mv-shots.json)里 type 是目录内名称、duration 在 0.2–1.0s □ 字体:不用管(字体随歌词,不单独指定);确需换字体请换歌词插件/模板
一句话:给「歌词 + 原唱音频」,出一支歌词同步的文字 PV成片。模板编号 xinghe-cd-001,由服务端直接编码(不排队占渲染机),比 MV 快得多。
| 项 | 值 |
|---|---|
template_id | xinghe-cd-001(模板列表接口的 code) |
| 名称 / 类别 | 星河字画 / CD;status=enabled |
| 画幅 / 默认分辨率 | 16:9 / 1080P(resolution=1080P) |
| 可选分辨率 | 720P / 1080P / 2K(1440P) / 4K(2160P),帧率固定 30fps(对应 supported_resolutions) |
| 成片时长 | ≈ 音频时长(实测 30.0s 音频 → 30.03s 成片);未传音频时按歌词行数自动定时长 |
| 编码规格 | H.264(avc1)+ AAC,MP4 容器(浏览器 / 微信 / iOS 均可直接播放) |
| 样片 | 模板列表接口 sample_url(30 秒真机样片,可直接播放确认观感) |
素材 type | 必填 | 格式 / 上限 | 说明 |
|---|---|---|---|
line_lyrics | ✅ 必填 | .lrc / .txt,≤ 1MB | 歌词文本,一行一句。也可改用 song_info.lyrics 内嵌传(见 18.3) |
original_vocal | ✅ 必填 | mp3 / wav / flac / m4a,≤ 50MB | 原唱音频。决定成片时长与歌词排轴节拍,且作为成片音轨 |
album_images | 可选 | jpg / jpeg / png / webp,≤ 20MB/张,最多 12 张 | 画面底图(不传则为引擎默认动效底) |
cover | 可选 | jpg / png / webp,≤ 10MB | 封面图(作品封面展示用) |
queued(与 §3 模板列表返回的 material_spec.required 一致);缺料时任务停在
awaiting_materials,missing_materials 逐项告诉你还缺哪一项 —— 补齐后自动回队,不用重新建单。
| 给法 | 写法 | 推荐度 |
|---|---|---|
① 素材上传 line_lyrics | 标准 LRC([00:12.34]那一句歌词)或纯文本,一行一句 | ✅ 推荐 |
② song_info.lyrics | 创建任务时把整段歌词作为字符串传入(\n 分行) | 可用(省一次上传) |
CD-2024-005(星光1号,走卡拉OK 逐字对时),不是本模板的能力。
编码:UTF-8(可带 BOM);不要 UTF-16。 不要在歌词里加 [ti:] / [ar:] 之外的舞台指令(会当普通文本处理)。
output_resolution)
{
"output_resolution": { "width": 1920, "height": 1080, "fps": 30 }
}
取值必须命中模板 supported_resolutions,否则返回 4008:
| 档位 | width × height @ fps |
|---|---|
| 720P | 1280 × 720 @ 30 |
| 1080P(默认) | 1920 × 1080 @ 30 |
| 2K | 2560 × 1440 @ 30 |
| 4K | 3840 × 2160 @ 30 |
不传则按模板默认 1080P 输出。当前模板为 16:9;竖屏(9:16)等其它画幅需另开模板,未在本模板范围内。
创建 → awaiting_materials(缺料,附 missing_materials)
→ queued(素材齐全,自动回队)
→ rendering(服务端编码,progress 1→100)
→ done(result.url 可下载)
| 情况 | 平台行为 / 甲方该做什么 |
|---|---|
缺歌词(error_code=MISSING_LYRICS) | 任务停在 awaiting_materials;补传 line_lyrics 或重新提交带 song_info.lyrics 的任务后自动回队 |
编码失败(XINGHE_RENDER_FAILED) | 平台自动重试 2 次(每次重新入队);第 3 次仍失败才置 failed,error 附原因,可调 重跑接口 |
| 任务被同一作品新单覆盖 | cancelled + error_code=SUPERSEDED(平台按最新提交出片,属正常取代) |
| 耗时参考 | 30 秒成片实测约 2 分钟(含排队+编码);4K 或长音频会相应变长,建议按 5 分钟量级设轮询上限 |
# ① 建单(先不给素材,返回 awaiting_materials + missing_materials) curl -X POST https://<你的域名>/v1/video/generations \ -H "Authorization: Bearer <API_KEY>" -H "Content-Type: application/json" \ -d '{ "template_id": "xinghe-cd-001", "song_info": { "song_name": "作品名", "lyricist": "词", "composer": "曲" }, "output_resolution": { "width": 1920, "height": 1080, "fps": 30 }, "external_task_id": "your-order-0001" }' # → { "id": "C6F8J1X1YBO45K11", "display_id": 547, "status": "awaiting_materials", ... } # ② 歌词:申请直传地址 → PUT → 登记 curl -X POST https://<你的域名>/v1/video/materials/presign \ -H "Authorization: Bearer <API_KEY>" -H "Content-Type: application/json" \ -d '{ "task_id": "C6F8J1X1YBO45K11", "type": "line_lyrics", "filename": "line.lrc" }' # → { "oss_key": "materials/xh01/tasks/547/line_lyrics_..._line.lrc", "put_url": "https://...", ... } curl -X PUT --upload-file ./line.lrc "<put_url>" curl -X POST https://<你的域名>/v1/video/materials/confirm \ -H "Authorization: Bearer <API_KEY>" -H "Content-Type: application/json" \ -d '{ "task_id": "C6F8J1X1YBO45K11", "type": "line_lyrics", "oss_key": "<上一步的 oss_key>", "filename": "line.lrc" }' # → task_status 仍为 awaiting_materials,missing 只剩 original_vocal # ③ 原唱音频:同上三步,type 换成 original_vocal # → task_status = "queued"(必需素材齐全,自动进入渲染) # ④ 轮询(建议 5 秒一次) curl https://<你的域名>/v1/video/generations/C6F8J1X1YBO45K11 \ -H "Authorization: Bearer <API_KEY>" # → rendering 1% → 25% → 40% → done 100%,result.url 即成品下载地址(COS 签名,长期可重新查询获取)
| 现象 | 原因 / 处理 |
|---|---|
任务一直 awaiting_materials | 看 missing_materials:多数是只传了音频没传歌词(或相反)。补齐后自动回队 |
MISSING_LYRICS | 本地已有素材但歌词拿不到:确认 line_lyrics 已 confirm 成功(返回 url),或改用 song_info.lyrics 重提 |
| 歌词和歌声对不上 | 本模板按节拍自动排轴,不做逐句对时。若要严格逐句卡点请用 CD-2024-005 |
| 成片时长和音频不一致 | 成片时长≈音频时长(尾部按引擎收束 ±0.1s 内)。若相差大,检查音频是否被裁短/首尾静音过长 |
| 播放器放不出声音 | 成片音轨统一转 AAC(引擎原生 Opus 在 iOS/Safari 不兼容,平台已自动转换)。若仍异常请反馈具体播放器 |
4008 | output_resolution 未命中 supported_resolutions,按 18.4 的档位传 |