VideoStudio 开放接口文档

对外提供视频生成、任务查询与账户余额查询能力 · 兼容 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 视频制作对接(含物料包契约、自检闸门、交付规格、联调回归)

⚠️ MV 模板提交必读(近期最高频的打回原因):交付包必须包含 input/mv-shots.json——每镜的时长 durationMs 与提示词 videoPrompt。 只有镜头底图、或只附 edit-script.md(剪辑概述,不含每镜时长与提示词)都会被打回为 awaiting_materials,24 小时内未补齐将自动取消并退款。 → 格式规范与打包自查
v3.0 起新增硬校验:镜头数 = shotCount = 分镜图张数;Σ durationMs = timeline.durationMs(±200ms);max(endMs) ≤ 音频时长(建议提供 audioDurationMs)。 任一不符 → MV_SELFCHECK_FAILED 打回(message 附四个实测数值),不消耗算力、不出片。→ §14.4 时间轴硬校验

0. 快速开始(接入指引)

生产环境 Base URL

https://video.livepartner.fans

所有接口统一使用该域名(HTTPS,nginx 反向代理至视频工厂服务),路径前缀为 /v1。文档中的「<你的域名>」占位符会自动替换为当前访问域名。

标准接入步骤(最小可跑通链路)

  1. 获取 API Key:向平台方申请客户账户,获取客户连接码(API_KEY,格式示例 ck_live_xxxxxxxx)。
  2. 查询模板:调用 GET /v1/templates 获取可用模板,记下目标模板的 code(作为后续 template_id)与 material_spec.required 素材清单。
  3. 创建任务:调用 POST /v1/video/generations 提交 template_id(可带 external_task_id 做幂等),返回 task_id。若未携带素材包,任务进入 awaiting_materials 并返回 missing_materials 缺失清单。
  4. 上传素材:按缺失清单逐类调用 POST /v1/video/materials(multipart 直传)或 POST /v1/video/materials/presign + confirm(OSS 预签名直传)。
  5. 提交任务:素材齐全后调用 POST /v1/video/generations/{task_id}/commit 使任务进入 queued;也可不调用,素材齐全后任务会自动入队。
  6. 轮询/回调:轮询 GET /v1/video/generations/{task_id}(或配置 callback 接收终态回调),等待 status 变为 done。
  7. 下载成片:从任务详情读取 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} 反复查询,结果长期有效。

0.1 对外公开清单页(免登录,可直接查阅)

以下资源清单页与接入文档同域公开、无需登录,可直接发给甲方/接入方查阅选型:

清单链接说明
LUT 调色滤镜库/lut-library.html204 款滤镜的黑底效果图、实测风格与参数、创作者来源;点击编号复制(详见 §16)
歌词样式清单/lyrics-catalog.html156 款歌词插件的真实引擎实时预览;点击插件编号复制(plugin_id)
字体库清单/fonts-catalog.html65 款字体按真实字体文件渲染样例(含中文字形标注),可下载字体文件打样
转场库/transition-catalog.html49 种转场的 ffmpeg 真实渲染动效预览、分组筛选与后端支持矩阵(详见 §15.4.3)

以上页面数据与平台实时一致;转场/歌词清单随插件库自动更新,字体清单在字体库变更后由平台重建。

1. 接口鉴权

所有接口均通过 Authorization 请求头携带你的客户 API Key(即「连接码」):

Authorization: Bearer <你的_API_KEY>

未携带或无效的 Key 将返回 401 authentication_error。你可以在「设置 → 客户设置」中查看每个客户的连接码。

连接码说明

错误响应结构(OpenAI 风格)

鉴权失败统一返回 401,响应体为 OpenAI 风格错误结构,请以 error.type 判断错误类型、error.code 判断 HTTP 状态码:

{ "error": { "type": "authentication_error", "code": "401",
             "message": "缺少 Authorization 请求头或格式不正确",
             "retryable": false, "request_id": "req-xxxxxxxx" } }

常见鉴权失败

2. 查询模型列表

GET /v1/models  ·  GET /models

