> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mavera.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Multilingual Content Localization

## Scenario

Take Mavera-generated scripts and use ElevenLabs' dubbing API to create localized versions in multiple languages, supporting global marketing campaigns without manual translation.

**Flow:** Mavera `POST /generations` (English script) → ElevenLabs TTS → `POST /v1/dubbing` → Poll → Download per language

## Code

<CodeGroup>
  ```python Python theme={"dark"}
  import os, requests, time

  EL_KEY = os.environ["ELEVENLABS_API_KEY"]
  EL_BASE = "https://api.elevenlabs.io/v1"
  MV = os.environ["MAVERA_API_KEY"]
  MV_BASE = "https://app.mavera.io/api/v1"
  MV_H = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}
  os.makedirs("localized_audio", exist_ok=True)

  LANGS = ["es", "fr", "de", "ja", "pt"]

  # 1. Generate English script → source audio
  gen = requests.post(f"{MV_BASE}/generations", headers=MV_H, json={
      "prompt": "Write a 45-second marketing video script for a SaaS analytics platform. "
          "Energetic, professional tone. Hook, three key benefits, CTA.",
  }).json()
  script = gen.get("output") or gen.get("content") or ""
  print(f"English script: {len(script.split())} words")

  tts = requests.post(f"{EL_BASE}/text-to-speech/21m00Tcm4TlvDq8ikWAM",
      headers={"xi-api-key": EL_KEY, "Content-Type": "application/json"},
      json={"text": script, "model_id": "eleven_multilingual_v2",
            "voice_settings": {"stability": 0.5, "similarity_boost": 0.75}})
  with open("localized_audio/source_en.mp3", "wb") as f: f.write(tts.content)
  print(f"Source audio: {len(tts.content) // 1024} KB")
  time.sleep(2)

  # 2. Dub into each target language
  for lang in LANGS:
      with open("localized_audio/source_en.mp3", "rb") as af:
          dub = requests.post(f"{EL_BASE}/dubbing", headers={"xi-api-key": EL_KEY},
              data={"target_lang": lang, "source_lang": "en", "num_speakers": "1", "watermark": "false"},
              files={"file": ("source.mp3", af, "audio/mpeg")}).json()
      dubbing_id = dub["dubbing_id"]
      print(f"\n[{lang}] Dubbing ID: {dubbing_id}")

      # 3. Poll for completion
      for attempt in range(60):
          time.sleep(5)
          st = requests.get(f"{EL_BASE}/dubbing/{dubbing_id}", headers={"xi-api-key": EL_KEY}).json()
          if st.get("status") == "dubbed":
              dl = requests.get(f"{EL_BASE}/dubbing/{dubbing_id}/audio/{lang}", headers={"xi-api-key": EL_KEY})
              path = f"localized_audio/script_{lang}.mp3"
              with open(path, "wb") as f: f.write(dl.content)
              print(f"  Saved: {path} ({len(dl.content) // 1024} KB, {(attempt+1)*5}s)")
              break
          elif st.get("status") == "failed":
              print(f"  Failed: {st.get('error')}"); break
      time.sleep(3)
  ```

  ```javascript JavaScript theme={"dark"}
  import fs from "fs";
  const EL_KEY = process.env.ELEVENLABS_API_KEY;
  const EL_BASE = "https://api.elevenlabs.io/v1";
  const MV = process.env.MAVERA_API_KEY;
  const MV_BASE = "https://app.mavera.io/api/v1";
  const MV_H = { Authorization: `Bearer ${MV}`, "Content-Type": "application/json" };
  fs.mkdirSync("localized_audio", { recursive: true });
  const LANGS = ["es", "fr", "de", "ja", "pt"];

  const gen = await fetch(`${MV_BASE}/generations`, { method: "POST", headers: MV_H,
    body: JSON.stringify({ prompt: "Write a 45-second marketing video script. Energetic. Hook, 3 benefits, CTA." }),
  }).then(r => r.json());

  const tts = await fetch(`${EL_BASE}/text-to-speech/21m00Tcm4TlvDq8ikWAM`, { method: "POST",
    headers: { "xi-api-key": EL_KEY, "Content-Type": "application/json" },
    body: JSON.stringify({ text: gen.output || gen.content || "", model_id: "eleven_multilingual_v2",
      voice_settings: { stability: 0.5, similarity_boost: 0.75 } }),
  });
  fs.writeFileSync("localized_audio/source_en.mp3", Buffer.from(await tts.arrayBuffer()));
  await new Promise(r => setTimeout(r, 2000));

  for (const lang of LANGS) {
    const form = new FormData();
    form.append("file", new Blob([fs.readFileSync("localized_audio/source_en.mp3")]), "source.mp3");
    form.append("target_lang", lang); form.append("source_lang", "en");
    form.append("num_speakers", "1"); form.append("watermark", "false");
    const dub = await fetch(`${EL_BASE}/dubbing`, {
      method: "POST", headers: { "xi-api-key": EL_KEY }, body: form,
    }).then(r => r.json());

    for (let i = 0; i < 60; i++) {
      await new Promise(r => setTimeout(r, 5000));
      const st = await fetch(`${EL_BASE}/dubbing/${dub.dubbing_id}`,
        { headers: { "xi-api-key": EL_KEY } }).then(r => r.json());
      if (st.status === "dubbed") {
        const audio = await fetch(`${EL_BASE}/dubbing/${dub.dubbing_id}/audio/${lang}`,
          { headers: { "xi-api-key": EL_KEY } });
        fs.writeFileSync(`localized_audio/script_${lang}.mp3`, Buffer.from(await audio.arrayBuffer()));
        console.log(`[${lang}] → script_${lang}.mp3`); break;
      }
      if (st.status === "failed") { console.log(`[${lang}] Failed`); break; }
    }
    await new Promise(r => setTimeout(r, 3000));
  }
  ```
</CodeGroup>

## Example Output

```text theme={"dark"}
English script: 118 words → source audio: 164 KB
[es] dub_9a2f7c3d → script_es.mp3 (172 KB, 35s)
[fr] dub_4b8e1f6a → script_fr.mp3 (178 KB, 40s)
[de] dub_7d3a9c2e → script_de.mp3 (169 KB, 30s)
[ja] dub_2e6b4d8f → script_ja.mp3 (151 KB, 55s)
[pt] dub_5c1a3e7d → script_pt.mp3 (175 KB, 45s)
```

## Error Handling

<AccordionGroup>
  <Accordion title="Dubbing language support">ElevenLabs supports 29+ languages. Check [supported languages](https://elevenlabs.io/docs/capabilities/dubbing) before submitting. Unsupported codes return 400. Common: `es`, `fr`, `de`, `ja`, `pt`, `zh`, `ko`.</Accordion>
  <Accordion title="Dubbing timeout">Processing scales with audio length — 45 seconds typically completes in 30–60s. Content over 5 minutes can take several minutes. If polling times out, check status manually.</Accordion>
  <Accordion title="Source audio quality">Dubbing works best with clean, single-speaker audio at 44.1kHz+. Background music or multiple speakers degrade output. Pre-process noisy audio before submitting.</Accordion>
</AccordionGroup>
