← Back to list
🎬

video-translate Checked

Translate and dub existing videos into multiple languages using HeyGen. Use when: (1) Translating…
🎬 Video & Motion skills By calesthio Version v1.0.0 Added 2026-09-07 Updated 2026-09-07 Source ↗ Part of Writing →
8.8Overall rating
2Views
12Downloads
56.5kStars

Installation

🤖 Install via AI

Copy the prompt below and send it to your AI assistant (e.g. Claude Code) — it will follow the instructions and install automatically.

Install the "video-translate" skill by following the instructions at https://skill123.me/install/video-translate.
⌨️ Command line install

Run in your terminal — downloads and installs to ~/.claude/skills/.

curl -fsSL https://skill123.me/install/video-translate.sh | bash
📦 Download ZIP

Download the zip and extract it into your skills directory (e.g. ~/.claude/skills/), then restart your session.

⬇ Download v1.0.0 · 4 KB
📊 Static rating
8.8/10
Trigger
8.0
Structure
8.0
Workflow
8.4
Content
9.0
Engineering
10.0
Security
10.0

Six-dimension rubric with reviewer rationale.

View scorecard ↓
🛡 Dynamic test
—

Not live-tested yet — this skill is rated on static analysis only.

About this skill

Translate and dub existing videos into multiple languages using HeyGen. Use when: (1) Translating a video into another language, (2) Dubbing video content with lip-sync, (3) Creating multi-language versions of existing videos, (4) Audio-only translation without lip-sync, (5) Working with HeyGen's /v2/video_translate endpoint.

Video Translation (HeyGen)

Translate and dub existing videos into multiple languages, preserving lip-sync and natural speech patterns. Provide a video URL or HeyGen video ID — no need to create the video on HeyGen first.

Documentation

Translate and dub existing videos into multiple languages using HeyGen. Use when: (1) Translating a video into another language, (2) Dubbing video content with lip-sync, (3) Creating multi-language versions of existing videos, (4) Audio-only translation without lip-sync, (5) Working with HeyGen's /v2/video_translate endpoint.

Video Translation (HeyGen)

Translate and dub existing videos into multiple languages, preserving lip-sync and natural speech patterns. Provide a video URL or HeyGen video ID — no need to create the video on HeyGen first.

Authentication

All requests require the X-Api-Key header. Set the HEYGEN_API_KEY environment variable.


curl -X POST "https://api.heygen.com/v2/video_translate" \
  -H "X-Api-Key: $HEYGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"video_url": "https://example.com/video.mp4", "output_language": "es-ES"}'

Default Workflow

1. Provide a video URL or HeyGen video ID

2. Call POST /v2/video_translate with the target language

3. Poll GET /v2/video_translate/{translate_id} until status is completed

4. Download the translated video from the returned URL

Creating a Translation Job

### Request Fields

| Field | Type | Req | Description |

|-------|------|:---:|-------------|

| video_url | string | Y* | URL of video to translate (*or video_id) |

| video_id | string | Y* | HeyGen video ID (*or video_url) |

| output_language | string | Y | Target language code (e.g., "es-ES") |

| title | string | | Name for the translated video |

| translate_audio_only | boolean | | Audio only, no lip-sync (faster) |

| speaker_num | number | | Number of speakers in video |

| callback_id | string | | Custom ID for webhook tracking |

| callback_url | string | | URL for completion notification |

**Either** video_url **or** video_id must be provided.

### curl


curl -X POST "https://api.heygen.com/v2/video_translate" \
  -H "X-Api-Key: $HEYGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "video_url": "https://example.com/original-video.mp4",
    "output_language": "es-ES",
    "title": "Spanish Version"
  }'

### TypeScript


interface VideoTranslateRequest {
  video_url?: string;
  video_id?: string;
  output_language: string;
  title?: string;
  translate_audio_only?: boolean;
  speaker_num?: number;
  callback_id?: string;
  callback_url?: string;
}

interface VideoTranslateResponse {
  error: null | string;
  data: {
    video_translate_id: string;
  };
}

