Credited skills
11 skills · 35 min
Skills
Skill 2 of 11
Dub audio and video into other languages using the ElevenLabs Dubbing API (dubbing_v2), preserving the original speakers’ voices.
4 minutes · 812 words · 13 sections
Install
npx skills add elevenlabs/skills --skill dubbingnpx skills add elevenlabs/skillsThe first command installs just this skill, by the name in its SKILL.md; the second installs the whole repository.
Dub audio or video into other languages while preserving the original speakers’ voices. Create a project from a file or URL, review and edit the source transcript, add one or more target languages, refine translations per segment, and regenerate outputs.
Important: Use the Dubbing Projects API —
elevenlabs.dubbing.project.*in the SDKs, or the/v1/dubbing/projectREST endpoints. Do not use the legacy v1 dubbing surface (client.dubbing.create(),client.dubbing.get(),client.dubbing.audio.get(), or bare/v1/dubbingroutes) — that is the older dubbing API, now under Legacy in the API reference.
Setup: See Installation Guide (opens in a new tab). The
elevenlabsCLI and the SDKs readELEVENLABS_API_KEYautomatically; REST base URL ishttps://api.elevenlabs.iowith your API key in thexi-api-keyheader.
| Concept | Meaning |
|---|---|
| Project | One source of media (file or URL) plus its source transcript. Prepared (transcribed) once, then rests in ready while you add languages. |
| Source transcript | Editable segments (text, speaker, timing) transcribed from the source. The single source of truth every language is translated from. |
| Language (target) | One dubbed output language. Each has its own transcript (source segments + a translation per segment) and its own dubbed audio output. |
| Revisions | Independent monotonic counters. The project’s revision bumps on source-transcript edits; a language’s revision bumps on translation edits or source edits that affect it. A language’s output_revision is the revision its current audio was generated from — when it’s behind revision, the output is out of date. |
Recommended order of operations: finalize the source transcript before adding any languages. Translations are produced from the source, so correcting the source first means every language starts from the right text — editing the source after a language completes marks it stale and requires a (charged) regeneration.
Enterprise: Transcript editing and regeneration are available to enterprise workspaces only. Creating projects, adding languages, and downloading dubs work on all plans.
queuedreadyqueued → processing → completedoutputs.lossless_audio when completedstalecompleted again with fresh outputimport os
import time
import requests
from elevenlabs.client import ElevenLabs
elevenlabs = ElevenLabs(api_key=os.getenv("ELEVENLABS_API_KEY"))
# 1. Create a project from a local file (or pass source_url=... instead of file)
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
import { writeFile } from "fs/promises";
const elevenlabs = new ElevenLabsClient();
// 1. Create a project (sourceUrl shown; file upload is also supported)
let
The elevenlabs CLI reads ELEVENLABS_API_KEY from the environment automatically.
# 1. Create a project (use --source-url "https://..." instead of --file to dub from a URL)
elevenlabs dubbing project create --file promo.mp4 --source-language en
# → {"project_id": "proj_...", "status": "queued", ...}
# 2. Poll until status is "ready"
elevenlabs dubbing project get --project-id proj_...
# 3. Add a target language
elevenlabs dubbing project language create --project-id proj_... --target-language
elevenlabs dubbing project create (REST: POST /v1/dubbing/project, multipart/form-data) takes either file or source_url (not both):
| Field | Required | Notes |
|---|---|---|
file | one of file/source_url | Source media to dub (audio or video), up to 3 GiB |
source_url | one of file/source_url | Public URL to fetch the source media from |
source_language | no | ISO 639 code (e.g. en). Omit to auto-detect — the detected language is reported on the source transcript’s language field |
reference | no | Free-form label to identify the project on your end (max 500 chars) |
model_id | no | dubbing_v2 (default) |
target_language | no | Optionally queue the first language target at creation; add more with language.create |
keyterms | no | Terms to bias transcription/translation toward (product/brand names). Up to 1000 terms; each at most 50 chars and 5 words; <>{}[]\ not allowed. Repeat the field once per term in multipart |
Once the project is ready, read the transcript, then correct it before adding languages. Every edit bumps the project’s revision. Each segment has a stable id used to edit or delete it. (Enterprise workspaces only.)
# Read the source transcript
transcript = elevenlabs.dubbing.project.transcript.get(project_id)
# Correct a segment's text — send only the fields to change (text, speaker_id, start_s, end_s)
elevenlabs.dubbing.project.transcript.update_segment(
project_id,
segment_id=transcript.segments[0].id,
text="Welcome to our latest product demo.",
)
# Add a segment (reuse an existing speaker_id so it's dubbed with that speaker's voice)
added = elevenlabs.dubbing.project.transcript.create_segment(
Via the CLI: elevenlabs dubbing project transcript get --project-id proj_..., then update a segment with only the changed fields (--text, --speaker-id, --start-s, --end-s):
elevenlabs dubbing project transcript update_segment \
--project-id proj_... --segment-id seg_... \
--text "Welcome to our latest product demo."A language’s transcript pairs each source segment with its translation (null = not yet translated; segment ids match the source). Edit a single translation, then regenerate. (Enterprise workspaces only.)
# Read the language's translations
target = elevenlabs.dubbing.project.language.transcript.get(project_id, language_id)
# Refine a single translation (pass translation=None to clear it and mark for re-translation)
elevenlabs.dubbing.project.language.transcript.update_segment(
project_id,
language_id,
segment_id=target.segments[0].id,
translation="Bienvenido a nuestra última demostración de producto.",
)
# Regenerate the dub from the current transcript (charged like a generation)
elevenlabs.dubbing.project.language.transcript.regenerate(project_id, language_id)Via the CLI: elevenlabs dubbing project language transcript update_segment --project-id proj_... --language-id lang_... --segment-id seg_... --translation "...", then elevenlabs dubbing project language transcript regenerate --project-id proj_... --language-id lang_... (returns 202 Accepted).
A translation edit affects only that language. After the edit, a completed language becomes stale — it keeps serving its previous output until you regenerate. Poll until completed; output_revision then equals revision and outputs.lossless_audio reflects the current transcript.
Add one language target per language — each generates independently. Track them all with language.list instead of polling one by one:
for lang in ["es", "fr", "de", "ja"]:
elevenlabs.dubbing.project.language.create(project_id, target_language=lang)
while True:
result = elevenlabs.dubbing.project.language.list(project_id)
if not any(l.status in ("queued", "processing") for l
Project:
| Status | Meaning |
|---|---|
queued | Created; source fetch + preparation enqueued |
preparing | Preparation (transcription) running |
ready | Source transcript available; add/generate languages. Projects stay ready — per-language progress lives on the languages |
failed | Preparation failed (e.g. source couldn’t be fetched or decoded) |
Language:
| Status | Meaning |
|---|---|
queued | Waiting on the project becoming ready, or on a generation worker |
processing | The dub is being generated |
completed | Finished; outputs populated with a signed download URL (valid ~1 hour — re-fetch for a fresh one) |
stale | Previously completed, but the transcript changed; keeps the last output until regenerated |
failed | Generation failed |
You can add a language before the project is ready — it stays queued and starts automatically once the project becomes ready. Adding a language accepts optional model_id (defaults to the project’s) and voice_settings (e.g. {"cloning_strength": 7}, range 0–10, default 7 — controls how strongly dubbed speakers clone the source voices).
ready or the language isn’t settled (e.g. already generating) — wait and retryoutputs.lossless_audio is signed and valid ~1 hour; re-fetch the language for a fresh URLDub audio and video into other languages using the ElevenLabs Dubbing API (dubbing_v2), preserving the original speakers' voices. Use when translating videos, podcasts, or recordings into other languages, localizing media content, reviewing or correcting dubbing transcripts and translations, or regenerating a dub after edits.
The verbatim description from this skill’s front matter — the string an agent matches on to decide whether to load it.
dubbing/SKILL.mdmain, last pushed 16 September 2026.SKILL.md, not by matching a directory convention. 2 distinct layouts observed: .agents/skills/*/SKILL.md, */SKILL.md.h1 and no skipped levels:/elevenlabs/skills.md, and each skill at its own .md URL.2 files · 16 KB
Everything this skill ships beside its prose. All of it is set here, as subchapters of skill 2.
Documentation the agent loads on demand, rather than up front.