查询当前账户可用的视频生成模型(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,服务端按所选模板的类别自动匹配对应模型。

3. 查询模板列表

GET /v1/templates?category=cd&status=enabled
GET /v1/templates/{code}

查询当前账户可用的视频模板及其素材要求。创建任务时必须指定一个模板的 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 模板有两个:CD-2024-005(星光1号:相册图轮播 + 卡拉OK 字幕,走渲染机)与 xinghe-cd-001(星河字画:歌词直出文字 PV,服务端编码,素材只要「歌词 + 原唱音频」,见 §18)。 查询参数口径:status 传 enabled(默认,仅已上架)或 all(含停用); category 大小写不敏感(cd / CD 等价),cd 与 mv 均可。

4. 创建视频生成任务

POST /v1/video/generations

请求体(JSON)

参数类型必填说明
template_idstring是工作流模板编号,如 CD-2024-005
promptstring否任务名称 / 描述
cust_user_idstring否调用方业务侧的用户标识,用于关联对账,原样透传保存
modelstring否指定模型,如 xinghe-cd-c1;不传时服务端按模板类别自动匹配
resolutionstring否输出分辨率,默认 1080P(720P / 1080P)
watermarkboolean / object否水印配置(含独立开关)。省略或 false=无水印;true=使用客户默认水印(后台配置);对象={enabled, type:"image"|"text", ...},图片水印与文字水印二者选其一,详见「水印 / 片头片尾 / 播放器标签」
introobject否片头独立开关与资源:{enabled:true, url, type:"image"|"video"};enabled:false=关闭(用模板默认片头)。省略=按模板默认片头
endingobject否片尾独立开关与资源:{enabled:true, url, type:"image"|"video"};enabled:false=关闭(用模板默认片尾)。省略=按模板默认片尾
labelsobject否播放器标签独立开关与覆盖文本:{player1:{enabled,title?,author?}, player2:{enabled,user_name?,platform_name?,level?}}。player1=左上角歌名标签,player2=右上角会员卡标签,enabled:false 隐藏该标签
song_infoobject否歌曲与用户元数据(歌名/词曲作者/歌词/用户昵称/会员等级/平台名),用于播放器卡片渲染,详见「水印 / 片头片尾 / 播放器标签」
plugin_idstring否渲染插件编号(plugin-001 格式),任务级覆盖模板的 default_plugin;两者皆无时使用平台内置播放器。插件库由客户端从服务器拉取,按编号取用
decorationsobject否装饰组件(阶段一 P5)。固定五项 intro / ending / watermark / corner_tl / corner_tr,每项 {plugin, enabled, params}。仅需覆盖模板默认时可省略;配置合并顺序:平台全局默认 < 模板 decorations_schema < 任务 decorations。未知装饰项 / 结构非法均返回 4008。示例:{"watermark": {"plugin":"plugin-001","enabled":true,"params":{"text":"版权所有"}}}
output_resolutionobject否动态输出规格 {width, height, fps?}(阶段一 P1)。width/height 必填正整数,fps 可选正整数。必须命中模板 supported_resolutions 中某一项(可从 GET /v1/templates 查看),否则返回 4008。省略时用 resolution 或模板默认分辨率
callbackstring / 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} 轮询兜底。详见「回调签名与重试」
priorityint否任务优先级 1-5,默认 3
delivery_urlstring否客户提供的成品交付地址(支持 PUT 直传)。任务完成后成品直传该地址;平台下载地址同时返回作为兜底
external_task_idstring否调用方业务侧的任务唯一标识,用于对账与幂等。若与历史任务重复且请求体一致,服务端返回已存在任务(不重复计费);若请求体不一致则返回 409 idempotency_conflict
material_packageobject否甲方对象存储的素材包地址(结构见下方说明),服务端接收并按需拉取素材
result_uploadobject否甲方对象存储的成品上传地址(结构见下方说明),任务完成后成品直传该地址
materialsobject否内联素材(键为 type,值为文件 URL),创建时一并提交

水印 / 片头片尾 / 播放器标签(均可经 API 独立开关)

片头、片尾、水印、左上角歌名标签(播放器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": "星光音乐"         // 平台名称
  }
}

说明:

歌词格式(支持标准 LRC 与 JSON,自动识别)

