Translate existing captions into another language with the Mux Robots API. Use translated captions when your videos reach viewers in more than one language.
Translate an existing caption track on a Mux asset from one language to another. The translated captions can be automatically attached to the asset as a new text track, making multilingual video accessible with a single API call. See the Translate Captions API referenceAPI for the full endpoint specification. See Mux Robots pricing for unit costs.
Caption translation requires an existing caption track on the asset. Make sure your asset has captions, either auto-generated or manually added, before creating a translate-captions job. By default, the request is also rejected if the asset already has a text track in the target language, or with the same name as the new track. See Managing existing tracks.
translate-captions jobcurl https://api.mux.com/robots/v0/jobs/translate-captions \
-H "Content-Type: application/json" \
-X POST \
-d '{
"parameters": {
"asset_id": "YOUR_ASSET_ID",
"track_id": "YOUR_TRACK_ID",
"to_language_code": "es"
}
}' \
-u ${MUX_TOKEN_ID}:${MUX_TOKEN_SECRET}This request is asynchronous. The POST returns immediately with the job in pending status and does not include results. We strongly recommend listening for the robots.job.translate_captions.completed webhook — the payload contains the full completed job, so no follow-up API call is needed. If webhooks aren't an option, you can poll GET /robots/v0/jobs/translate-captions/{JOB_ID} with the id from the response until the status is completed.
| Parameter | Type | Description |
|---|---|---|
asset_id | string | Required. The Mux asset ID whose captions will be translated. |
track_id | string | Required. The text track ID of the source caption track to translate. |
to_language_code | string | Required. BCP 47 target language code (e.g. es, ja). See language support for Mux Robots. |
upload_to_mux | boolean | Whether to upload the translated VTT and attach it as a text track on the asset. Defaults to true. |
replace_existing_tracks | string | What to do when the asset already has a conflicting text track: fail (the default), replace_all, or replace_generated. See Managing existing tracks. |
track_name | string | Name for the translated text track. Defaults to "{Language} (Auto-translated)", e.g. "Spanish (Auto-translated)". An existing track with this name is handled by replace_existing_tracks. |
never_translate | array of strings | Best-effort list of terms (brand names, proper nouns) to keep verbatim in the translation. Up to 100 terms, each up to 100 characters. Terms can't contain <, >, or invisible characters. Does not guarantee exact output. |
The outputs object is included in the job once its status is completed. You'll receive it on the robots.job.translate_captions.completed webhook (recommended), or you can fetch it with GET /robots/v0/jobs/translate-captions/{JOB_ID}. It contains:
| Field | Type | Description |
|---|---|---|
uploaded_track_id | string | Mux text track ID of the uploaded translated captions. Present when upload_to_mux is true. |
temporary_vtt_url | string | Temporary pre-signed URL to download the translated VTT file. Present when upload_to_mux is true. |
never_translate_terms_preserved | boolean | Present when never_translate was set. false when at least one term wasn't kept verbatim. |
replaced_tracks | array of objects | Every track deleted before the new track was created. Absent when nothing was deleted. See Managing existing tracks. |
This is the payload delivered to the robots.job.translate_captions.completed webhook, and the same shape you get from GET /robots/v0/jobs/translate-captions/{JOB_ID}:
{
"data": {
"id": "rjob_pqr678",
"workflow": "translate-captions",
"status": "completed",
"units_consumed": 1,
"parameters": {
"asset_id": "YOUR_ASSET_ID",
"track_id": "YOUR_TRACK_ID",
"to_language_code": "es",
"upload_to_mux": true
},
"outputs": {
"uploaded_track_id": "track_abc123",
"temporary_vtt_url": "https://storage.googleapis.com/..."
}
}
}When upload_to_mux is true (the default), the translated caption track is automatically attached to your asset. Your viewers will see the new language option in the player's caption menu without any additional work.
Use replace_existing_tracks to control what happens when the asset already has a text track in the target language (ignoring region, so es matches es-MX) or with the same name as the new track.
| Value | Behavior |
|---|---|
fail (default) | Nothing is deleted, and the new track isn't added. |
replace_all | Conflicting tracks are deleted, then the new track is added. |
replace_generated | Conflicting tracks auto-generated by Mux Video are deleted. If any other track conflicts, nothing is deleted and the new track isn't added. |
Tracks created by an earlier Robots job count as uploaded, so replacing one needs replace_all.
outputs.replaced_tracks.422. If a conflicting track is added while the job runs, the job errors instead. Neither case is billed.