# Dubbing API

Canonical docs: https://platform.sonilo.com/docs/api/dubbing
Source path: /docs/api/dubbing
Runtime API host: https://api.sonilo.com/v1

Do not send API requests to platform.sonilo.com, docs.sonilo.com, or local docs URLs. Documentation pages are for reading only. Send runtime requests to https://api.sonilo.com/v1 with Authorization: Bearer sk_your_api_key.

## Endpoint

POST /v1/dubbing

## Summary

Dub one video into several languages in a single async call, returning one dubbed .mp4 per requested language. Translates and re-voices the existing speech; it does not generate music or sound effects.

## Use This For

- Localizing a finished video into several languages without re-recording or re-editing it.
- Producing a per-language deliverable set from one source, in one call and one charge rather than one call per language.

## Request

- video: file upload. Provide exactly one of video or video_url.
- video_url: URL input, https only — plain http is rejected, not merely discouraged. Provide exactly one of video or video_url.
- languages: optional JSON array string of language codes, e.g. ["pt_br", "th"]. Defaults to ["zh_cn", "es", "fr"] when omitted — which bills for three languages, so pass an explicit single-element array if only one is wanted. Supported: en, zh_cn, ja, ko, pt, pt_br, es, es_419, de, fr, it, ru, th, ar, tr, vi, id. pt_br is Brazilian Portuguese and es_419 Latin American Spanish; plain pt and es are unqualified Portuguese and Spanish, so they are a third option rather than synonyms. ar is unqualified Arabic rather than one of the country dialects. An unsupported code is rejected with 422 before anything is charged.
- ducking: optional boolean, default false. Ducks the background music/effects bed under the dubbed voice while it speaks; the bed is kept either way, and this is free.
- lipsync: optional boolean, default true. With lip sync on, the speaker's mouth is re-rendered to match the dubbed speech. Pass lipsync=false to leave the picture completely untouched instead — the video comes back 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. Use it for footage with no on-camera speaker, or when preserving the exact original picture matters more than matching lip movement. The background bed is rebuilt either way, so ducking is unaffected.

## Response And Errors

- 202 returns task_id and status=processing.
- Poll GET /v1/tasks/{task_id} every 2-3 seconds.
- On success, read outputs — a map of language code to dubbed .mp4 URL. There is no single output_url, and no audio.url: a three-language request returns three entries keyed exactly by the codes that were requested.
- Billed as video duration multiplied by the number of languages requested, with a 10-second floor applied after that multiplication rather than per language. There are no free-trial runs on this endpoint, unlike most others.
- Source videos may be at most 300 seconds.
- 401 auth_invalid, 402 payment_required or insufficient_balance, 403 forbidden, 404 not_found, 422 unprocessable_entity (unsupported language code, over-limit duration, or a non-https video_url), and 429 Retry-After should be handled explicitly.

## Example

```bash
curl -X POST "https://api.sonilo.com/v1/dubbing" \
  -H "Authorization: Bearer sk_your_api_key" \
  -F "video_url=https://example.com/clip.mp4" \
  -F 'languages=["pt_br", "es_419", "th"]'
```

## Shared Error Handling

- 401 auth_invalid: set Authorization: Bearer sk_your_api_key on the request.
- 402 payment_required or insufficient_balance: add credits before rerunning; do not create fake audio.
- 403 forbidden: the key is valid but the account or service permission is missing.
- 404 not_found: check the endpoint path and host. Use https://api.sonilo.com/v1, not a docs URL.
- 429 rate_limit_exceeded: honor Retry-After and retry with backoff.

## Endpoint Vocabulary

- GET /v1/account/services
- GET /v1/account/usage
- POST /v1/text-to-music
- POST /v1/video-to-music
- POST /v1/audio-ducking
- POST /v1/text-to-sfx
- POST /v1/video-to-sfx
- GET /v1/tasks/{task_id}