async function translateVideo(config: VideoTranslateRequest): Promise<string> {
  const response = await fetch("https://api.heygen.com/v2/video_translate", {
    method: "POST",
    headers: {
      "X-Api-Key": process.env.HEYGEN_API_KEY!,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(config),
  });

  const json: VideoTranslateResponse = await response.json();

  if (json.error) {
    throw new Error(json.error);
  }
View full documentation

return json.data.video_translate_id;

}



### Python

import requests

import os

def translate_video(config: dict) -> str:

response = requests.post(

"https://api.heygen.com/v2/video_translate",

headers={

"X-Api-Key": os.environ["HEYGEN_API_KEY"],

"Content-Type": "application/json"

},

json=config

)

data = response.json()

if data.get("error"):

raise Exception(data["error"])

return data["data"]["video_translate_id"]



## Supported Languages

| Language | Code | Notes |
|----------|------|-------|
| English (US) | en-US | Default source |
| Spanish (Spain) | es-ES | European Spanish |
| Spanish (Mexico) | es-MX | Latin American |
| French | fr-FR | Standard French |
| German | de-DE | Standard German |
| Italian | it-IT | Standard Italian |
| Portuguese (Brazil) | pt-BR | Brazilian Portuguese |
| Japanese | ja-JP | Standard Japanese |
| Korean | ko-KR | Standard Korean |
| Chinese (Mandarin) | zh-CN | Simplified Chinese |
| Hindi | hi-IN | Standard Hindi |
| Arabic | ar-SA | Modern Standard Arabic |

## Translation Options

### Basic Translation (with lip-sync)

const config = {

video_url: "https://example.com/original.mp4",

output_language: "es-ES",

title: "Spanish Translation",

};



### Audio-Only Translation (faster, no lip-sync)

const config = {

video_url: "https://example.com/original.mp4",

output_language: "es-ES",

translate_audio_only: true,

};



### Multi-Speaker Videos

const config = {

video_url: "https://example.com/interview.mp4",

output_language: "fr-FR",

speaker_num: 2,

};



## Advanced Options (v4 API)

For more control over translation:

interface VideoTranslateV4Request {

input_video_id?: string;

google_url?: string;

output_languages: string[]; // Multiple languages in one call

name: string;

srt_key?: string; // Custom SRT subtitles

instruction?: string;

vocabulary?: string[]; // Terms to preserve as-is

brand_voice_id?: string;

speaker_num?: number;

keep_the_same_format?: boolean;

input_language?: string;

enable_video_stretching?: boolean;

disable_music_track?: boolean;

enable_speech_enhancement?: boolean;

srt_role?: "input" | "output";

translate_audio_only?: boolean;

}



### Multiple Output Languages

const config = {

input_video_id: "original_video_id",

output_languages: ["es-ES", "fr-FR", "de-DE"],

name: "Multi-language translations",

};



### Custom Vocabulary (preserve specific terms)

const config = {

video_url: "https://example.com/product-demo.mp4",

output_language: "ja-JP",

vocabulary: ["SuperWidget", "Pro Max", "TechCorp"],

};



### Custom SRT Subtitles

const config = {

video_url: "https://example.com/video.mp4",

output_language: "es-ES",

srt_key: "path/to/custom-subtitles.srt",

srt_role: "input",

};



## Checking Translation Status

### curl

curl -X GET "https://api.heygen.com/v2/video_translate/{translate_id}" \

-H "X-Api-Key: $HEYGEN_API_KEY"



### TypeScript

interface TranslateStatusResponse {

error: null | string;

data: {

id: string;

status: "pending" | "processing" | "completed" | "failed";

video_url?: string;

message?: string;

};

}

async function getTranslateStatus(translateId: string): Promise<TranslateStatusResponse["data"]> {

const response = await fetch(

https://api.heygen.com/v2/video_translate/${translateId},

{ headers: { "X-Api-Key": process.env.HEYGEN_API_KEY! } }

);

const json: TranslateStatusResponse = await response.json();

if (json.error) {

throw new Error(json.error);

}

return json.data;

}



## Polling for Completion

Translations take longer than standard video generation — allow up to 30 minutes.

async function waitForTranslation(

translateId: string,

maxWaitMs = 1800000,

pollIntervalMs = 30000

): Promise<string> {

const startTime = Date.now();

while (Date.now() - startTime < maxWaitMs) {

const status = await getTranslateStatus(translateId);

switch (status.status) {

case "completed":

return status.video_url!;

case "failed":

throw new Error(status.message || "Translation failed");

default:

console.log(Status: ${status.status}...);

await new Promise((r) => setTimeout(r, pollIntervalMs));

}

}

throw new Error("Translation timed out");

}



## Complete Workflow

async function translateAndDownload(

videoUrl: string,

targetLanguage: string

): Promise<string> {

console.log(Starting translation to ${targetLanguage}...);

const translateId = await translateVideo({

video_url: videoUrl,

output_language: targetLanguage,

});

console.log(Translation ID: ${translateId});

console.log("Processing translation...");

const translatedVideoUrl = await waitForTranslation(translateId);

console.log(Translation complete: ${translatedVideoUrl});

return translatedVideoUrl;

}

const spanishVideo = await translateAndDownload(

"https://example.com/my-video.mp4",

"es-ES"

);



## Batch Translation

Translate to multiple languages in parallel:

async function tran

Score breakdown

Trigger
8.0
Five numbered use cases with endpoint keyword; no explicit exclusions or phrasing variants.
Structure
8.0
Single 411-line file under limit but dense; language and option tables could be references.
Workflow
8.4
Complete workflow, polling loop with failed/timeout branches, batch isolation and error-message mapping.
Content
9.0
Parallel curl/TS/Python examples with concrete language codes and configs.
Engineering
10.0
Valid frontmatter with env and allowed-tools; no path references to verify.
Security
10.0
Only api.heygen.com URLs, env-var key, no injection, secrets or scripts.
Solid HeyGen video-translation wrapper: language table, v2 plus v4 options, polling with timeout, batch parallel translation with per-language error isolation; single 411-line file with no offload and no When-Not.