VT 唇形同步
namifusion/vt-lipsync
VT 唇形同步通过翻译后的视频、翻译后音频、翻译后字幕时间轴,以及原始视频和原始字幕时间轴,对翻译后的视频进行口型同步。
示例
参数
| 名称 | 类型 | 默认 | 约束 | 说明 |
|---|---|---|---|---|
| audio_url *翻译后音频 | audio_upload | — | audio/mpeg,audio/wav,audio/ogg,audio/webm,audio/aac,audio/flac,audio/* | 提供与翻译后视频对应的翻译后音频。翻译服务和输入音频由调用方自行准备,只要求 ASR 分句结果能够与字幕时间轴对应。 |
| subs_list *翻译后字幕分段 | array<object> | [] | — | 提供翻译后视频按句子的 ASR 时间段。由于翻译后视频时长可能变化,这组字幕分段必须与翻译后目标视频对应。 |
| ↳start_ms *开始时间 (ms) | number | — | step 1 | 该分段的开始时间,单位毫秒。 |
| ↳end_ms *结束时间 (ms) | number | — | step 1 | 该分段的结束时间,单位毫秒。 |
| original_video_url *原始视频 | video_upload | — | video/mp4,video/webm,video/quicktime,video/* | 提供用户上传的原始视频。该视频用于作为原始口型结构的参考。 |
| original_subs_list *原始字幕分段 | array<object> | [] | — | 提供原始视频按句子的 ASR 时间段。原始字幕分段需要与翻译后字幕分段相互对应。 |
| ↳start_ms *开始时间 (ms) | number | — | step 1 | 该分段的开始时间,单位毫秒。 |
| ↳end_ms *结束时间 (ms) | number | — | step 1 | 该分段的结束时间,单位毫秒。 |
API
通过统一 REST API 调用本模型;在 API Keys 页获取密钥。
cURL
# 1) Submit — returns { "task_uuid": "..." }
curl -X POST "https://www.namifusion.com/api/v1/marketplace/run/namifusion/vt-lipsync" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": {
"audio_url": "https://d5v2vcqcwe9y5.cloudfront.net/algorithm/video_translate/260327/default/qtqfcgymg08o.wav",
"subs_list": [
{
"end_ms": 4178,
"start_ms": 300
}
],
"original_video_url": "https://d5v2vcqcwe9y5.cloudfront.net/video_translate/260327/6964a3741d6212ca41d15d2d/3ftvqu8aewix.mp4",
"original_subs_list": [
{
"end_ms": 3780,
"start_ms": 300
}
]
}
}'
# 2) Poll until status is "completed", then read the output URLs
curl "https://www.namifusion.com/api/v1/marketplace/run/tasks/TASK_UUID" \
-H "Authorization: Bearer YOUR_API_KEY"Python
import time, requests
API_KEY = "YOUR_API_KEY"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
# 1) Submit
resp = requests.post(
"https://www.namifusion.com/api/v1/marketplace/run/namifusion/vt-lipsync",
headers=HEADERS,
json={
"input": {
"audio_url": "https://d5v2vcqcwe9y5.cloudfront.net/algorithm/video_translate/260327/default/qtqfcgymg08o.wav",
"subs_list": [
{
"end_ms": 4178,
"start_ms": 300
}
],
"original_video_url": "https://d5v2vcqcwe9y5.cloudfront.net/video_translate/260327/6964a3741d6212ca41d15d2d/3ftvqu8aewix.mp4",
"original_subs_list": [
{
"end_ms": 3780,
"start_ms": 300
}
]
}
},
)
resp.raise_for_status() # 401/402/429/5xx stop here instead of polling a bad task
task = resp.json()
# 2) Poll until a terminal state (completed / failed / cancelled).
# This model is allowed up to 1800s server-side.
deadline = time.time() + 1860
while task.get("status") not in ("completed", "failed", "cancelled"):
if time.time() > deadline:
raise TimeoutError(f"still {task.get('status')} — keep the task_uuid and poll later")
time.sleep(3)
poll = requests.get(f"https://www.namifusion.com/api/v1/marketplace/run/tasks/{task['task_uuid']}", headers=HEADERS)
poll.raise_for_status()
task = poll.json()
print(task["status"], task.get("output"))JavaScript
const API_KEY = "YOUR_API_KEY";
const HEADERS = { Authorization: `Bearer ${API_KEY}` };
// 1) Submit
const resp = await fetch("https://www.namifusion.com/api/v1/marketplace/run/namifusion/vt-lipsync", {
method: "POST",
headers: { ...HEADERS, "Content-Type": "application/json" },
body: JSON.stringify({
"input": {
"audio_url": "https://d5v2vcqcwe9y5.cloudfront.net/algorithm/video_translate/260327/default/qtqfcgymg08o.wav",
"subs_list": [
{
"end_ms": 4178,
"start_ms": 300
}
],
"original_video_url": "https://d5v2vcqcwe9y5.cloudfront.net/video_translate/260327/6964a3741d6212ca41d15d2d/3ftvqu8aewix.mp4",
"original_subs_list": [
{
"end_ms": 3780,
"start_ms": 300
}
]
}
}),
});
if (!resp.ok) throw new Error(`submit failed: ${resp.status} ${await resp.text()}`);
let task = await resp.json();
// 2) Poll until a terminal state (completed / failed / cancelled).
// This model is allowed up to 1800s server-side.
const deadline = Date.now() + 1860 * 1000;
while (!["completed", "failed", "cancelled"].includes(task.status)) {
if (Date.now() > deadline) throw new Error(`still ${task.status} — keep the task_uuid and poll later`);
await new Promise((r) => setTimeout(r, 3000));
const poll = await fetch(`https://www.namifusion.com/api/v1/marketplace/run/tasks/${task.task_uuid}`, { headers: HEADERS });
if (!poll.ok) throw new Error(`poll failed: ${poll.status}`);
task = await poll.json();
}
console.log(task.status, task.output);文档
NamiFusion VT LipSync
视频翻译后口型同步:输入翻译后视频、翻译后音频及双侧分句时间轴,输出重新对齐口型的结果视频。
NamiFusion VT LipSync 是一个面向视频翻译场景的口型同步服务。它适用于"原始视频经过翻译后,视频时长和音频节奏发生变化"的情况,通过输入翻译后的视频、翻译后音频,以及翻译前后两套按句子切分的时间段信息,生成与目标音频对齐的口型同步视频。
核心特性
- 面向视频翻译场景: 专门处理翻译后音视频长度变化带来的口型错位问题。
- 双时间轴输入: 同时接收翻译后分句时间轴和原始视频分句时间轴,用于建立句级对应关系。
- 异步任务: 提交任务后返回
task_uuid,通过轮询或 Webhook 获取结果。 - 结果视频输出: 任务完成后返回口型同步后的视频 URL。
技术规格
| 参数 | 详情 |
|---|---|
| 模型 ID | namifusion/vt-lipsync |
| 请求方式 | 异步 POST(提交任务 + 轮询/Webhook 获取结果) |
| 输入 | 翻译后视频 URL + 翻译后音频 URL + 双侧分句时间轴 |
| 输出 | 口型同步后的视频 URL |
| 处理时间 | 通常数十秒到数分钟,取决于视频时长与分句数量 |
快速开始
API 端点
| 端点 | 方法 | 说明 |
|---|---|---|
/api/v1/marketplace/run/namifusion/vt-lipsync | POST | 提交 VT LipSync 任务 |
/api/v1/marketplace/run/tasks/{task_uuid} | GET | 查询任务状态与结果 |
认证
在请求 Header 中携带您的 API Key:
X-API-Key: sk-your-api-key
使用示例
第 1 步:提交任务
curl -X POST "https://www.namifusion.com/api/v1/marketplace/run/namifusion/vt-lipsync" \
-H "X-API-Key: sk-your-api-key" \
-H "Content-Type: application/json" \
-d '{
"input": {
"video_url": "https://example.com/translated_video.mp4",
"audio_url": "https://example.com/translated_audio.wav",
"subs_list": [
{ "start_ms": 0, "end_ms": 8090 },
{ "start_ms": 8090, "end_ms": 10269 }
],
"original_video_url": "https://example.com/original_video.mp4",
"original_subs_list": [
{ "start_ms": 0, "end_ms": 7840 },
{ "start_ms": 7840, "end_ms": 9820 }
],
}
}'
响应示例:
{
"task_uuid": "69b931ac-d2db-d096-fc0a-bed1a2c3d4e5",
"status": "pending",
"cost_credits": 0
}
第 2 步:轮询任务状态
curl -X GET "https://www.namifusion.com/api/v1/marketplace/run/tasks/69b931ac-d2db-d096-fc0a-bed1a2c3d4e5" \
-H "X-API-Key: sk-your-api-key"
处理中:
{
"task_uuid": "69b931ac-d2db-d096-fc0a-bed1a2c3d4e5",
"status": "processing"
}
完成:
{
"task_uuid": "69af63b1-285a-4ae0-fe92-6cc5a1b2c3d4",
"model_id": "namifusion/vt-lipsync",
"status": "completed",
"output": {
"lipsync_video_url": "https://d5v2vcqcwe9y5.cloudfront.net/algorithm/lipsync/260310/default/tx6hbykt7ntp.mp4",
"lipsync_from": 1
},
"cost_credits": 0,
"created_at": "2026-03-08T00:20:01Z",
"completed_at": "2026-03-08T00:21:31Z"
}
Python 调用示例
import requests
import time
API_KEY = "sk-your-api-key"
BASE_URL = "https://www.namifusion.com/api/v1/marketplace/run"
HEADERS = {
"X-API-Key": API_KEY,
"Content-Type": "application/json",
}
payload = {
"input": {
"video_url": "https://example.com/translated_video.mp4",
"audio_url": "https://example.com/translated_audio.wav",
"subs_list": [
{"start_ms": 0, "end_ms": 8090},
{"start_ms": 8090, "end_ms": 10269},
],
"original_video_url": "https://example.com/original_video.mp4",
"original_subs_list": [
{"start_ms": 0, "end_ms": 7840},
{"start_ms": 7840, "end_ms": 9820},
],
}
}
task_resp = requests.post(
f"{BASE_URL}/namifusion/vt-lipsync",
headers=HEADERS,
json=payload,
).json()
task_uuid = task_resp["task_uuid"]
print(f"Task submitted: {task_uuid}")
while True:
status_resp = requests.get(
f"{BASE_URL}/tasks/{task_uuid}",
headers=HEADERS,
).json()
status = status_resp["status"]
print(f"Status: {status}")
if status == "completed":
result = status_resp["output"]
print("Result video:", result["lipsync_video_url"])
print("Source type:", result.get("lipsync_from"))
break
if status == "failed":
print("Failed:", status_resp.get("error_message", "Unknown error"))
break
time.sleep(5)
参数与返回值详解
请求参数
请求体格式为 JSON,所有参数放在 input 对象中:
{
"input": {
"video_url": "https://...",
"audio_url": "https://...",
"subs_list": [
{ "start_ms": 6140, "end_ms": 8090 }
],
"original_video_url": "https://...",
"original_subs_list": [
{ "start_ms": 6140, "end_ms": 7840 }
]
}
}
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
video_url | string | 是 | - | 翻译后的视频 URL。该视频已按目标语言完成时长变化或动态重定时。 |
audio_url | string | 是 | - | 翻译后的音频 URL。服务将基于该音频进行口型同步。 |
subs_list | array | 是 | - | 翻译后音频的 ASR 分句结果,每个元素表示一句的起止时间。 |
original_video_url | string | 是 | - | 用户上传的原始视频 URL,用于提供原始说话口型参考。 |
original_subs_list | array | 是 | - | 原始视频音频的 ASR 分句结果,每个元素表示一句的起止时间。 |
分句时间段对象
subs_list 与 original_subs_list 的每个元素都使用相同结构:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
start_ms | integer | 是 | 当前句子的开始时间,单位毫秒。 |
end_ms | integer | 是 | 当前句子的结束时间,单位毫秒。 |
参数约束与对应关系
| 项目 | 说明 |
|---|---|
subs_list 与 original_subs_list | 两者分别是翻译后音频和原始音频的 ASR 分句结果,长度不要求一致。 |
| 时间单位 | 所有时间都使用毫秒。 |
| 时间顺序 | 每个分句对象都应满足 start_ms < end_ms。 |
| URL 可访问性 | 所有 URL 都应为服务端可直接下载的公开地址。 |
| 音视频对应关系 | video_url 与 audio_url 应属于同一份翻译后内容;original_video_url 与 original_subs_list 应属于同一份原始内容。 |
任务状态
提交任务后通过轮询获取状态,建议轮询间隔 5 秒:
| 状态 | 说明 |
|---|---|
pending | 任务已创建,等待处理。 |
processing | 任务正在处理中。 |
completed | 任务已完成,可从 output.lipsync_video_url 获取结果。 |
failed | 任务失败,查看 error_message 了解原因。 |
返回值结构
提交任务响应
| 字段 | 类型 | 说明 |
|---|---|---|
task_uuid | string | 任务唯一标识,用于后续查询状态。 |
status | string | 初始状态,通常为 pending。 |
cost_credits | number | 本次任务消耗的积分。 |
任务完成响应
| 字段 | 类型 | 说明 |
|---|---|---|
task_uuid | string | 任务唯一标识。 |
model_id | string | 模型 ID(namifusion/vt-lipsync)。 |
status | string | 任务状态。 |
output.lipsync_video_url | string | 口型同步后的视频 URL。 |
output.lipsync_from | integer | 结果来源标记。当前样例返回值为 1。 |
cost_credits | number | 消耗积分。 |
created_at | string | 任务创建时间(ISO 8601)。 |
completed_at | string | 任务完成时间(ISO 8601)。 |
error_message | string | 错误信息(仅 failed 时返回)。 |
内部任务字段映射
下表用于说明该对外 API 与底层任务文档字段的关系:
| 对外请求字段 | 底层任务文档字段 |
|---|---|
input.video_url | extra.video_url |
input.audio_url | extra.audio_url |
input.subs_list | extra.subs_list |
input.original_video_url | extra.original_video_url |
input.original_subs_list | extra.original_subs_list |
output.lipsync_video_url | data.lipsync_video_url |
output.lipsync_from | data.lipsync_from |
参数对输出结果的影响
| 参数 | 对结果的影响 |
|---|---|
video_url | 决定口型同步的基础画面与翻译后视频节奏。 |
audio_url | 决定结果视频最终需要对齐的目标语音内容。 |
subs_list | 翻译后音频的 ASR 分句结果,决定翻译后每句的时间边界,直接影响句级口型重对齐。 |
original_video_url | 提供原始嘴型运动参考,用于保留原视频说话特征。 |
original_subs_list | 原始音频的 ASR 分句结果,用于将原始视频句级时间与翻译后句级时间建立映射关系。 |
错误响应
当任务失败时,轮询响应中包含错误信息:
{
"task_uuid": "69b931ac-d2db-d096-fc0a-bed1a2c3d4e5",
"status": "failed",
"error_message": "Invalid subtitle alignment"
}
常见错误:
| 错误码 | 说明 |
|---|---|
| 400 | 参数错误,例如缺少必要字段、时间段格式不合法。 |
| 401 | 认证失败,API Key 无效或缺失。 |
| 408 | 下载视频或音频超时。 |
| 422 | 输入媒体不可访问,或分句时间与内容不匹配。 |
| 500 | 服务内部错误。 |
注意事项
- 请同时提供翻译后视频和翻译后音频:该服务依赖二者共同完成口型同步。
- 分句时间轴来自各自音频的 ASR 结果:
subs_list是翻译后音频的 ASR 分句结果,original_subs_list是原始音频的 ASR 分句结果,两者长度不要求一致。 - 翻译后视频允许长度变化:该服务适用于翻译后视频长度相较原视频发生变化的场景。
- 建议保证分句切分稳定:句子切分过粗或过碎,都会影响同步效果。
- 结果字段:最终结果视频地址位于
output.lipsync_video_url。
相关模型
Kling Omni Video O3
Kling Omni Video O3 参考到视频模型可通过多个视角的角色、道具或场景参考生成创意视频。提取主体特征并创建新的视频内容,同时保持帧间身份一致性。支持音频生成。即用型 REST API,性能最佳,无冷启动,价格实惠。
Kling Omni Video O3
Kling Omni Video O3 参考到视频模型可通过多个视角的角色、道具或场景参考生成创意视频。提取主体特征并创建新的视频内容,同时保持帧间身份一致性。支持音频生成。即用型 REST API,性能最佳,无冷启动,价格实惠。
Kling Omni Video O1 参考视频生成
Kling Omni Video O1 参考视频生成使用多个视角的角色、道具或场景参考来生成创意视频。它提取主体特征并在生成新视频内容的同时保持跨帧的身份一致性。提供即用型 REST API,最佳性能,无冷启动,价格实惠。
Kling Omni Video O1 参考视频生成
Kling Omni Video O1 参考视频生成使用多个视角的角色、道具或场景参考来生成创意视频。它提取主体特征并在生成新视频内容的同时保持跨帧的身份一致性。提供即用型 REST API,最佳性能,无冷启动,价格实惠。
Kling 3.0 Standard 动作控制
Kling 3.0 Standard 动作控制将参考视频中的动作转移到静态图片中进行动画化。上传角色图片和动作片段(舞蹈、动作、手势),模型提取动作生成流畅、逼真的视频。提供即用型 REST 推理 API,性能最佳,无冷启动,价格实惠。
seedance-2-0 reference-to-video
Seedance 2.0 的“参考生视频”功能是视觉统一的终极方案。它能精准提取参考素材的艺术风格、光影基调或构图意向,并将其完美融入新生成的视频中,确保您的系列创作拥有高度一致的视觉语言。
Alibaba WAN 2.6
Alibaba WAN 2.6 Reference-to-Video 能够将角色、道具或场景的参考图(无论是单视角还是多视角)转化为全新的视频片段。它在保持物体特征、风格及布局高度一致的同时,确保了动作的流畅自然。我们提供现成的 REST 推理 API,具备极致性能与零冷启动特性,价格极具竞争力。