Skip to content
DashboardGet API Key

Translate a remote video

client.videoTranslate.generate(VideoTranslateGenerateParams { inputs, target_languages, config, 7 more } body, RequestOptionsoptions?): VideoTranslateGenerateResponse { request_id, status }
POST/v1/video-translate/generate

Validates a remote video and starts an asynchronous translation request.

Optional config.source_srt / config.target_srts supply subtitles and config.speaker_voices assigns voices to speakers (see VideoTranslateConfig). When webhook_url is supplied, the service sends one JSON POST after the request reaches completed or failed. The event type is video_translate.completed or video_translate.failed; the request body uses {id, type, created_at, data} and data mirrors the public request response without webhook_url. Successful events include freshly signed video, audio and SRT URLs. Receivers should deduplicate on X-Chamelaion-Delivery. Transport failures, HTTP 429 and HTTP 5xx are retried up to three times with the same delivery ID; redirects and other non-2xx responses are not accepted. Validation happens in two phases:

  1. Synchronous (HTTP 400, no request is created): request shape, config types, SRT size, UTF-8 encoding and syntax (optional BOM stripped, CRLF/CR normalized to LF), cue limit, language consistency, target_srts keys must be listed in target_languages, speaker ID syntax, and voice availability (every speaker_voices value must be a voice_id returned by GET /v1/video-translate/voices).
  2. After the video is processed, before translation starts: SRT timing against the video duration (+1.2 s tolerance), source/target cue count and speaker compatibility, the detected source language against source_srt.language, and speaker_voices keys against the speakers in the source subtitles (or, without any SRT, the speakers already stored for the media). Failures mark the request failed with a descriptive error_message; no translation is started.

Limits: JSON body 8 MiB; each SRT 1 MiB; all SRTs 5 MiB; 5000 cues per SRT; 32 speaker_voices entries; config keys other than source_srt, target_srts and speaker_voices 64 KiB in total; normalized config 6 MiB (measured without HTML escaping). Duplicate JSON keys anywhere in the body and NUL characters in config are rejected.

ParametersExpand Collapse
body: VideoTranslateGenerateParams { inputs, target_languages, config, 7 more }
inputs: Array<Input>
type: "video"
url: string
formaturi
target_languages: Array<string>
config?: Config

Request config. tts_model, source_srt, target_srts and speaker_voices are validated and consumed by the translation; every other key is stored as sent (at most 64 KiB in total, no NUL characters) and returned in responses. Duplicate keys at any depth are rejected. Numbers are stored exactly, but responses decode them as IEEE-754 doubles, so integers beyond 2^53 may lose precision when read back. Without SRTs and voices, translation behaves exactly as before (transcription and speaker detection are automatic).

source_srt?: SourceSrt { content, file_name, language }

One SRT document. Each cue is an index (1, 2, …), a timing line HH:MM:SS,mmm --> HH:MM:SS,mmm, and text formatted Speaker N: text. UTF-8 only (an optional BOM is stripped; CRLF/CR line endings are normalized to LF). At most 1 MiB and 5000 cues per document and 5 MiB across all documents.

content: string
minLength1
file_name?: string

Display name without path separators or control characters. Defaults to source-<language>.srt (source-source.srt when the source language is not yet known) or target-<language>.srt.

maxLength255
language?: string

For source_srt, must equal source_language when that is given, and the detected language otherwise; taken from it when omitted. For target_srts, must equal the key when given.

speaker_voices?: Record<string, string>

Voice per speaker. Keys are base-10, non-negative integer speaker IDs as used in the SRT cues ("1" for Speaker 1: ...); names such as "speaker-1", signs, whitespace or hexadecimal are rejected, and keys that collide after normalization ("01" and "1") are rejected. Keys are returned in canonical form. Values are external voice IDs (voice_id from GET /v1/video-translate/voices); unknown or deleted voices are rejected. Every key must be a speaker of the source subtitles; without any SRT, keys are checked against the speakers already detected for the video, and the request fails if none are known yet.

target_srts?: Record<string, TargetSrts>

Target-language subtitles keyed by language code (trimmed, case-insensitive; keys must be unique after normalization and listed in target_languages). Target languages without an entry are translated automatically. Each target must have the same cue count and speakers as the effective source subtitles (the supplied source_srt, or the segments stored for the processed video).

content: string
minLength1
file_name?: string

Display name without path separators or control characters. Defaults to source-<language>.srt (source-source.srt when the source language is not yet known) or target-<language>.srt.

maxLength255
language?: string

For source_srt, must equal source_language when that is given, and the detected language otherwise; taken from it when omitted. For target_srts, must equal the key when given.

Deprecatedtts_model?: "eleven_v4" | "eleven_multilingual_v2"

Deprecated compatibility field. Prefer top-level model. eleven_v4 equals expressive; eleven_multilingual_v2 equals classic. If both fields are sent they must agree.

