Dubbing
Dub a video into another language over the Direct API with dub_media on Morphic Dub, quote it first, follow the generation, and read the settled charge.
dub_media dubs one recording into another language in its speakers' own voices. On Morphic Dub (mdl_h2z5a7af7y50) it takes a video up to 10 minutes long and returns the same video, the same length, with every speaker re-voiced in their own voice and their close-ups lip-synced to the new speech. It is a long generation, up to about 13 minutes per minute of video, and its charge is an estimate at start that is settled to what the run spent.
Choose the model
| Model | model_id | Takes | Returns |
|---|---|---|---|
| Morphic Dub | mdl_h2z5a7af7y50 | one video, up to 10 minutes | the video, dubbed and lip-synced |
| ElevenLabs Dubbing | see the catalog | one audio or video file, up to 30 minutes | an audio file, the length of the source |
Omit model_id and a video runs on your organization's default dubbing model, which is Morphic Dub on paid plans. Name mdl_h2z5a7af7y50 to pin it. An audio file, or a video longer than 10 minutes, is refused on Morphic Dub with 422 naming the limit; send those to ElevenLabs Dubbing.
Inputs
| Field | Required | |
|---|---|---|
media_asset_id | yes | the video to dub: an asset id from list_assets, a finished generation's asset, or a public HTTPS URL (see Passing your own media) |
target_language | yes | one BCP-47 tag, such as hi, es or pt-BR. One language per call; for several markets, make one call per language. Morphic Dub dubs a regional variant in its main language and says so in the response's notice |
source_language | no | the language spoken, as a BCP-47 tag. Omit to have it detected; set it when the audio is noisy or mixes languages |
keyterms | no | names, places and brands the translation keeps as spoken, each up to 5 words |
voice_mode | no | original (the default) keeps every speaker's own voice; assigned speaks each person in a catalog voice. Morphic Dub only |
voices | no | who speaks in which voice, up to 20 entries; needs voice_mode: "assigned". See Assign voices |
source_transcript_asset_id | no | your own timed SRT of the speech, in the spoken language, used instead of transcribing; on Morphic Dub needs voice_mode: "assigned", on ElevenLabs Dubbing needs source_language |
translation_asset_id | no | your own timed SRT of the lines in the target language, used instead of translating; on Morphic Dub needs voice_mode: "assigned", on ElevenLabs Dubbing goes only with source_transcript_asset_id |
model_id | no | mdl_h2z5a7af7y50 for Morphic Dub. A call carrying voice_mode: "assigned", voices or either SRT with no model named runs on Morphic Dub; naming another model with them is refused |
project_id | yes | the project the dub lands in, from list_projects |
A video with no audio stream, or a target_language equal to the source_language you set, is refused before anything is charged.
Assign voices, bring your own transcript or translation
By default every speaker keeps their own voice and Morphic transcribes and translates the speech. With voice_mode: "assigned", each person speaks in a voice from Morphic's voice catalog instead, and you can hand in your own text. On Morphic Dub, a transcript or translation of your own needs assigned: the original voices are dubbed in one pass that takes no cast and no text, and a call that sends either with original is refused with 422 naming the field.
- List the voices a dub can assign:
list_voiceswithmodel_id: "mdl_h2z5a7af7y50". It needs no scope and returns each voice'svoice_id. Catalog voices only; a voice of your organization is refused - For a speaker named by a face image or a clip, pass the asset's id or its HTTPS URL as
speaker_asset_id; otherwise describe them inspeaker_description(up to 120 characters, none of;,=or"). Exactly one of the two per entry, and each speaker once; speakers you leave out get a fitting catalog voice - For your own SRT, pass its HTTPS URL or the id of an SRT document already in your library (
list_assetsshows it) assource_transcript_asset_id(spoken language) ortranslation_asset_id(target language); a URL is added to the project as a document before the dub starts, like any other file by URL. The two fields take two different files
{
"input": {
"media_asset_id": "01928f4e-…",
"target_language": "es",
"voice_mode": "assigned",
"voices": [
{ "speaker_asset_id": "https://cdn.example.com/host-face.jpg", "voice_id": "0192b1c0-…" },
{ "speaker_description": "the narrator", "voice_id": "0192b1c1-…" }
],
"source_transcript_asset_id": "https://cdn.example.com/interview.en.srt",
"translation_asset_id": "https://cdn.example.com/interview.es.srt",
"model_id": "mdl_h2z5a7af7y50",
"project_id": "01928f4e-…"
}
}Both voice modes are charged at the same rate.
Over MCP the two SRT fields work on ElevenLabs Dubbing too, with model_name: "ElevenLabs Dubbing" and no voices: every speaker keeps their own voice, source_language is required, since the engine cannot detect the language from a transcript, and translation_asset_id goes only beside source_transcript_asset_id, with a translated cue over every transcript cue. When most cues start with a speaker label, such as Mira: …, the labels decide who speaks when, one voice per speaker. ElevenLabs Dubbing has no model_id, so over the Direct API a dub with your own text runs on Morphic Dub.
Quote it first
A dub is priced on the length of the source, per language. plan_media prices the call without starting it; on Morphic Dub the quote is the estimate the start will charge, which settlement can later move.
{
"input": {
"steps": [
{ "id": "dub", "tool_name": "dub_media", "arguments_json": "{\"media_asset_id\":\"01928f4e-…\",\"target_language\":\"hi\",\"model_id\":\"mdl_h2z5a7af7y50\"}" }
]
}
}See Quote before you spend for the full call.
Start the dub
curl -s https://mcp.morphic.com/v1/direct/tools/dub_media \
-H "Authorization: Bearer $MORPHIC_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: dub-interview-hi-1" \
-d '{
"input": {
"media_asset_id": "https://cdn.example.com/interview.mp4",
"target_language": "hi",
"keyterms": ["Arjun", "Meera"],
"model_id": "mdl_h2z5a7af7y50",
"project_id": "01928f4e-…"
}
}'The response is 202 Accepted:
{
"result": {
"generation_id": "0192a7b3-a1c4-7e02-8f9d-1a2b3c4d5e6f",
"status": "queued",
"model_id": "mdl_h2z5a7af7y50",
"estimated_credits": 580,
"credits_settle_on_output_duration": true
},
"billing": { "credits_charged": 580, "credits_are_final": false }
}estimated_credits is the estimate charged now; credits_settle_on_output_duration: true says it will be settled.
Follow the generation
A dub on Morphic Dub takes up to about 13 minutes per minute of video, and a short clip takes longer than that ratio suggests, since the fixed stages cost the same whatever the length: a 50-second clip took 17 minutes. Do not poll from the start. Wait about 13 times the clip's length, then read with a long wait and back off from the poll_after_seconds each read carries.
sleep 660 # a 50 s clip: about 13 times its length
curl -s "https://mcp.morphic.com/v1/direct/generations/$GENERATION_ID?wait=45" \
-H "Authorization: Bearer $MORPHIC_API_KEY"A webhook spares you the loop: pass a registered webhook_id in the call body and Morphic calls your endpoint when the dub is final. Use the webhook as the main signal and an occasional poll as the safety net.
When the generation is succeeded, its assets hold the dubbed video. The response's notice is set when the dub ran on another input than the one given, such as a regional variant dubbed in its main language.
What it costs
Morphic Dub is billed on the source's length at your organization's API rates, per language:
- At start, the estimate is charged:
estimated_credits, alsobilling.credits_charged - When the dub finishes, the charge is settled to what the run actually spent. The settled amount can be below or above the estimate, but never more than three times it; past that, Morphic absorbs the rest
- Once the generation is final,
billing.credits_chargedis the settled net amount andcredits_are_finalistrue. A dub that fails or is cancelled is refunded in full
Read the generation again once it is final for the settled amount; a webhook is sent only once it is. See Credits and usage for the ledger.
If you have any trouble or have any questions, feel free to reach out. We're happy to help. Write to us at support@morphic.com.