Unified Models · byte-omnihuman-1-5

OmniHuman 1.5 数字人视频,接进 unified 了

一张人像图 + 一段音频(<60 秒),出一条对口型说话视频。走火山 visual API(V4 签名),由 bytedance-proxy 代理,unified 里当普通 image2video 模型调。TEST 环境端到端已跑通。

success
TEST 端到端结果
7分28秒
整单耗时(720p fast)
0 行
consumer 新增代码
1 条
模型配置(Path A)

这条链路长什么样

QUEUE X-MODEL V4 签名 15s 轮询 WEBHOOK 回投 CALLER 你的服务 POST /generate UNIFIED queue consumer BYTEDANCE_PROXY PROXY bytedance-proxy 主体gate · 202 queued VOLCENGINE visual API CVSubmitTask/GetResult CF QUEUE callback-queue kind=omnihuman_poll STORE R2 funpub cdn-asia.funplus… LEGEND 焦点 · 本次改动 已有服务 存储 / 队列 轮询(火山无 callback)

关键差异:火山这个接口不会主动回调,所以 proxy 用自己的 Cloudflare Queue 每 15 秒发一条延迟消息去查任务,查到终态才把结果 webhook 回 unified consumer。对 unified 来说它和其它 async 模型没有区别。

最终配置(TEST 已注册,可直接拷去 prod)

{
  "model_id": "byte-omnihuman-1-5",
  "name": "byte-omnihuman-1-5",
  "display_name": "OmniHuman 1.5 (Volcengine)",
  "enabled": true,
  "supported_types": ["image2video"],
  "config": {
    "image2video": {
      "async": true,
      "timeout": 1500000,          // 25 分钟:proxy 轮询上限 80 次 × 15s ≈ 20 分钟,留余量
      "provider": "bytedance",
      "worker_binding": "BYTEDANCE_PROXY",
      "supports_n": false,
      "parameterMapping": {},       // 字段名与 proxy 完全一致,直传
      "defaults": {},
      "provider_headers": {
        "X-Model": "video/omnihuman-1.5"
      },
      "outputMapping": {
        "status": "status",
        "results": "videos"         // proxy 的 results[] → unified 的 videos[]
      }
    }
  }
}

byte-seedance-1-pro-i2v 同款形状写的。没有 fallback_model_id —— 数字人对口型没有可替补的等价模型,失败就该原样报给 caller。

prod 建模命令

curl -X POST "https://model-config-dashboard.pages.dev/api/models" \
  -H "Content-Type: application/json" \
  -d '{"model_id":"byte-omnihuman-1-5","name":"byte-omnihuman-1-5","display_name":"OmniHuman 1.5 (Volcengine)","enabled":true,"supported_types":["image2video"],"config":{"image2video":{"async":true,"timeout":1500000,"provider":"bytedance","worker_binding":"BYTEDANCE_PROXY","supports_n":false,"parameterMapping":{},"defaults":{},"provider_headers":{"X-Model":"video/omnihuman-1.5"},"outputMapping":{"status":"status","results":"videos"}}}}'

prod 除这条 curl 外什么都不用动:bytedance-proxy 是单 worker,prod/test consumer 早就都绑了 BYTEDANCE_PROXY,火山 secrets 也已设在 proxy 上。

调用示例

POST https://unified-generation-api.adtech-videogen.workers.dev/generate
Authorization: Bearer <你的 unified key>

{
  "type": "image2video",
  "models": ["byte-omnihuman-1-5"],
  "input": {
    "image_url": "https://.../portrait.jpeg",   // 必填,人像图
    "audio_url": "https://.../speech.mp3",      // 必填,音频 <60s(15s 内效果最好)
    "prompt": "自然微笑,轻微点头",               // 可选,≤300 字符
    "output_resolution": 1080,                  // 可选,720 或 1080(默认 1080)
    "pe_fast_mode": false,                      // 可选,720 配 true / 1080 配 false 最接近即梦
    "mask_url": ["https://.../mask.png"],       // 可选,指定谁说话(多主体图才需要)
    "seed": -1,                                 // 可选
    "skip_subject_check": false                 // 可选,true 跳过主体识别省 ~20s
  }
}
字段必填说明
image_urltask-type 要求的字段,也是 proxy 的原生字段名,直传不映射
audio_url60 秒硬上限(超了提交成功但查询报 50215);建议 15 秒内
output_resolution / pe_fast_mode720+fast 实测约 3 分钟出片;1080+非 fast 更慢但质量高
skip_subject_check默认先跑主体识别(约 20 秒),图里没人/类人主体直接快速失败,不花生成钱

测试结果(TEST 环境真实一单)

task_id1df3529b-376d-4d81-b4e1-5fbef3d62d05
输入Seedream 生成人像 + 8 秒合成音频,720p + fast mode
提交 → 完成07:30:39 → 07:38:08(7 分 28 秒,含主体识别 + 排队)
最终 statussuccess(subtask completed,无 fallback)
产出07eb78ed…mp4(1.9 MB,HTTP 200 已验证下载)

另有 proxy 直连一单(绕过 unified):960×960 H.264+AAC、8 秒、1.86 MB,中间帧人像口型正常。两条路径都验过。

接入方要知道的一件事:火山对这条线的内容审核明显比 ARK 严。实测一张真人合照图被拦(50411 Pre Img Risk Not Pass)、一段 29 秒音乐音频被拦(50514 Pre Audio Risk Not Pass),换成 AI 生成人像 + 干净音频就过。这类错误 proxy 会把火山的 code + message 原样透传,caller 能直接看到被拦原因,不会重试(重试也过不了)。

DB / 部署影响