One of the following:
"eleven_v4"
"eleven_multilingual_v2"
disable_background_audio?: boolean

Defaults to false when omitted; set to true to disable background audio.

disable_lip_sync?: boolean

Defaults to false when omitted; set to true to disable lip sync.

formality?: boolean
model?: "expressive" | "classic"

Product speech model. expressive maps to Eleven v4 and is the default; classic maps to Eleven Multilingual v2.

One of the following:
"expressive"
"classic"
reference_id?: string
maxLength255
source_language?: string

Optional supported source language code; detected when omitted.

webhook_url?: string

Optional HTTPS callback URL for terminal status. It must have a public host, contain no credentials or fragment, and redirects are not followed. The POST has Content-Type: application/json, X-Chamelaion-Event and X-Chamelaion-Delivery headers.

formaturi
maxLength2048
ReturnsExpand Collapse
VideoTranslateGenerateResponse { request_id, status }
request_id: string
formatuuid
status: "success"

Translate a remote video

import Chamelaion from 'chamelaion';

const client = new Chamelaion({
  bearerToken: process.env['CHAMELAION_BEARER_TOKEN'], // This is the default and can be omitted
});

const response = await client.videoTranslate.generate({
  inputs: [
    { type: 'video', url: 'https://storage.googleapis.com/chamelaion-test-media/video.mp4' },
  ],
  target_languages: ['de', 'fr'],
  config: {
    source_srt: {
      file_name: 'interview.srt',
      content:
        '1\n00:00:00,000 --> 00:00:02,500\nSpeaker 0: Welcome back.\n\n2\n00:00:02,600 --> 00:00:05,000\nSpeaker 1: Thanks for having me.\n',
    },
    target_srts: {
      de: {
        content:
          '1\n00:00:00,000 --> 00:00:02,500\nSpeaker 0: Willkommen zurück.\n\n2\n00:00:02,600 --> 00:00:05,000\nSpeaker 1: Danke für die Einladung.\n',
      },
    },
    speaker_voices: { '0': '21m00Tcm4TlvDq8ikWAM', '1': 'AZnzlk1XvdvUeBnXmlld' },
  },
  model: 'expressive',
  reference_id: 'customer-job-42',
  source_language: 'en',
  webhook_url: 'https://hooks.example.com/chamelaion/video-translate',
});

console.log(response.request_id);
{
  "status": "success",
  "request_id": "4c98dd00-a982-47d9-a8d6-e1f0b35a8944"
}
{
  "error": "target_languages must contain at least one language"
}
{
  "error": "duplicate target language \"de\""
}
{
  "error": "input must be a video file"
}
{
  "error": "config must be a valid JSON object"
}
{
  "error": "config.source_srt is not a valid SRT file: Line 2: invalid time format, 00:00:01 --> 00:00:02, expecting in '00:00:04,139 --> 00:00:04,799' format"
}
{
  "error": "config.target_srts.fr: language \"fr\" is not listed in target_languages"
}
{
  "error": "source_srt must be supplied either in config or as a multipart file, not both"
}
{
  "error": "config.speaker_voices key \"speaker-1\" must be a non-negative integer speaker ID such as \"1\""
}
{
  "error": "speaker_voices references unknown or unavailable voice IDs: \"missing-voice\""
}
{
  "error": "missing authorization header"
}
{
  "error": "invalid authorization format"
}
{
  "error": "missing token"
}
{
  "error": "invalid token"
}
{
  "error": "unauthorized"
}
{
  "error": "request body exceeds the 8 MiB limit"
}
{
  "error": "rate limit exceeded"
}
{
  "error": "internal error"
}
Returns Examples
{
  "status": "success",
  "request_id": "4c98dd00-a982-47d9-a8d6-e1f0b35a8944"
}
{
  "error": "target_languages must contain at least one language"
}
{
  "error": "duplicate target language \"de\""
}
{
  "error": "input must be a video file"
}
{
  "error": "config must be a valid JSON object"
}
{
  "error": "config.source_srt is not a valid SRT file: Line 2: invalid time format, 00:00:01 --> 00:00:02, expecting in '00:00:04,139 --> 00:00:04,799' format"
}
{
  "error": "config.target_srts.fr: language \"fr\" is not listed in target_languages"
}
{
  "error": "source_srt must be supplied either in config or as a multipart file, not both"
}
{
  "error": "config.speaker_voices key \"speaker-1\" must be a non-negative integer speaker ID such as \"1\""
}
{
  "error": "speaker_voices references unknown or unavailable voice IDs: \"missing-voice\""
}
{
  "error": "missing authorization header"
}
{
  "error": "invalid authorization format"
}
{
  "error": "missing token"
}
{
  "error": "invalid token"
}
{
  "error": "unauthorized"
}
{
  "error": "request body exceeds the 8 MiB limit"
}
{
  "error": "rate limit exceeded"
}
{
  "error": "internal error"
}