歌词可通过 song_info.lyrics 传入,也可作为素材上传(type=line_lyrics 逐行歌词 / type=word_lyrics 逐字歌词,见第 5 节)。服务端与渲染端自动识别以下三种格式,无需声明:

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": "风穿过旧时光" }
]
历史兼容说明:早期版本把非 LRC 的 JSON 歌词当作"无时间戳纯文字"处理,会把 JSON 原样烧进字幕画面。自本版起,渲染端识别 JSON 数组后先转换为规范 LRC/ASS 再渲染,杜绝"代码烧进画面";同时歌曲名/作者/平台名等元数据若塞在 prompt 的 ```json params 中,服务端也会自动提取补入 song_info,确保画面文字出处规范、准确(prompt 本体仅作为任务描述,不直接渲染进画面)。

material_package / result_upload 字段结构(甲方对象存储契约)

当甲方通过自己的对象存储交换素材包与成品时,可传入以下结构。字段原样保存并透传返回,便于双方对账:

{
  "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。
计费:任务创建成功即扣除 1 次额度并写入账单流水;任务取消或失败会自动退款(退回 1 次额度),详见下文「任务管理」与「账单流水」章节。

请求示例

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 字段标识所使用的模型:

"model": "xinghe-cd-c1"

模型按模板类别拆分(与 /v1/models 返回的模型 ID 一致):CD 类模板使用 xinghe-cd-c1,MV 类模板使用 xinghe-mv-m1。客户端可在请求中通过可选字段 model 指定模型;不传时服务端按所选模板的类别自动匹配。

5. 上传任务素材

POST /v1/video/materials

为指定任务上传自定义素材(图片 / 音频 / 视频),multipart/form-data 上传。任务渲染时将完全使用该客户上传的素材,不再使用默认素材库。

表单字段

参数类型必填说明
task_idstring是创建任务返回的任务编号(如 JH3OOFVHYNQXN0K0)
typestring是素材类型(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 均可),内容自动识别
filefile是素材文件。相册图可多次上传多张,按文件名排序。

请求示例

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 预签名直传作为兜底方案。
POST /v1/video/materials/presign

素材上传有两条等价受理的路径(2026-09-27 口径统一):
① POST /v1/video/materials(multipart 表单直传)—— 适合小文件、实现最简单;
② POST /v1/video/materials/presign + PUT + POST /v1/video/materials/confirm —— 大文件推荐:申请一个 对象存储预签名直传地址(PUT 方法),客户端拿到 put_url 后直接 PUT 上传,不经过服务器、不占服务器带宽,传完后调 confirm 登记。
两条最终都落到同一份任务素材目录与同一套验收规则上,任选其一即可。

请求参数(JSON body)

参数类型必填说明
task_idstring是任务编号(如 JH3OOFVHYNQXN0K0)
typestring是素材类型,canonical key 与上方 multipart 一致(poster/cover/original_vocal/accompaniment/word_lyrics/line_lyrics/album_images/user_avatar/edit_script/intro/ending/platform_logo,兼容旧别名,自动归一化)
filenamestring否原始文件名(用于登记与排序,可选)

请求示例

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"
2026-09-27 起:put_url 有效期 24 小时(expires_in: 86400,另有 expires_at 绝对时间);直传时 Content-Type 不校验,按实际文件类型填写或省略均可(历史上曾要求 application/octet-stream,已取消)。若地址确实过期(403),重新调用一次本接口即可拿到新地址。直传完成后请调用下方 confirm 接口登记,否则素材不会进入任务。
POST /v1/video/materials/confirm

直传完成后,调用本接口登记素材。服务端会校验对象存在,并把素材拉取到任务素材目录、更新任务状态(awaiting_materials → queued)。

请求参数(JSON body)

参数类型必填说明
task_idstring是任务编号
oss_keystring是presign 响应返回的 oss_key
typestring是素材类型(与 presign 时一致)
filenamestring否文件名(可选,用于登记与排序)

请求示例

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,补齐后任务自动进入队列"
}
登记前请确保 OSS 直传已完成(对象已存在),否则返回 4006 错误。相册图可多次 presign/confirm 上传多张。与 multipart 一致:只有模板 material_spec.required 列出的所有必需素材齐全后,任务才进入 queued。

6. 查询任务进度

GET /v1/video/generations/{task_id}

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 列出仍缺的素材项。
会被打回的情形:① 必需素材不齐;② MV 交付包缺少镜头脚本(每镜 durationMs + videoPrompt);③ 素材解析失败或超过 5 分钟未完成。打回后可通过 POST /v1/video/materials 补齐素材(或用新的 material_package 重传),再 POST /v1/video/generations/{task_id}/commit 重新入队;已生成的镜头产物会保留,只补未完成部分。
队列超时:pending / queued 超过 30 分钟无人认领会判失败(error_code=QUEUE_TIMEOUT,自动退款并回调);MV 任务在「素材解析 + 图生视频」阶段不适用该规则(该阶段由图生视频工作机推进,进度见镜头明细接口)。
提交即校验 vs 后台解析:commit 会同步读取交付包清单做合规校验(缺镜头脚本立即 409,不入队、不占额度);而素材包的下载/解压/解析是后台异步完成的,其失败会以「打回待补件」+ error 的形式体现在本接口。

7. 获取任务列表

GET /v1/video/generations?limit=20

返回当前 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 } ] }

8. 任务管理(提交 / 取消 / 退款 / 重跑)

以下接口均使用 task_id(任务编号或数字内部 id)定位任务,请求头鉴权同其它接口。任务状态流转:awaiting_materials → queued → rendering → done / failed / cancelled。

POST /v1/video/generations/{task_id}/commit

显式提交:客户端声明素材已就绪,主动把 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 清单)。

⚠️ MV 交付包:镜头脚本(mv-shots.json)格式规范与打包自查

现象: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 可查)。不提供则一切照旧

硬约束(不满足会被打回或生成错误成片)

渲染前自检闸门(v3.0 起,硬性):我方在任何生成动作之前校验下列四条,任一不通过 → 任务转 awaiting_materials、error_code=MV_SELFCHECK_FAILED, message 内附四个实测数值(镜头数 / Σ镜头时长 / timeline.durationMs / max(endMs) / 音频实测),不消耗算力、不产出成片:
  1. shots.length == timeline.shotCount == 包内分镜图张数
  2. |Σ shots[].durationMs − timeline.durationMs| ≤ 200ms
  3. max(shots[].endMs) ≤ 音频实测时长
  4. timeline.durationMs 与音频实测的偏差仅告警(durationMs 常为整秒取整,如 122000 vs 实测 122376;时间轴以音频实测对轴)
另:全片时长以音频实测为准,镜头逐条按 shots[].durationMs 排布(±1 帧),不按模板默认时间轴/固定节奏,不自行补齐;Σ镜头比音频短 ≤2s 由末镜铺满,长于音频 >2s 直接打回。

打包自查 5 步(提交前务必做)

  1. 解压交付包,确认 input/mv-shots.json 文件真实存在(不能只有 manifest 里的声明)
  2. 打开它,确认 shots 数组非空,且每条都带 videoPrompt 与 durationMs
  3. 确认 shots 条数 = 镜头图张数 = timeline.shotCount,且顺序与文件名序号一致
  4. 对账 Σ durationMs = timeline.durationMs(±200ms),且 max(endMs) ≤ 音频时长
  5. 确认音轨是原唱(vocalUrl / originalVocalUrl),不是伴奏

若已被打回:按 error_code/message 补齐后重新提交(或调用 POST /v1/video/generations/{task_id}/commit)即可续跑;超过 24 小时任务会被自动取消并退款,重新提交即可。同一份物料包重推时,已完成的镜头成果会保留。

POST /v1/video/generations/{task_id}/cancel

取消任务并自动退款(退回 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 已进入处理阶段无法取消。

POST /v1/video/generations/{task_id}/refund

对失败或已取消任务退还额度(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 已退款不可重复、或状态非失败/已取消。

POST /v1/video/generations/{task_id}/retry

对失败或已取消任务重新进入队列,并重新校验素材齐全度(齐全 → 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 已退款任务重跑时额度不足。

POST /v1/video/generations/{task_id}/refresh

签名地址过期续跑:当素材包下载或成片回传的签名 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)。

POST /v1/video/callbacks/replay

回调人工重放:按 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 幂等去重。

素材打回事件:material_rejected(2026-10-07 新增)

素材包验收不通过被打回时(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
  }
}

9. 账单流水

GET /v1/billing/transactions?limit=50

查询当前账户的扣费 / 退款流水记录。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 次),便于双方对账。

10. 成品下载说明

视频渲染完成后存于平台存储,甲方按以下流程获取成品:

  1. 轮询或回调获知任务 status = done;
  2. 调用 GET /v1/video/generations/{task_id},读取 result.url;
  3. result.url 为平台同域名下的成品下载地址,直接用 HTTP GET 下载即可;
  4. 下载后甲方应自行转存到自己的文件桶并长期留存。
本平台定位为加工厂,成品长期有效可随时重新调用查询接口获取下载地址。若创建任务时提供了 delivery_url(支持 PUT 直传),平台会在任务完成后优先把成品直传到该地址,失败时兜底回平台下载地址;result_upload(甲方对象存储成品地址)已上线:任务完成后成片自动 PUT 直传甲方指定对象键(携带 result_upload.content_type 请求头,仅写入 url 指定对象),失败仅重传成片、不重新渲染、不重复扣费。

11. 查询账户余额

GET /v1/user/balance  ·  GET /v1/me
{
  "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"
}

12. 错误码

HTTPtypecode说明
401authentication_error401缺少或无效的 API Key
403permission_error403账户已停用
429rate_limit_error429请求过于频繁,已触发限流(响应头 Retry-After 指示可重试秒数)
400invalid_request_error4001参数缺失或无效(template_id / task_id / type / file 等),或文件上传失败
400invalid_request_error4006oss_key 与任务不匹配,或 OSS 对象不存在
400invalid_request_error4007模板已停用(status=disabled)
404not_found_error4041模板不存在
402quota_error4029账户额度不足
404not_found_error404任务不存在或不属于当前账户
409idempotency_conflict409幂等冲突:同一 Idempotency-Key 但请求体不一致
409invalid_request_error409状态冲突:任务当前状态不允许该操作(已处理中无法取消 / 不可重复退款 / 非失败不可重跑等)
503server_error503存储后端未配置或暂不可用
500server_error5000服务端内部异常

任务级 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,便于双方对账排查。

13. 变更记录

14. 素材验收标准与打回整改(重要)

成片必须由符合分类标准的素材拼接:CD(宣传片)用照片,MV(音乐视频)用视频。 平台在素材入库与渲染出包两个环节强制校验,不符合的不予受理、不会出片、不会交付给甲方。

14.1 标准

分类相册素材(成片画面主体)不满足时
CD照片(jpg / jpeg / png / webp / bmp / tif)打回:相册里出现视频即视为包不合规
MV视频片段(mp4 / mov / mkv / webm / avi / m4v)打回:MV 的每个镜头须完成「图生视频」并产出视频片段后才可进入渲染

14.2 打回时查询接口会回传什么

任务状态变为 awaiting_materials,同时回传以下字段(均为可程序化处理的整改依据):

字段含义
error整段整改备注,形如「【素材包不予受理,请整改后重新推送】1. … 2. …」,逐条列出问题与整改方向
invalid_materials上述备注的结构化问题项(字符串数组),便于展示与自动处理
error_codeMATERIAL_SPEC_REJECTED 表示「分类与媒体类型不符」;其余素材类错误码见 §1
missing_materials按模板 material_spec.required 判定仍缺的素材项
material_package_status素材包拉取与验收状态:downloading(拉取中)/ ingested(已入库)/ failed(拉取或验收失败);任务未收到素材包时为 null
ingest_note包级备注(SHA-256 校验失败、下载地址过期、包内容不合规等)

14.3 整改后如何重新推送

  1. 按备注整改素材包(补齐文件 / 换成正确的媒体类型 / 修正镜头脚本)
  2. POST /v1/video/generations/{task_id}/refresh 刷新素材地址并按新包重新验收;或在创建任务时传入新的 material_package
  3. 验收通过后任务自动进入 queued;已完成的镜头成果会保留,只补跑未完成的部分

14.4 MV 时间轴硬校验(渲染前自检闸门,v3.0 新增)

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 直接打回;成片内不存在冻结段/空画面。

14.5 常见打回原因与整改对照

现象 / 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 中四数值定位

14.6 哈希验收口径(v3.0 确认)

我方 ingest 会重新打包 materials.zip(并可能改写清单),因此整包 sha256 不可复现; 我方对素材包的 SHA 校验仅用于「下载是否完整」,不作为拒收成片依据。双方验收统一以 逐素材 sha 比对 为准。

MV 镜头脚本(mv-shots.json)的格式规范、硬约束与打包自查 5 步,见 「MV 交付包:镜头脚本格式规范与打包自查」; 完整对接契约(物料包字段、自检闸门、音频基准、交付规格、联调回归 752/757/683、哈希口径)见 §15 MV 视频制作对接。

15. MV 视频制作对接(物料契约 · 自检闸门 · 回归验收)

一句话说明:甲方提供 物料包(分镜图 + 镜头脚本 + 音乐)与 成片回传通道;我方负责把每张分镜图做成视频片段、严格按 shots[].durationMs 逐镜排布、以原唱轨合成音画,并把成片回传给甲方。

平台 Base URL:https://video.livepartner.fans(任务提交 / 查询接口见 §4、§6)

15.1 本期整改对照(甲方 R1–R9)

问题回顾(我方责任,已定位并修复):#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 的期望值与验收口径
我方已用甲方 752 / 757 的真实物料包完成实测复现(数值与甲方报告一致):
{ 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 条件④),我方一律以音频实测对轴,不会因为这几百毫秒把成片切短。

15.2 交付方式与接入凭据

接入凭据(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 给我方运营登记联调初期、少量作品

方式① 接单入口契约(甲方推送 → 我方自动拉物料并投产):

POST https://video.livepartner.fans/api/mv/inbound
# 请求头
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。
后续:自动拉物料 → 素材入库 → 自检闸门(§15.4)→ 逐镜生成 → 拼接 → 回传甲方。

15.3 甲方需实现的接口(方式①/②共用)

GET /v1/mv-video/materials/{workId}

物料包下发(我方调用,必配)。返回结构:

{
  "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
PUT {result_upload.url} —— 成片直传

我方把 MP4 以 Content-Type: video/mp4 PUT 到甲方提供的预签名地址,随后调用 complete。

POST /v1/mv-video/materials/{workId}/returns/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)。

POST /v1/mv-video/materials/{workId}/returns/refresh —— 刷新物料/票据

票据过期时我方调用,不新建任务。

甲方自助校验工具(提交前本地自查,建议接进打包流程)

文件地址用途
可交互接口页
推荐先看这个
/docs/swagger.html浏览器打开即可按 tag 浏览全部接口(Try it out 直接发真实请求、Authorize 填 Key / 接单令牌),数据来自同一份 /openapi.yaml,无需安装任何工具
机器可读规范/openapi.yamlOpenAPI 3.0 规范(v1.3.0)。已含 MV 契约:接单入口 + 三个需甲方实现的接口(标注 x-implemented-by: provider,Base URL 用 {api_base} 变量)+ 物料/回传全量 schema。可直接用 openapi-generator 等工具生成客户端 SDK或服务端骨架
镜头脚本规范/docs/mv-shots.schema.jsonmv-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} 替换为甲方自己的基址即可。

15.4 渲染前自检闸门(R1 / R2 / R5)

甲方要求「渲染前自检四条,任一不通过 → 停止并回报(附四个数值),不得渲染、不得兜底」。我方已实现为素材入库解析后的第一步—— 在任何 GPU 生成动作之前执行,不通过则任务直接转 awaiting_materials,不消耗算力、不产出成片。
#条件不通过时
①shots.length == timeline.shotCount,且等于包内分镜图张数(shot/NNN.jpg 去重计数)awaiting_materials
error_code=MV_SELFCHECK_FAILED
message 内含:
「MV 自检闸门不通过(已停止出片):<失败项>|实测:镜头数=N Σ镜头=Xms timeline.durationMs=Yms maxEnd=Zms 音频实测=Wms(<音轨文件>)」
②|Σ shots[].durationMs − timeline.durationMs| ≤ 200ms
③max(shots[].endMs) ≤ 音频实测时长(无镜头越过音频终点)
④timeline.durationMs 与音频实测的偏差 只告警不拦截(甲方 durationMs 为整秒取整,常差 300–500ms;时间轴一律以音频实测为准)

闸门通过时我方会做什么

绝不做的事(本次事故根因,已永久禁止):
  • 不使用模板自带测试素材顶替甲方素材(素材未就绪 → 一律打回等待);
  • 不按模板默认时间轴/固定镜头节奏铺镜头(只认 shots[]);
  • 不在缺字段时猜测 durationMs / 镜头数(缺则打回并回报)。
本地自查(推荐):直接跑我方提供的零依赖脚本,输出与平台闸门完全相同的四数值与问题清单 —— 详见 §15.3 甲方自助校验工具:
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) 允许几百毫秒(整秒取整)

15.4.1 MV 一致性核验链(2026-10-03 新增,硬性)

甲方口径:核验单覆盖 MV 一致性的完整链条 —— MV 脚本 → 主角定妆照 → MV 镜头表(含首帧)→ 镜头首尾帧。 四环缺一不可:素材入库解析即核验,不通过直接打回(任务转 awaiting_materials,不消耗算力、不产出成片), 打回原因以「【素材包不予受理,请整改后重新推送】」开头并逐条列出。
⚡ 推包前 30 秒自查清单(2026-10-07 新增 —— 近期多单卡在定妆照被打回,按此清单可一次过闸)
  1. 主角定妆照(最高频打回点),三种给法任选其一: ① 清单 mv.dressImageUrl 填一个可公网下载的定妆照 URL(jpg/png,单人正面半身/全身均可); ② 清单 mv.dressAvailable=true 且 zip 包内 dress/(或 定妆/)目录放主角定妆图; ③ 只在包内 dress/ 目录放图也可(我方会自动转存并回填地址)。 常见错误:清单里这两个字段留空 / null —— 留空即视为未定妆,接单被拦。
  2. 镜头脚本:包内 input/mv-shots.json(每镜 durationMs + videoPrompt)。
  3. 每镜首帧图:input/objects/shot/NNN.jpg 与镜号一一对应。
  4. 每镜尾帧图: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 节点新增字段(乙方拉包即可见)

字段类型说明
mv.dressImageUrlstring主角定妆照地址。包内给图时我方会转存并替换为可下载地址(cos:// / https)。用途:换脸依据 —— 是否需要换脸以换脸开关为准(见下方「定妆照的用途」)
mv.dressAvailableboolean定妆照可用性。true = 已定妆(可接单);缺失或 false 且无可下载地址 → 未定妆,接单被拦下
mv.faceSwapboolean换脸开关(甲方提供):true = 用定妆照做换脸;false = 不换脸(不使用定妆照);未提供 = 未声明。已兼容 faceSwap / face_swap / enableFaceSwap / useDressImage / dressSwap 等别名,取值兼容布尔与 on/off、启用/不启用、是/否
mv.tailFrameReadyCountinteger尾帧就绪数,与 shots[].endImageUrl 对应。我方用它做交叉核验:声明数与包内实际匹配数不一致即打回(防止「声明有尾帧、包里缺图」)

主角定妆照的用途:换脸依据(是否需要换脸由甲方开关决定)

行为变化(请同步给生成侧)

本地自查(已同步):§15.3 甲方自助校验工具的 validate-mv-shots.mjs 已增加 ⑥ 定妆照与⑦ 尾帧完整性两项检查(与平台核验链同一口径),建议接进打包流程,别等推过来被打回。
可观测:作品详情接口返回 mv_consistency(dressImageUrl / dressAvailable / tailFrameReadyCount / tailFrameReady), 镜头级明细每镜带 end_frame_status('' 未声明尾帧|ok 可下发|blocked 声明了但地址不可下载)与 end_frame_used(生成机实际用上的尾帧字段,空 = 实际未用首尾帧)。

15.4.2 海报分镜(镜头 0)与主体锁定(2026-10-09 新增;2026-10-14 海报独立音画 + 接入范例;2026-10-19 海报镜尾帧必带、缺帧打回不兜底)

本期变更两点:① MV 开场「海报 5 秒」由静态展示升级为生成机生成的动态海报分镜(编号 0); ② 每一镜提示词注入主体锁定硬约束(首尾帧之间主体人物锁死、背景可变、禁止出现新人物)。 两项均为提示词与时间轴层面的变更:甲方推送格式、接口、回传通道零改动。

一、海报分镜(segmentType=poster,默认 5 秒)

项默认行为(平台自动插入,甲方包无需改动)
触发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(未插入,含原因)

对甲方的影响清单:

⚠️ 甲方自带海报镜的规则(也可自己在 mv-shots.json 声明,平台检测到后不再自动插入,防双海报)
  1. 镜号不得与原镜头重复:海报镜占用 (segmentIndex 0, shotIndex 0) 后,原镜头的 shotIndex 必须顺延(原第一镜改 shotIndex 1,依次类推)。 撞号会导致镜号去重丢镜(成片少一段开场、其后画面整体前移 → 画面与歌词全部错位);平台现在会对撞号镜头自动顺延兜底,但请从源头写对镜号;
  2. durationMs 必填:海报镜时长缺失/为 0 时平台按 5000ms 兜底,但请明确填写;
  3. timeline.durationMs 与 shotCount 必须包含海报镜(2026-10-14 修正,以此为准):自带海报镜时 timeline.durationMs = Σ 全部镜头 durationMs(含海报镜,±200ms)、timeline.shotCount = 总镜数(含海报镜)。 自检闸门②按甲方 timeline.durationMs 原值直接与 Σ镜头时长比对——少写海报时长会被 MV_SELFCHECK_FAILED 打回(此前文档写「无需修改」与闸门实际口径不符,已修正);
  4. 音画口径(海报镜独立):海报镜期间静音、无歌词字幕;歌曲音频与歌词字幕由平台自动整体后移海报时长——甲方音频文件、歌词文件零改动,歌曲镜的相对间隔与音画对齐关系与甲方声明完全一致;
  5. startMs/endMs 建议写绝对时间轴:海报镜 0 → P,歌曲镜自 P 起依次顺延;末镜结束 ≤ 音频实测时长 + 海报段(自检闸门③上限);
  6. 【2026-10-19 新增 · 硬要求】海报镜必须自带首尾帧:海报镜与普通分镜同权,imageUrl(首帧)+ endImageUrl(尾帧)+ videoPrompt 三者缺一不可。 缺尾帧 → 解析阶段直接打回(status=awaiting_materials、error_code=MATERIAL_MISSING_END_FRAME),平台不做任何自动补齐 —— 既不会拿包内海报图代替,也不会用首帧「首尾同图」代替 (尾帧是本镜收束画面的锚点,也是 QA 末帧符合度校验的参照;平台代补等于替甲方编造交付内容); 尾帧上希望出现的文字,请写进 videoPrompt 由模型生成,不要写成「从首帧渐变显现」的文字动效。
  7. 海报镜的 imageUrl / videoPrompt / hasPerson 按普通镜头格式声明;海报镜通常 5s(略低于 §15.4.4 生成甜点区下限 5.2s,属正常、不影响出片)。

三、甲方接入范例(自带海报镜,2026-10-14 新增 · 一次接对模板)

以下是一份可直接照抄的 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 秒自查(自带海报镜版,全过即一次接对):

二、主体锁定(所有镜头逐镜注入,纯提示词、无检测)

口径(甲方原话):背景风景可以随镜头运动自然变化,但主体人物绝对不能变、不能出现新的人。

每镜下发给生成模型的提示词中,人物约束共 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 时平台按纯风景/物件镜头处理(注入 ⑤ 的全镜禁令)。未声明时按首帧画面与提示词自行判断(注入 ①–④)。

15.4.3 转场系统(2026-10-13 新增;2026-10-14 端到端核准,49 项)

MV 渲染管线已接入 ffmpeg xfade 全量转场:目录共 49 项(ffmpeg xfade 原生变体 46 + 预留/自研 3,见下表标注),支持 三级配置:逐镜声明(mv-shots.json 的 shots[].transition)> manifest 全局默认(delivery 的 transitions 节点)> 平台默认 fade。 转场发生在相邻镜头的重叠余量区内,不占用甲方脚本时长、不影响歌词-画面对位(渲染端按声明时长精确消耗重叠区,全片时长严格等于音频时长)。 声明 "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;过大不会损坏成片,会被自动截断到可用余量。

二、转场目录(49 项 = ffmpeg xfade 原生 46 + 预留/自研 3)

分组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 导致逐镜累积膨胀、歌词越往后越不齐的问题已根治)

15.4.4 分镜时长与生成效率规范(2026-10-13 新增)

一句话结论:单镜时长落在 5.2 ~ 6.5 秒 区间时,生成速度最快、画面最稳、无任何后处理代价; 不要低于 5.2 秒(会按模型训练下限强制补足后裁剪,白耗算力);超过 6.9 秒会自动启用「分段续接」, 成片质量有保障,但生成时间翻倍并带轻微变速。

一、时长对照表(实测口径:H3 模型 + 当前固化配方)

单镜时长生成方式生成耗时(单镜实测)画面稳定性建议
< 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 计——密集短镜会拉长总生成时间

15.5 我方交付规格

项规格
封装 / 编码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(超出会中止并报错,不产出不合格成片)

15.6 状态与运维

作品状态机(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),供运营监控与问题处理:

凭据口径(2026-10-02 明示):本小节为乙方内部运维接口,列出仅为流程透明。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交付包解析预览(不入库,用于提交前核对解析结果)
镜头生成期间若生成机离线,任务保持「正在处理」(不判失败、不打回、不重复扣费),我方 GPU 生成机上线后自动续跑未完成镜头。

15.6.1 镜头级状态查询(甲方接入,2026-10-02 新增)

甲方可凭乙方 worker 管理令牌(向星河索取后配置到甲方系统的 mv_worker_admin_token)直接查询任意作品的逐镜头生成状态与质检指标:

GET /api/mv/works/{workId}/shots[?status=pending|generating|done|failed]

鉴权(二选一):

方式凭据可见范围
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[].statuspending / 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"
只读接口,不暴露我方客户资料与存储凭据。令牌仅用于本查询通道,与接单令牌、成片回传凭据相互独立。

15.7 错误码与整改指引

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 视为成功。

15.8 联调回归(R9)

按甲方要求,用甲方提供的测试作品走完整链路,并回报「自检闸门四个数值 + 成片实测总时长」。

作品 ID期望 durationMs期望镜头数我方回报内容验收口径
75210053627① 镜头数(含包内分镜图张数)
② Σshots[].durationMs(含与 timeline.durationMs 偏差)
③ max(shots[].endMs) 与音频实测时长
④ 音频实测时长(原唱轨)
⑤ 成片实测总时长 / 分辨率 / 帧率
成片总时长 == durationMs(±200ms)
镜头数 == 分镜图数 == shotCount
无冻结段/空画面
音画同步(歌词落点不偏移)
75712237623
68313394452
我方已完成的预核对(用甲方 752 / 757 的真实物料包逐条复现甲方报告数值,解析阶段实测):
{ 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 待甲方物料接口就绪后走同一链路回归。

15.9 哈希与回传口径(R7 / R8)

项口径
素材包整包 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 分钟)

15.10 常见问题

16. 调色滤镜库(LUT 编号调用)

成片调色由平台统一完成,你只需在交付里给编号(lutCode),不需要提供滤镜文件。滤镜总览(每个滤镜的黑底效果预览图、实测风格与参数、创作者来源)在此公开查看,无需登录:

→ 打开 LUT 调色滤镜库  (可搜索、按风格/创作者筛选、点编号复制)

调用字段delivery.lutCode(随交付文件下发)
取值滤镜库中的「编号」,纯数字(001–204),例如 007
套用方式对成片整体套用一次(全片一致,镜头之间无色偏跳变)
一致性要求编号须与库中完全一致(三位数字,含前导零,如 007);写错或库中不存在 → 该片不调色并记录告警,不阻断出片
不调色不填 lutCode 即保持原片色彩(合法状态)
选型提示标注「LOG/平面专用」的滤镜是为 LOG/平面素材设计的,直接套常规成片会发灰,慎用;「饱和」为负表示整体降饱和(胶片感)

口径变更记录(2026-10-14):lutCode 最终统一为编号型(三位数字、含前导零,001–204,如 007)——与滤镜库、渲染校验实现一致。本文档 §15 示例曾出现名称型 "TEAL_ORANGE_01",属早期遗留,已废弃;名称型取值将因库中无同名文件而按「不调色」处理并记录告警。

如需完整清单(含缩略图与参数)的表格文件(Excel / CSV),可向对接人索取;线上总览页即上述链接。

17. 字幕(歌词)· 字体 · 转场 提交规范

2026-10-22 定版。本节把甲方最常问的三件事一次讲清楚:歌词怎么带、字体能不能指定、转场怎么声明。每项都标注了实现状态,请按状态列判断能否在本期使用。

一句话口径:歌词走素材上传(line_lyrics / word_lyrics)+ 平台自动加前置段偏移;转场走交付包 manifest.transitions(包级)或 MV 的 mv-shots.json → shots[].transition(逐镜);字体随歌词——由歌词样式整体决定(CD 内置卡拉OK / MV 歌词插件),不单独指定、也无预留字段(见 §17.3)。

17.1 速查表

维度甲方怎么带字段 / 位置适用状态
歌词(行级)作为素材上传,类型 line_lyrics .lrc(标准 LRC 或 <mm:ss.xx> 增强逐字)/ 行级 JSONCD + 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.3CD + MV — 不单独指定
(已定版不做)

17.2 歌词规范

① 三种给法(任选其一,不要重复上传互相矛盾的两份):素材上传 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 对应行)

17.3 字体规范(已定版:字体随歌词,不单独指定)

口径(2026-10-22 定版):字体不单独配置,一律「随歌词」。歌词用什么字体、字号、配色、描边,由渲染这份歌词的歌词样式整体决定——CD 走星光1号内置卡拉OK样式,MV 走所选歌词插件的样式。 甲方不传、也无需传任何字体字段;误传会被忽略(不报错、不告警)。本平台不做「任务级字体指定」,也没有预留字段——请不要按「可指定字体」设计对接。

① 各产出的字体来源(固定)

产出字体与版式(固定)
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 会回退),成本与稳定性都不划算,且会与插件样式规范冲突。该草案已删除,文档不再保留,避免甲方误以为可传。

17.4 转场规范

完整类型目录(49 项,含 fade / wipeleft / slideup / circleopen …)与各类型观感说明见 §15.4.3 转场系统,线上可搜版:转场库。

① 声明位置与优先级(高 → 低)

层级位置适用
逐镜声明(最高)mv-shots.json → shots[i].transition = {type, duration}MV
包级 per_shotmanifest.json → transitions.per_shot[k]CD + MV
包级 defaultmanifest.json → transitions.defaultCD + MV
转场插件 / 后台默认平台侧配置(甲方无需关心)CD + MV
兜底fade 0.5sCD + 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 } }
] }

17.5 状态与告警口径

情况平台行为
歌词缺失(整片无歌词素材)不阻断,渲染无歌词成片;任务正常完成
歌词时间戳错位(甲方加了偏移)不阻断,按错位渲染;需甲方重推修正
误传字体字段(如 typography)忽略,按歌词样式渲染,不报错、不告警
转场 type 写错不阻断,该处按默认/自定义转场渲染,记录日志
转场 duration 超范围夹取到 0.2–1.0s 后使用
MV 逐镜声明与包级冲突逐镜优先

17.6 推包前自查(这三件)

□ 歌词:包内有 line_lyrics(.lrc)或 word_lyrics(逐字 JSON),UTF-8
□ 歌词:时间戳从音频 0 秒起算(不加封面/海报偏移),且覆盖到音频结尾
□ 转场:manifest.json(或 MV 的 mv-shots.json)里 type 是目录内名称、duration 在 0.2–1.0s
□ 字体:不用管(字体随歌词,不单独指定);确需换字体请换歌词插件/模板

18. 星河字画(文字 PV)CD 模板

一句话:给「歌词 + 原唱音频」,出一支歌词同步的文字 PV成片。模板编号 xinghe-cd-001,由服务端直接编码(不排队占渲染机),比 MV 快得多。

18.1 模板信息

项值
template_idxinghe-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 秒真机样片,可直接播放确认观感)

18.2 素材要求

素材 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 逐项告诉你还缺哪一项 —— 补齐后自动回队,不用重新建单。

18.3 歌词怎么给(只关心一件事:一行一句)

给法写法推荐度
① 素材上传 line_lyrics标准 LRC([00:12.34]那一句歌词)或纯文本,一行一句✅ 推荐
② song_info.lyrics创建任务时把整段歌词作为字符串传入(\n 分行)可用(省一次上传)
与 §17.2 的口径差异(务必注意):本模板由星河字画引擎按歌曲节拍自动排轴, LRC 里的时间戳不参与对时(保留无害、会被自动剥掉)。所以: ① 不需要精确到毫秒的时间戳,也不要为此加偏移;② 关键是文本与断行正确(一行一句、不要一段多句、不要重复行); ③ 想逐句卡点请用 CD-2024-005(星光1号,走卡拉OK 逐字对时),不是本模板的能力。

编码:UTF-8(可带 BOM);不要 UTF-16。 不要在歌词里加 [ti:] / [ar:] 之外的舞台指令(会当普通文本处理)。

18.4 分辨率怎么指定(output_resolution)

{
  "output_resolution": { "width": 1920, "height": 1080, "fps": 30 }
}

取值必须命中模板 supported_resolutions,否则返回 4008:

档位width × height @ fps
720P1280 × 720 @ 30
1080P(默认)1920 × 1080 @ 30
2K2560 × 1440 @ 30
4K3840 × 2160 @ 30

不传则按模板默认 1080P 输出。当前模板为 16:9;竖屏(9:16)等其它画幅需另开模板,未在本模板范围内。

18.5 状态流转与错误码

创建 → 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 分钟量级设轮询上限

18.6 完整接入示例(可直接照抄)

# ① 建单(先不给素材,返回 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 签名,长期可重新查询获取)
小文件也可以不用直传:直接 POST /v1/video/materials(multipart/form-data,字段 file + type + task_id)一次完成上传与登记,见 §5。

18.7 常见问题

现象原因 / 处理
任务一直 awaiting_materials看 missing_materials:多数是只传了音频没传歌词(或相反)。补齐后自动回队
MISSING_LYRICS本地已有素材但歌词拿不到:确认 line_lyrics 已 confirm 成功(返回 url),或改用 song_info.lyrics 重提
歌词和歌声对不上本模板按节拍自动排轴,不做逐句对时。若要严格逐句卡点请用 CD-2024-005
成片时长和音频不一致成片时长≈音频时长(尾部按引擎收束 ±0.1s 内)。若相差大,检查音频是否被裁短/首尾静音过长
播放器放不出声音成片音轨统一转 AAC(引擎原生 Opus 在 iOS/Safari 不兼容,平台已自动转换)。若仍异常请反馈具体播放器
4008output_resolution 未命中 supported_resolutions,按 18.4 的档位传