Sync Lipsync 1.9.0 Beta API Documentation
Playground
Try it on WaveSpeedAI!Generate realistic lip-sync animations from audio using advanced algorithms for high-quality facial synchronization. Ready-to-use REST inference API, best performance, no coldstarts, affordable pricing.
Features
sync/lipsync-1.9.0-beta takes an existing video and a separate audio track, then reanimates the speaker’s mouth so the lips match the new speech. It’s a zero-shot lipsync model from Sync Labs—no training or cloning step required.
🔍 Highlights
- Zero-shot lipsync – Works on any person in any video; just upload video + audio.
- Style-aware editing – Adjusts only the mouth region while keeping the person’s identity, lighting, and background intact.
- Cross-domain support – Handles live-action footage, stylised CG, and AI-generated faces.
- Flexible timing control – sync_mode lets you decide how to handle length mismatches between video and audio.
đź§© Parameters
-
video* Required. Input video to be edited (URL or upload). Use a shot with a clearly visible face for best results.
-
audio* Required. Target speech track (URL or upload, e.g. MP3/WAV). The model will align lip movements to this audio.
-
sync_mode Controls behavior when video and audio durations differ. Options:
-
loop
-
bounce
-
cut_off
-
silence
-
remap
Choose how you want the shorter stream to be treated (looped, trimmed, padded with silence, or time-remapped).
Output: a new video where the speaker’s lips follow the uploaded audio.
đź’° Pricing
Rate: $0.025 per second of processed video.
| Clip length (s) | Price (USD) |
|---|---|
| 5 | $0.13 |
| 10 | $0.25 |
| 20 | $0.50 |
| 30 | $0.75 |
| 60 | $1.50 |
You will only be charged for the actual duration of the input video after upload.
🚀 How to Use
- Upload your video in the video field (face should be front-facing or Âľ view, with minimal occlusion).
- Upload your audio in the audio field (clean speech, minimal background noise).
- Pick a sync_mode depending on how you want to handle length mismatches.
- Click Run and wait for the processed clip.
- Review the result; if timing feels off, try a different sync_mode or tweak your source video/audio.
đź’ˇ Tips
- Use clean, well-lit close-ups for the most convincing lipsync.
- Avoid heavy head turns or faces partially out of frame.
- For dubbed content, make sure the speech rhythm in your audio is reasonably close to the original—lipsync works best when phrasing and pauses roughly match the performance.
More Models to Try
-
WaveSpeedAI / InfiniteTalk WaveSpeedAI’s single-avatar talking-head model that turns one photo plus audio into smooth, lip-synced digital presenter videos for tutorials, marketing, and social content.
-
WaveSpeedAI / InfiniteTalk Multi Multi-avatar version of InfiniteTalk that drives several characters in one scene from separate audio tracks, ideal for dialog-style explainers, interviews, and role-play videos.
-
Kwaivgi / Kling V2 AI Avatar Standard Cost-effective Kling-based AI avatar model that generates natural talking-face videos from a single reference image and voice track, suitable for everyday content and customer support.
-
Kwaivgi / Kling V2 AI Avatar Pro Higher-fidelity Kling V2 avatar model for premium digital humans, offering smoother motion, better lip-sync, and more stable faces for commercials, brand spokespeople, and product demos.
Authentication
For authentication details, please refer to the Authentication Guide.
API Endpoints
Submit Task & Query Result
set -euo pipefail
export WAVESPEED_API_KEY="your-api-key"
REQUEST_BODY=$(cat <<'JSON'
{
"video": "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4",
"audio": "https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3",
"sync_mode": "cut_off"
}
JSON
)
# 1. Submit the prediction.
SUBMIT_RESPONSE=$(curl --silent --show-error --fail-with-body \
-X POST "https://api.wavespeed.ai/api/v3/sync/lipsync-1.9.0-beta" \
-H "Authorization: Bearer ${WAVESPEED_API_KEY}" \
-H "Content-Type: application/json" \
-d "${REQUEST_BODY}")
TASK=$(printf '%s' "${SUBMIT_RESPONSE}" | jq 'if type == "object" and has("data") then .data else . end')
PREDICTION_ID=$(printf '%s' "${TASK}" | jq -r '.id // empty')
if [ -z "${PREDICTION_ID}" ]; then
printf 'Submission response did not contain a prediction id
' >&2
exit 1
fi
RESULT_URL="https://api.wavespeed.ai/api/v3/predictions/${PREDICTION_ID}/result"
# 2. Poll until the prediction finishes.
while true; do
RESPONSE=$(curl --silent --show-error --fail-with-body \
"${RESULT_URL}" \
-H "Authorization: Bearer ${WAVESPEED_API_KEY}")
RESULT=$(printf '%s' "${RESPONSE}" | jq 'if type == "object" and has("data") then .data else . end')
STATUS=$(printf '%s' "${RESULT}" | jq -r '.status // empty')
case "${STATUS}" in
completed) printf '%s\n' "${RESULT}" | jq '.outputs'; break ;;
failed|cancelled|timeout|deleted) printf '%s\n' "${RESULT}" | jq . >&2; exit 1 ;;
*) sleep 2 ;;
esac
doneParameters
Task Submission Parameters
Request Parameters
| Parameter | Type | Required | Default | Range | Description |
|---|---|---|---|---|---|
| video | string | Yes | - | The video to be used for generation | |
| audio | string | Yes | - | - | The audio to be used for generation |
| sync_mode | string | No | cut_off | bounce, loop, cut_off, silence, remap | Defines how to handle duration mismatches between video and audio inputs. See the Media Content Tips guide https://docs.sync.so/compatibility-and-tips/media-content-tips#sync-mode-options for a brief overview, or the SyncMode enum below for detailed explanations of each option. |
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| code | integer | HTTP status code (e.g., 200 for success) |
| message | string | Status message (e.g., “success”) |
| data.id | string | Unique identifier for the prediction, Task Id |
| data.model | string | Model ID used for the prediction |
| data.outputs | array | Output values, usually URL strings; some models return text strings or structured result objects (empty when status is not completed) |
| data.urls | object | Object containing related API endpoints |
| data.status | string | Task status. completed is successful; failed, cancelled, timeout, and deleted are failure terminal statuses. |
| data.created_at | string | ISO timestamp of when the request was created (e.g., “2023-04-01T12:34:56.789Z”) |
| data.error | string | Error message (empty if no error occurred) |
| data.timings | object | Object containing timing details |
| data.timings.inference | integer | Inference time in milliseconds |
Result Request Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| id | string | Yes | - | Task ID |
Result Response Parameters
| Parameter | Type | Description |
|---|---|---|
| code | integer | HTTP status code (e.g., 200 for success) |
| message | string | Status message (e.g., “success”) |
| data | object | The prediction data object containing all details |
| data.id | string | Unique identifier for the prediction |
| data.model | string | Model ID used for the prediction |
| data.outputs | array<string | object> | Array of generated outputs (empty when status is not completed). Items are usually URL strings, but may be text strings or structured result objects, depending on the model. |
| data.urls | object | Object containing related API endpoints |
| data.status | string | Status: completed is successful; failed, cancelled, timeout, and deleted are failure terminal statuses |
| data.created_at | string | ISO timestamp of when the request was created |
| data.error | string | Error message (empty if no error occurred) |
| data.timings | object | Object containing timing details |
| data.timings.inference | integer | Inference time in milliseconds |