## Translate a remote video

`video_translate.generate(VideoTranslateGenerateParams**kwargs)  -> VideoTranslateGenerateResponse`

**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`).
1. **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.

### Parameters

- `inputs: Iterable[Input]`

  - `type: Literal["video"]`

    - `"video"`

  - `url: str`

- `target_languages: Sequence[str]`

- `config: Optional[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: Optional[ConfigSourceSrt]`

    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: str`

    - `file_name: Optional[str]`

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

    - `language: Optional[str]`

      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: Optional[Dict[str, str]]`

    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: Optional[Dict[str, ConfigTargetSrts]]`

    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: str`

    - `file_name: Optional[str]`

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

    - `language: Optional[str]`

      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.

  - `tts_model: Optional[Literal["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.

    - `"eleven_v4"`

    - `"eleven_multilingual_v2"`

- `disable_background_audio: Optional[bool]`

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

- `disable_lip_sync: Optional[bool]`

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

- `formality: Optional[bool]`

- `model: Optional[Literal["expressive", "classic"]]`

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

  - `"expressive"`

  - `"classic"`

- `reference_id: Optional[str]`

- `source_language: Optional[str]`

  Optional supported source language code; detected when omitted.

- `webhook_url: Optional[str]`

  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.

### Returns

- `class VideoTranslateGenerateResponse: …`

  - `request_id: str`

  - `status: Literal["success"]`

    - `"success"`

### Example

```python
import os
from chamelaion import Chamelaion

client = Chamelaion(
    bearer_token=os.environ.get("CHAMELAION_BEARER_TOKEN"),  # This is the default and can be omitted
)
response = client.video_translate.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",
        },
    },
    disable_background_audio=False,
    disable_lip_sync=False,
    formality=False,
    model="expressive",
    reference_id="customer-job-42",
    source_language="en",
    webhook_url="https://hooks.example.com/chamelaion/video-translate",
)
print(response.request_id)
```

#### Response

```json
{
  "status": "success",
  "request_id": "4c98dd00-a982-47d9-a8d6-e1f0b35a8944"
}
```
