Skip to main content

POST /api/translate

Translates a video clip’s audio to a different language using ElevenLabs’ AI dubbing technology. The system:
  1. Extracts the original audio track
  2. Uploads to ElevenLabs Dubbing API
  3. Waits for AI-generated dubbed audio (preserves speaker voice characteristics)
  4. Replaces the original audio with the dubbed version
This endpoint is synchronous and may take 2-5 minutes depending on video length and ElevenLabs queue.

Authentication

X-ElevenLabs-Key
string
required
Your ElevenLabs API key for dubbing services

Request Body

job_id
string
required
The job ID from /api/process
clip_index
integer
required
Zero-based index of the clip to translate
target_language
string
required
Target language code (e.g., es for Spanish, fr for French). See language list
source_language
string
Source language code (auto-detected if omitted)
input_filename
string
Specific video filename to translate (for effect chaining)
{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "clip_index": 0,
  "target_language": "es",
  "source_language": "en"  // Optional
}

Response

success
boolean
required
Always true on successful translation
new_video_url
string
required
Relative URL to the translated video file
{
  "success": true,
  "new_video_url": "/videos/550e8400-e29b-41d4-a716-446655440000/translated_es_video_123_clip_1.mp4"
}

GET /api/translate/languages

Returns the list of supported languages for translation.

Response

languages
array
required
Array of language objects with code, name, and native name
{
  "languages": [
    {"code": "en", "name": "English", "native_name": "English"},
    {"code": "es", "name": "Spanish", "native_name": "Español"},
    {"code": "fr", "name": "French", "native_name": "Français"},
    {"code": "de", "name": "German", "native_name": "Deutsch"},
    {"code": "it", "name": "Italian", "native_name": "Italiano"},
    {"code": "pt", "name": "Portuguese", "native_name": "Português"},
    {"code": "pl", "name": "Polish", "native_name": "Polski"},
    {"code": "tr", "name": "Turkish", "native_name": "Türkçe"},
    {"code": "ru", "name": "Russian", "native_name": "Русский"},
    {"code": "nl", "name": "Dutch", "native_name": "Nederlands"},
    {"code": "cs", "name": "Czech", "native_name": "Čeština"},
    {"code": "ar", "name": "Arabic", "native_name": "العربية"},
    {"code": "zh-cn", "name": "Chinese (Simplified)", "native_name": "简体中文"},
    {"code": "ja", "name": "Japanese", "native_name": "日本語"},
    {"code": "ko", "name": "Korean", "native_name": "한국어"},
    {"code": "hi", "name": "Hindi", "native_name": "हिन्दी"}
  ]
}

Supported Languages

ElevenLabs supports 30+ languages including:
CodeLanguageNative
enEnglishEnglish
esSpanishEspañol
frFrenchFrançais
deGermanDeutsch
itItalianItaliano
ptPortuguesePortuguês
plPolishPolski
trTurkishTürkçe
ruRussianРусский
nlDutchNederlands
csCzechČeština
arArabicالعربية
zh-cnChinese (Simplified)简体中文
jaJapanese日本語
koKorean한국어
hiHindiहिन्दी
idIndonesianBahasa Indonesia
msMalayBahasa Melayu
taTamilதமிழ்
fiFinnishSuomi
svSwedishSvenska
ukUkrainianУкраїнська
Call /api/translate/languages for the most up-to-date list with all supported languages.

Error Codes

CodeDescription
400Missing X-ElevenLabs-Key header
404Job ID not found
404Metadata file not found
404Clip index out of range
404Video file not found at specified path
500ElevenLabs API error (quota exceeded, invalid language, etc.)

Examples

Translate to Spanish

curl -X POST http://localhost:8000/api/translate \
  -H "X-ElevenLabs-Key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "job_id": "550e8400-e29b-41d4-a716-446655440000",
    "clip_index": 0,
    "target_language": "es"
  }'
