All skills
elevenlabs avatar

/dubbing

@62eb4fc official
by elevenlabselevenlabs/skills462 stars
74

Dub 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.

Use this Skill: https://skilld.dev/gh/elevenlabs/skills/dubbing

This session only. Nothing lands on disk.

referencesapi-reference.md

≈3.4k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Dubbing Projects API Reference

Full endpoint-by-endpoint reference for the Dubbing Projects API.

  • Base URL: https://api.elevenlabs.io
  • Authentication: xi-api-key header on every request (the SDKs read ELEVENLABS_API_KEY)
  • SDK: elevenlabs.dubbing.project.* in Python and JavaScript (camelCase methods in JS). The older client.dubbing.* methods are the legacy v1 API — do not use them
  • Model: dubbing_v2 (default)
  • Source size limit: up to 3 GiB per source (upload or URL)
  • Enterprise: transcript editing and regeneration endpoints are available to enterprise workspaces only

Contents

Endpoint quick reference

Method Path Python SDK method Purpose
POST /v1/dubbing/project dubbing.project.create Create a project (file or URL)
GET /v1/dubbing/project dubbing.project.list List projects (paginated)
GET /v1/dubbing/project/{project_id} dubbing.project.get Get a project
DELETE /v1/dubbing/project/{project_id} dubbing.project.delete Delete a project and its languages
GET /v1/dubbing/project/{project_id}/transcript dubbing.project.transcript.get Get the source transcript
PATCH /v1/dubbing/project/{project_id}/transcript/segment/{segment_id} dubbing.project.transcript.update_segment Edit a source segment
POST /v1/dubbing/project/{project_id}/transcript/segment dubbing.project.transcript.create_segment Add a source segment
DELETE /v1/dubbing/project/{project_id}/transcript/segment/{segment_id} dubbing.project.transcript.delete_segment Delete a source segment
POST /v1/dubbing/project/{project_id}/language dubbing.project.language.create Add a language target
GET /v1/dubbing/project/{project_id}/language dubbing.project.language.list List language targets (paginated)
GET /v1/dubbing/project/{project_id}/language/{language_id} dubbing.project.language.get Get a language target
DELETE /v1/dubbing/project/{project_id}/language/{language_id} dubbing.project.language.delete Delete a language target
GET /v1/dubbing/project/{project_id}/language/{language_id}/transcript dubbing.project.language.transcript.get Get a language's transcript (translations)
PATCH /v1/dubbing/project/{project_id}/language/{language_id}/transcript/segment/{segment_id} dubbing.project.language.transcript.update_segment Edit a translation
POST /v1/dubbing/project/{project_id}/language/{language_id}/transcript/regenerate dubbing.project.language.transcript.regenerate Regenerate a language from its edited transcript

JS methods are the same paths in camelCase (e.g. dubbing.project.transcript.updateSegment).

Projects

Create a project

POST /v1/dubbing/project — multipart/form-data with either file or source_url (not both).

Field Required Notes
file one of file/source_url The source media to dub (audio or video)
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
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 (e.g. product or brand names), up to 1000 terms; each at most 50 characters and 5 words; <>{}[]\ not allowed. In multipart, repeat the field once per term

Auto-detected source language: if source_language is omitted, the project's source_language stays null; the detected language is reported as the language field on the source transcript.

Response (201 Created) — the project starts in queued; media is null until preparation finishes:

{
  "project_id": "proj_1601kwkyxp0hfzvtmyxwqxx6mcy3",
  "status": "queued",
  "reference": "Q3 marketing video",
  "source_language": "en",
  "model_id": "dubbing_v2",
  "media": null,
  "language_ids": [],
  "revision": 0,
  "created_at": "2026-07-03T10:15:30Z",
  "updated_at": "2026-07-03T10:15:30Z"
}

The source is fetched (for a URL) and transcribed asynchronously — poll the project until it reaches ready.

Get a project

GET /v1/dubbing/project/{project_id}

Once ready, media is populated:

{
  "project_id": "proj_1601kwkyxp0hfzvtmyxwqxx6mcy3",
  "status": "ready",
  "reference": "Q3 marketing video",
  "source_language": "en",
  "model_id": "dubbing_v2",
  "media": {
    "filename": "promo.mp4",
    "duration_s": 42.5,
    "has_video": true,
    "mime_type": "video/mp4"
  },
  "language_ids": [],
  "revision": 0,
  "created_at": "2026-07-03T10:15:30Z",
  "updated_at": "2026-07-03T10:17:12Z"
}

