VT Lip Sync

namifusion/vt-lipsync

VT Lip Sync synchronizes mouth movements for a translated video by using the translated target video, translated audio, translated subtitle timing, and the original source video with its original subtitle timing.

Examples

VT Lip Sync example 1

Parameters

NameTypeDefaultConstraintsDescription
audio_url *Translated Audioaudio_uploadaudio/mpeg,audio/wav,audio/ogg,audio/webm,audio/aac,audio/flac,audio/*Provide the translated audio that matches the translated video. The caller is expected to prepare the translated audio, and the service only requires that the ASR segmentation can align with the subtitle timing.
subs_list *Translated Subtitle Segmentsarray<object>[]Provide sentence-level ASR timing for the translated video. Because the translated video length can change, these subtitle segments must match the translated target video.
start_ms *Start Time (ms)numberstep 1Segment start time in milliseconds.
end_ms *End Time (ms)numberstep 1Segment end time in milliseconds.
original_video_url *Original Videovideo_uploadvideo/mp4,video/webm,video/quicktime,video/*Provide the original source video uploaded by the user. This is the reference video used to preserve the original mouth movement structure.
original_subs_list *Original Subtitle Segmentsarray<object>[]Provide sentence-level ASR timing for the original source video. The original and translated subtitle segmentations need to stay aligned between the two videos.
start_ms *Start Time (ms)numberstep 1Segment start time in milliseconds.
end_ms *End Time (ms)numberstep 1Segment end time in milliseconds.

API

Call this model through one unified REST API. Get a key on the API Keys page.

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);

Documentation

NamiFusion VT LipSync

Lip-sync for translated videos: input a translated video, translated audio, and sentence-level timelines for both sides, then output a lip-synced result video.

NamiFusion VT LipSync is a lip-sync service designed for video translation scenarios. It is suitable for cases where the duration and rhythm of a video change after translation. By providing the translated video, translated audio, and two sets of sentence-level timing segments for the original and translated content, it generates a lip-synced video aligned with the target audio.


Key Features

  • Built for video translation workflows: Specifically handles lip-sync drift caused by changes in audio and video length after translation.
  • Dual timeline input: Accepts both translated sentence-level timelines and original sentence-level timelines to establish sentence-to-sentence alignment.
  • Async Tasks: Returns a task_uuid after submission, and you can retrieve results through polling or Webhook.
  • Result video output: Returns the lip-synced video URL when the task is completed.

Technical Specifications

ParameterDetails
Model IDnamifusion/vt-lipsync
Request MethodAsync POST (submit task + poll/Webhook for results)
InputTranslated video URL + translated audio URL + dual sentence-level timelines
OutputLip-synced video URL
Processing TimeTypically tens of seconds to several minutes, depending on video duration and number of sentence segments

Quick Start

API Endpoints

EndpointMethodDescription
/api/v1/marketplace/run/namifusion/vt-lipsyncPOSTSubmit a VT LipSync task
/api/v1/marketplace/run/tasks/{task_uuid}GETQuery task status and results

Authentication

Include your API Key in the request header:

X-API-Key: sk-your-api-key

Usage Example

Step 1: Submit a Task

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 }
      ],

    }
  }'

Response Example:

{
  "task_uuid": "69b931ac-d2db-d096-fc0a-bed1a2c3d4e5",
  "status": "pending",
  "cost_credits": 0
}

Step 2: Poll Task Status

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"

Processing:

{
  "task_uuid": "69b931ac-d2db-d096-fc0a-bed1a2c3d4e5",
  "status": "processing"
}

Completed:

{
  "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 Example

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)

Detailed Parameters and Return Values

Request Parameters

The request body is JSON, and all parameters are placed inside the input object:

{
  "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 }
    ]
  }
}
ParameterTypeRequiredDefaultDescription
video_urlstringYes-URL of the translated video. This video has already been retimed or duration-adjusted for the target language.
audio_urlstringYes-URL of the translated audio. The service performs lip-sync based on this audio.
subs_listarrayYes-ASR sentence segmentation result for the translated audio. Each item represents the start and end time of one sentence.
original_video_urlstringYes-URL of the original video uploaded by the user. Used as the source reference for original mouth movements.
original_subs_listarrayYes-ASR sentence segmentation result for the original video audio. Each item represents the start and end time of one sentence.

Sentence Timeline Object

Each item in subs_list and original_subs_list uses the same structure:

FieldTypeRequiredDescription
start_msintegerYesStart time of the current sentence, in milliseconds.
end_msintegerYesEnd time of the current sentence, in milliseconds.

Parameter Constraints and Correspondence

ItemDescription
subs_list and original_subs_listThese are the ASR sentence segmentation results for the translated audio and original audio respectively. Their lengths do not need to match.
Time unitAll time values use milliseconds.
Time orderEach sentence object should satisfy start_ms < end_ms.
URL accessibilityAll URLs should be publicly accessible so the server can download them directly.
Audio-video correspondencevideo_url and audio_url must belong to the same translated content; original_video_url and original_subs_list must belong to the same original content.

Task Status

After submitting the task, query its status by polling. A 5-second polling interval is recommended:

StatusDescription
pendingThe task has been created and is waiting to be processed.
processingThe task is being processed.
completedThe task is completed, and the result is available in output.lipsync_video_url.
failedThe task failed. Check error_message for the reason.

Return Value Structure

Task Submission Response

FieldTypeDescription
task_uuidstringUnique task identifier used for later status queries.
statusstringInitial task status, usually pending.
cost_creditsnumberCredits consumed by this task.

Task Completion Response

FieldTypeDescription
task_uuidstringUnique task identifier.
model_idstringModel ID (namifusion/vt-lipsync).
statusstringTask status.
output.lipsync_video_urlstringURL of the lip-synced video.
output.lipsync_fromintegerResult source marker. The current example response returns 1.
cost_creditsnumberCredits consumed.
created_atstringTask creation time (ISO 8601).
completed_atstringTask completion time (ISO 8601).
error_messagestringError message, returned only when failed.

Internal Task Field Mapping

The following table shows the relationship between the public API fields and the underlying task document fields:

Public Request FieldUnderlying Task Document Field
input.video_urlextra.video_url
input.audio_urlextra.audio_url
input.subs_listextra.subs_list
input.original_video_urlextra.original_video_url
input.original_subs_listextra.original_subs_list
output.lipsync_video_urldata.lipsync_video_url
output.lipsync_fromdata.lipsync_from

How Parameters Affect the Output

ParameterEffect on Output
video_urlDetermines the base visuals and translated-video pacing used for lip-sync alignment.
audio_urlDetermines the target speech content that the result video must align with.
subs_listASR sentence segmentation result for the translated audio. It defines the sentence boundaries in the translated content and directly affects sentence-level lip-sync realignment.
original_video_urlProvides the original mouth movement reference to preserve the speaking characteristics of the source video.
original_subs_listASR sentence segmentation result for the original audio. It is used to map sentence-level timing from the original video to the translated version.

Error Response

When a task fails, the polling response contains an error message:

{
  "task_uuid": "69b931ac-d2db-d096-fc0a-bed1a2c3d4e5",
  "status": "failed",
  "error_message": "Invalid subtitle alignment"
}

Common errors:

Error CodeDescription
400Invalid parameters, such as missing required fields or invalid timeline format.
401Authentication failed because the API Key is missing or invalid.
408Timeout while downloading video or audio.
422Input media is inaccessible, or the sentence timelines do not match the content correctly.
500Internal service error.

Notes

  1. Provide both the translated video and translated audio: The service depends on both inputs to perform lip-sync correctly.
  2. Sentence timelines must come from ASR results of their respective audio tracks: subs_list is the ASR sentence segmentation result for the translated audio, and original_subs_list is the ASR sentence segmentation result for the original audio. Their lengths do not need to match.
  3. Translated videos may have different durations: This service is designed for scenarios where the translated video length differs from the original video.
  4. Stable sentence segmentation is recommended: Segmentation that is too coarse or too fragmented may reduce sync quality.
  5. Result field: The final output video URL is located at output.lipsync_video_url.

Related models

Kling Omni Video O3
Video to VideoKling

Kling Omni Video O3

Kling Omni Video O3 Reference-to-Video generates creative videos using character, prop, or scene references from multiple viewpoints. Extracts subject features and creates new video content while maintaining identity consistency across frames. Supports audio generation. Ready-to-use REST API, best performance, no cold starts, affordable pricing.

from $0.380 / per run
Kling Omni Video O3
Video to VideoKling

Kling Omni Video O3

Kling Omni Video O3 Reference-to-Video generates creative videos using character, prop, or scene references from multiple viewpoints. Extracts subject features and creates new video content while maintaining identity consistency across frames. Supports audio generation. Ready-to-use REST API, best performance, no cold starts, affordable pricing.

from $0.630 / per run
Kling Omni Video O1 Reference-to-Video
Video to VideoKling

Kling Omni Video O1 Reference-to-Video

Kling Omni Video O1 Reference-to-Video generates creative videos using character, prop, or scene references from multiple viewpoints. Extracts subject features and creates new video content while maintaining identity consistency across frames. Ready-to-use REST API, best performance, no cold starts, affordable pricing.

from $0.380 / per run
Kling Omni Video O1 Reference-to-Video
Video to VideoKling

Kling Omni Video O1 Reference-to-Video

Kling Omni Video O1 Reference-to-Video generates creative videos using character, prop, or scene references from multiple viewpoints. Extracts subject features and creates new video content while maintaining identity consistency across frames. Ready-to-use REST API, best performance, no cold starts, affordable pricing.

from $0.630 / per run
Kling 3.0 Standard
Video to VideoKling

Kling 3.0 Standard

Kling 3.0 Standard Motion Control transfers motion from reference videos to animate still images. Upload a character image and a motion clip (dance, action, gesture), and the model extracts the movement to generate smooth, realistic video. Ready-to-use REST inference API, best performance, no cold starts, affordable pricing.

from $0.380 / per run
seedance-2-0 reference-to-video
Video to VideoDoubao

seedance-2-0 reference-to-video

The "Reference-to-Video" feature of Seedance 2.0 is the ultimate solution for visual stylistic unity. It precisely extracts artistic styles, lighting tones, or compositional intents from reference materials and seamlessly integrates them into newly generated videos, ensuring a highly consistent visual language for your creative series.

from $0.470 / per run
Alibaba WAN 2.6
Video to VideoAlibaba

Alibaba WAN 2.6

Alibaba WAN 2.6 Reference-to-Video seamlessly transforms character, prop, or scene references—supporting both single and multi-view inputs—into high-quality video sequences. It excels at preserving identity, style, and layout while delivering fluid, coherent motion. Experience peak performance via our production-ready REST API, featuring zero cold starts and cost-effective pricing.

from $0.750 / per run