Response:
{
  "success": true,
  "new_video_url": "/videos/550e8400-e29b-41d4-a716-446655440000/translated_es_video_123_clip_1.mp4"
}

Get Supported Languages

curl http://localhost:8000/api/translate/languages

Python SDK Example

import requests

# Translate to Spanish
url = "http://localhost:8000/api/translate"
headers = {"X-ElevenLabs-Key": "YOUR_KEY"}
payload = {
    "job_id": "550e8400-e29b-41d4-a716-446655440000",
    "clip_index": 0,
    "target_language": "es",
    "source_language": "en"  # Optional
}

response = requests.post(url, headers=headers, json=payload)
result = response.json()

if result["success"]:
    print(f"Translated video: {result['new_video_url']}")

# Get language list
lang_response = requests.get("http://localhost:8000/api/translate/languages")
languages = lang_response.json()["languages"]
print(f"Supported languages: {len(languages)}")

JavaScript/Fetch Example

// Translate video
const translateVideo = async (jobId, clipIndex, targetLanguage) => {
  const response = await fetch('http://localhost:8000/api/translate', {
    method: 'POST',
    headers: {
      'X-ElevenLabs-Key': 'YOUR_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      job_id: jobId,
      clip_index: clipIndex,
      target_language: targetLanguage
    })
  });
  
  return await response.json();
};

// Get languages
const getLanguages = async () => {
  const response = await fetch('http://localhost:8000/api/translate/languages');
  const data = await response.json();
  return data.languages;
};

// Usage
const languages = await getLanguages();
console.log('Available languages:', languages);

const result = await translateVideo(
  '550e8400-e29b-41d4-a716-446655440000',
  0,
  'es'
);
console.log('Translated video:', result.new_video_url);

Translate and Add Subtitles

import requests

job_id = "550e8400-e29b-41d4-a716-446655440000"
headers_elevenlabs = {"X-ElevenLabs-Key": "YOUR_KEY"}

# 1. Translate to Spanish
translate_resp = requests.post(
    "http://localhost:8000/api/translate",
    headers=headers_elevenlabs,
    json={
        "job_id": job_id,
        "clip_index": 0,
        "target_language": "es"
    }
)
translated_file = translate_resp.json()["new_video_url"].split("/")[-1]
print(f"Translated to Spanish: {translated_file}")

# 2. Add Spanish subtitles (auto-detects dubbed video and re-transcribes)
subtitle_resp = requests.post(
    "http://localhost:8000/api/subtitle",
    json={
        "job_id": job_id,
        "clip_index": 0,
        "input_filename": translated_file,
        "position": "bottom",
        "font_size": 16
    }
)
final_file = subtitle_resp.json()["new_video_url"]
print(f"Spanish video with Spanish subtitles: {final_file}")

How It Works

  1. Audio Extraction: FFmpeg extracts audio from the video
  2. Upload: Audio file sent to ElevenLabs Dubbing API
  3. AI Processing: ElevenLabs analyzes speech, generates dubbed audio in target language
  4. Polling: API polls ElevenLabs every 10 seconds for completion
  5. Download: Dubbed audio track downloaded
  6. Merge: FFmpeg replaces original audio with dubbed audio
  7. Output: New video file saved with translated_{language}_ prefix

Voice Preservation

ElevenLabs’ AI dubbing preserves:
  • Speaker characteristics: Tone, pitch, and vocal style
  • Emotion: Excitement, sarcasm, emphasis
  • Timing: Lip-sync alignment where possible
  • Background audio: Music and sound effects preserved

Performance Notes

  • Processing Time: 2-5 minutes for typical 30-60 second clips
  • ElevenLabs Queue: May vary based on API load
  • Blocking: This endpoint is synchronous (waits for dubbing to complete)
  • Costs: ElevenLabs charges per character/second of dubbed audio
Translated videos replace the original in the job result’s video_url field and metadata.json. The original video is preserved on disk.

Next Steps

Build docs developers (and LLMs) love