Video translation

For AI agents →First 15 seconds free: 1 preview per account, one language, no credit card required.
Translate a video into one or more target languages — translated speech, mixed back under the original music/effects bed. Returns 202 Accepted with a task_id; poll GET /v1/tasks/:task_id until the task reaches a terminal status.
POST/v1/dubbingmultipart/form-data
API URLhttps://api.sonilo.com/v1/dubbing

Send API requests to https://api.sonilo.com. The platform.sonilo.com/docs pages are documentation only and are not API endpoints.

curl -X POST https://api.sonilo.com/v1/dubbing \
  -H "Authorization: Bearer $SONILO_API_KEY" \
  -F "[email protected]" \
  -F 'languages=["ja","tr"]' \
  -F "subtitles[ja][email protected]" \
  -F "subtitles[tr]=https://cdn.example.com/episode1.tr.vtt" \
  -F "export_srt=true"
# => {"task_id": "9f5f2f7e-...", "status": "processing"}

curl https://api.sonilo.com/v1/tasks/9f5f2f7e-... \
  -H "Authorization: Bearer $SONILO_API_KEY"
# poll until "status" is "succeeded" or "failed"
{
  "task_id": "9f5f2f7e-…",
  "status": "processing",
  "subtitle_preflight": {
    "ja": {
      "status": "prepared_review_required",
      "cue_count": 42,
      "issues": [],
      "changes_count": 0
    },
    "tr": {
      "status": "prepared_review_required",
      "cue_count": 38,
      "issues": [],
      "changes_count": 0
    }
  }
}

Authorization

Authenticate via Bearer token. Generate keys at the API Keys page and pass them in the Authorization header on every request. Keep keys server-side, for example in SONILO_API_KEY.

Authorization: Bearer sk_your_api_key

Store the key server-side, commonly as SONILO_API_KEY. A 401 means the key is missing, invalid, or revoked. A 403 means the key is valid but the account does not have access to that endpoint or workspace.

Body Parameters

videofile
Video file upload. Provide either video or video_url, not both. Accepted formats: mp4, mov, webm, m4v, gif (animated). Max file size: default 300MB. Max duration: 300 sec.
video_urlstring
URL to a video file. Provide either video or video_url, not both. Must be a public https:// URL — plain http:// is rejected (the dubbing pipeline requires https); private/internal addresses are rejected.
languagesstring
Optional JSON array of target language codes, e. g. ["es", "fr"]. Defaults to ["zh_cn", "es", "fr"] when omitted. Billed as video duration × number of languages requested.
en
English
zh_cn
Chinese (Simplified)
ja
Japanese
ko
Korean
pt
Portuguese
pt_br
Portuguese (Brazil)
es
Spanish
es_419
Spanish (Latin America)
de
German
fr
French
it
Italian
ru
Russian
th
Thai
ar
Arabic
tr
Turkish
vi
Vietnamese
id
Indonesian
ta
Tamil
ml
Malayalam
kn
Kannada
gu
Gujarati
pa_in
Punjabi (India)
sd_in
Sindhi (India)
hi
Hindi

pt and es are unqualified Portuguese and Spanish. Request pt_br or es_419 when the region matters — they are additional targets, not replacements. Punjabi and Sindhi are available in their Indian variants only — that is what pa_in and sd_in say.

duckingboolean
Optional boolean. Set to true to apply Sonilo ducking — the background music/effects bed is lowered while the dubbed voice is speaking. Defaults to false: the dubbed voice is mixed over the bed unchanged.
lipsyncboolean
Optional boolean, defaults to true. With lip sync on, the speaker's mouth is re-rendered to match the dubbed speech. Set lipsync=false to leave the picture completely untouched instead — the video is returned at its original resolution and frame rate rather than re-rendered, and only the audio is replaced, so the mouths keep moving to the original language. Useful for footage with no on-camera speaker, or when preserving the exact original picture matters more than matching lip movement. The background music/effects bed is rebuilt either way, so ducking behaves the same.
subtitles[<language>]file | string
Optional. One subtitle script per entry in languages, sent as subtitles[language]: an uploaded .srt or .vtt file, or a public https:// URL. Example: subtitles[ja][email protected], subtitles[tr]=https://cdn.example.com/episode1.tr.vtt. Scripts are in the target language and the dub speaks them verbatim instead of translating the source speech. Every requested language needs exactly one script. Max file size: 1 MiB each. Validated before billing — a rejected script returns 422 with code SUBTITLE_PREFLIGHT_BLOCKED and, under details, the report keyed by language.
export_srtboolean
Optional boolean, defaults to false. Requires subtitles. Returns every language's lines re-timed against its dubbed audio as subtitles on the finished task.

Response

task_idstring
The task identifier. Poll the Get Task endpoint (GET /v1/tasks/:task_id) until the task reaches a terminal status.
statusstring
Always processing on submission — generation runs asynchronously.
outputsobject
Present when the task succeeded — a map of language code to a temporary download URL for that language's dubbed video, valid for 7 days.
subtitlesobject
Present when export_srt was set and the task succeeded — a map of language code to a temporary download URL for that language's re-timed .srt.
subtitle_preflightobject
Present when subtitle scripts were given — per language: status, cue_count, issues, changes_count, report_url.
subtitle_exportobject
Present when export_srt was set — per language: status (exported, exported_review_required or blocked), issues, alignment_loss, error, report_url. A blocked export never fails the task.
trial_previewobject
Present when this run was the account's free preview: the first 15 seconds of the video, in one language, at no charge. Carries preview_seconds, source_duration_seconds, trimmed, languages, full_video_cost_usd (what translating the full video costs) and a message. Repeated on the task in every state.
duration_secondsnumber
The source video's duration, in seconds. Present when the task succeeded.