language_ids stays empty until languages are added; revision stays 0 until the source transcript is edited (transcription itself doesn't bump it).

Project states:

Status Meaning
queued Created; the source is being fetched and preparation is enqueued, but no worker has started it yet
preparing Preparation tasks are running
ready Preparation finished. The source transcript is available and languages can be added/generated. A project stays at ready — per-language progress lives on the languages
failed Preparation failed (e.g. the source couldn't be fetched or decoded)

List projects

GET /v1/dubbing/project — cursor-paginated.

Query params: page_size (default 20, max 100), cursor, status (queued/preparing/ready/failed), sort_direction (DESCENDING default).

{ "projects": [ /* ProjectResponse... */ ], "next_cursor": null }

Pass next_cursor back as cursor to fetch the next page; null means the end.

Delete a project

DELETE /v1/dubbing/project/{project_id} — deletes the project and its languages.

Source transcript

Transcript editing (and regeneration) is available to enterprise workspaces only. Every source edit bumps the project's revision; each edit response returns the new value. Editing the source after a language exists marks that language's output stale and requires a regeneration — finalize the source before adding languages.

Get the source transcript

GET /v1/dubbing/project/{project_id}/transcript

{
  "language": "en",
  "segments": [
    {
      "id": "0199a3f0-1c2d-7abc-8def-0123456789ab",
      "text": "Welcome to our product demo.",
      "speaker_id": "default_speaker",
      "start_s": 0.0,
      "end_s": 2.5
    }
  ],
  "revision": 0
}

Each segment has a stable id used to edit or delete it.

Edit a segment

PATCH /v1/dubbing/project/{project_id}/transcript/segment/{segment_id}

Send only the fields to change (text, speaker_id, start_s, end_s); at least one is required. If sending both start_s and end_s, end_s must be greater than start_s.

{
  "segment": {
    "id": "0199a3f0-1c2d-7abc-8def-0123456789ab",
    "text": "Welcome to our latest product demo.",
    "speaker_id": "default_speaker",
    "start_s": 0.0,
    "end_s": 2.5
  },
  "revision": 1
}

Add a segment

POST /v1/dubbing/project/{project_id}/transcript/segment

All fields required (text, speaker_id, start_s, end_s). The server assigns the segment id. Use a speaker_id that already appears in the source transcript so the new line is dubbed with that speaker's voice.

The response echoes the new segment with its server-assigned id plus the new project revision.

Delete a segment

DELETE /v1/dubbing/project/{project_id}/transcript/segment/{segment_id}

{ "revision": 3 }

Languages

Add a language

POST /v1/dubbing/project/{project_id}/language

JSON body:

Field Required Notes
target_language yes ISO 639 code (e.g. es)
model_id no Defaults to the project's model
voice_settings no e.g. {"cloning_strength": 7} — cloning_strength accepts values between 0 and 10 inclusive (default 7); controls how strongly dubbed speakers clone the source voices

Response (201 Created) — starts queued:

{
  "language_id": "lang_1001kwkyxp0je6ktn4knsfrasx5s",
  "project_id": "proj_1601kwkyxp0hfzvtmyxwqxx6mcy3",
  "target_language": "es",
  "status": "queued",
  "model_id": "dubbing_v2",
  "outputs": null,
  "revision": 0,
  "output_revision": null,
  "created_at": "2026-07-03T10:16:00Z",
  "updated_at": "2026-07-03T10:16:00Z"
}

A language can be added to a project that isn't ready yet — it stays queued and starts automatically once the project becomes ready. You can also queue the first language when creating the project by passing target_language to project.create.

Language states:

Status Meaning
queued Created and waiting — either on the project becoming ready, or on a worker to pick up its generation
processing The dub is being generated
completed The dub finished; outputs is populated
stale Previously completed, but its transcript (source or translation) changed, so the current output no longer matches. It keeps its last output until regenerated
failed Generation failed

Get a language

GET /v1/dubbing/project/{project_id}/language/{language_id}

Once completed, outputs carries a signed, time-limited download URL (valid ~1 hour; re-fetch the language for a fresh URL):

{
  "language_id": "lang_1001kwkyxp0je6ktn4knsfrasx5s",
  "project_id": "proj_1601kwkyxp0hfzvtmyxwqxx6mcy3",
  "target_language": "es",
  "status": "completed",
  "model_id": "dubbing_v2",
  "outputs": {
    "lossless_audio": "https://storage.googleapis.com/eleven-dubbing/.../output.wav?X-Goog-Signature=..."
  },
  "revision": 0,
  "output_revision": 0,
  "created_at": "2026-07-03T10:16:00Z",
  "updated_at": "2026-07-03T10:20:45Z"
}

When output_revision equals revision, the downloadable output reflects the current transcript. When it's behind (and status is stale), the output is out of date and needs a regeneration.

List languages

GET /v1/dubbing/project/{project_id}/language — cursor-paginated, optional status filter.

Delete a language

DELETE /v1/dubbing/project/{project_id}/language/{language_id} → 204 No Content.

Language transcript (translations)

Get a language's transcript

GET /v1/dubbing/project/{project_id}/language/{language_id}/transcript

Pairs each source segment with its translation (null = not yet translated). Segment ids match the source transcript, so translations line up against the source.

{
  "source_language": "en",
  "target_language": "es",
  "segments": [
    {
      "id": "0199a3f0-1c2d-7abc-8def-0123456789ab",
      "speaker_id": "default_speaker",
      "start_s": 0.0,
      "end_s": 2.5,
      "source_text": "Welcome to our latest product demo.",
      "translation": "Bienvenido a la demostración de nuestro producto."
    }
  ],
  "revision": 0
}

Edit a translation

PATCH /v1/dubbing/project/{project_id}/language/{language_id}/transcript/segment/{segment_id}

Body: {"translation": "..."}. Pass null to clear it and mark the segment for re-translation.

A translation edit affects only this language — the source transcript and other languages are untouched. It bumps this language's revision, and a completed language becomes stale: its downloadable output still reflects the previous output_revision until regenerated.

Regeneration

POST /v1/dubbing/project/{project_id}/language/{language_id}/transcript/regenerate

Produces a fresh dub from the current transcript after editing a language's translation (or after source edits marked it stale). Charged like a generation.

Response (202 Accepted) — the language goes back to queued; output_revision still points at the previous output until the new one finishes:

{
  "language_id": "lang_1001kwkyxp0je6ktn4knsfrasx5s",
  "project_id": "proj_1601kwkyxp0hfzvtmyxwqxx6mcy3",
  "target_language": "es",
  "status": "queued",
  "model_id": "dubbing_v2",
  "outputs": null,
  "revision": 1,
  "output_revision": 0,
  "created_at": "2026-07-03T10:16:00Z",
  "updated_at": "2026-07-03T10:25:10Z"
}

Poll the language until completed, then download the refreshed outputs.lossless_audio. At that point output_revision equals revision.

Returns 409 Conflict if the project isn't ready or the language isn't in a settled state (e.g. it's already generating).

Revisions

Every project and language carries its own monotonic revision counter, each starting at 0 and independent of the others:

  • The project's revision increases on each source-transcript edit (transcription itself doesn't bump it).
  • A language's revision starts at 0 when the language is created — it does not inherit the project's current revision — and increases when its translation is edited or when a source edit affects it.
  • A language's output_revision is the revision its current audio was generated from. When output_revision is behind revision, the output is out of date and needs a regeneration.

Source: SKILL.md on GitHub

1 warning1mo3 checks · Risk SAFE
  • Gen Agent Trust Hub1mo

    The skill provides instructions and examples for using the ElevenLabs Dubbing API to translate audio and video. It follows security best practices for secret management and uses official, well-known software distributions.

  • Socket1mo

    No alerts

  • Snyk1mo

    Risk: MEDIUM · 1 issue

Signed by skilld at 62eb4fc. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated last month
compatibility
Requires internet access and an ElevenLabs API key (ELEVENLABS_API_KEY).
Other metadata
metadata
{
  "openclaw": {
    "requires": {
      "env": [
        "ELEVENLABS_API_KEY"
      ]
    },
    "primaryEnv": "ELEVENLABS_API_KEY"
  }
}

README badge

README badge for elevenlabs/skills/dubbing