# Professional Subtitle Translator & Video Captioner (`lumaxys/media-to-professional-subtitles`) Actor

Transcribe, translate, quality-check, and burn subtitles into videos. Upload video, audio, SRT, or VTT and export SRT, VTT, TXT, JSON, or ready-to-publish MP4. Supports multilingual subtitles with automatic timing and QC.

- **URL**: https://apify.com/lumaxys/media-to-professional-subtitles.md
- **Developed by:** [François Fernandez](https://apify.com/lumaxys) (community)
- **Categories:** Videos, Automation, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $30.00 / 1,000 translated minutes

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Professional Subtitle Translator & Video Captioner

Transcribe, translate, quality-check, format, and optionally burn subtitles into video.

Upload a video, audio file, SRT, or VTT. The Actor can reuse existing subtitle tracks, translate them into multiple languages, correct technical subtitle issues, and export subtitle files or final subtitled MP4 videos.

> Machine translations are not human-reviewed. Linguistic review is recommended before professional publication.

### Which Actor should I use?

- **Media to translated subtitle files, without a rendered video:** [Video & Audio to Translated Subtitles](https://apify.com/lumaxys/professional-subtitle-formatter)
- **An existing SRT or VTT file that needs checking or correction:** [Professional Subtitle QC](https://apify.com/lumaxys/subtitle-qc)
- **The complete workflow, including an optional subtitled video:** use this Actor.

Each Actor covers a different stage of the subtitle workflow, so you only pay for the processing you actually need.

### What this Actor does

Use this Actor to:

- transcribe video or audio into timed subtitles;
- reuse an existing SRT or VTT file without retranscribing;
- extract a text subtitle track embedded in a compatible video container;
- translate subtitles into up to five target languages per run;
- apply terminology replacements for names, brands, and technical vocabulary;
- check and correct subtitle timing and formatting;
- export SRT, WebVTT, TXT, and structured JSON;
- create optional MP4 videos with subtitles permanently embedded;
- process several direct media URLs in one batch.

### Supported inputs

#### Media

- Video: MP4, MOV, MKV, WEBM
- Audio: MP3, WAV, M4A, AAC, OGG, FLAC
- Uploaded files through the Apify Console
- Direct public HTTP or HTTPS links to media files
- Multiple direct media URLs through `mediaUrls`

#### Existing subtitles

- Standalone SRT or WebVTT
- One video paired with an external SRT or VTT file
- A compatible text subtitle track embedded in a video container

#### Not supported

YouTube, TikTok, Instagram, and similar webpage URLs are not direct media files and are refused. Download the media first, then upload it or provide a direct file URL.

Bitmap subtitle tracks such as PGS or VobSub are not supported because this Actor does not include OCR.

### Main workflows

#### 1. Transcribe video or audio

Choose the transcription mode to create timed subtitles from the audio track.

The Actor can automatically detect the spoken language, preserve speaker changes when diarization is enabled, and format the result using the selected subtitle profile.

#### 2. Reuse existing subtitles

Use an external SRT/VTT file or an embedded text subtitle track to skip transcription.

This is useful when the original timing is already correct and you only need quality control, translation, or a final subtitled video.

#### 3. Translate subtitles

Select one or more target languages. Each successful translation is returned as separate subtitle files.

The **Translate into** menu provides 10 validated output languages:

- English (American) — `EN-US`
- Spanish — `ES`
- French — `FR`
- German — `DE`
- Italian — `IT`
- Portuguese (Brazilian) — `PT-BR`
- Arabic — `AR`
- Chinese (Simplified) — `ZH-HANS`
- Japanese — `JA`
- Korean — `KO`

You can select up to five of these languages in one run.

Longer translated text may be redistributed into additional cues while remaining inside the available media timeline.

A failure in one language does not remove successful outputs from other languages.

#### 4. Quality control

Technical QC checks:

- maximum lines per subtitle;
- maximum characters per line;
- reading speed in characters per second;
- minimum and maximum cue duration;
- overlaps and chronological order;
- minimum gaps between cues;
- empty cues and invalid timecodes;
- whitespace and line wrapping;
- media-boundary overflow.

When correction mode is enabled, the Actor can rewrap lines, normalize whitespace, repair overlaps, extend or trim durations, and conservatively merge short adjacent fragments.

QC validates technical subtitle compliance. It does not guarantee that a machine translation is semantically or culturally correct.

#### 5. Render final subtitled MP4 videos

Enable `renderSubtitles` to permanently embed subtitles into the video.

You can render:

- the source language;
- translated languages;
- every available language.

Rendering uses FFmpeg and libass inside the Actor container. The original media file is never overwritten.

When subtitles are already burned into the image, an optional box or blur can hide a user-defined horizontal zone before the new subtitles are added.

### Subtitle profiles

The Actor includes three formatting profiles:

| Profile | Intended use |
| --- | --- |
| `documentary` | Long-form and general video |
| `social` | Short-form and social-media video |
| `accessibility` | More conservative, highly readable subtitles |

Advanced settings can override line length, reading speed, minimum duration, maximum duration, and related rules.

### Output files

For each successful language, the Actor can generate:

- `.srt` — SubRip subtitles;
- `.vtt` — WebVTT subtitles;
- `.txt` — plain-text transcript;
- `.json` — structured data with metadata, cue timings, and QC information;
- `.mp4` — optional H.264/AAC video with burned subtitles.

Generated files are stored in the run Key-Value Store. The Dataset contains one result row per language with direct download links.

The `OUTPUT` record contains the complete run summary, including successful languages, failed languages, QC details, file references, billable minutes, and safe error messages.

### Example input

Translate an existing French SRT paired with a video into English, Spanish, and German:

```json
{
  "mediaFile": "https://example.com/video.mp4",
  "videoSubtitleMode": "external",
  "videoSubtitleUrl": "https://example.com/subtitles-fr.srt",
  "outputLanguageMode": "translations",
  "targetLanguages": [
    "EN-US",
    "ES",
    "DE"
  ],
  "outputFormats": [
    "srt",
    "vtt",
    "json"
  ],
  "profile": "social",
  "enableQc": true,
  "qcCorrectionMode": "check-and-correct",
  "qcAfterTranslation": true,
  "renderSubtitles": false
}
````

### Example output summary

```json
{
  "status": "success",
  "sourceFilename": "video.mp4",
  "languageCode": "fr",
  "mediaDurationSeconds": 111.67,
  "billableMinutes": 2,
  "successfulLanguages": [
    "EN-US",
    "ES",
    "DE"
  ],
  "nonCompliantLanguages": [],
  "failedLanguages": [],
  "translations": [
    {
      "languageCode": "EN-US",
      "status": "success",
      "technicalStatus": "compliant",
      "linguisticStatus": "machine-translated-unreviewed"
    }
  ]
}
```

### Pricing

This Actor uses pay-per-event pricing.

| Event | When it applies |
| --- | --- |
| Actor start | Once for a valid, non-empty run |
| Transcribed minute | Per started media minute sent for transcription |
| Subtitle QC minute | Per started subtitle minute processed with QC |
| Translated minute | Per started minute and successful target language |
| Rendered video minute | Per started minute and successful rendered language |

The Apify Console displays the maximum permitted run cost before execution. A failed translation is not charged as a successful translated-language event, and a failed render is not charged as a successful rendered-video event.

### Limits

| Limit | Value |
| --- | --- |
| Media size | 500 MB |
| Default media duration | 60 minutes |
| Absolute media duration | 180 minutes |
| Subtitle file size | 8 MB |
| Available target languages | 10 validated languages |
| Target languages per run | 5 maximum |
| Batch inputs | 50 |
| Parallel inputs | 5 |
| Subtitle lines | 2 maximum |
| Rendered MP4 | 2 GB per output |

Inputs above the configured limits are rejected before paid provider processing whenever possible.

### Privacy and external processing

Media is downloaded into temporary storage inside the run container and removed when the run ends.

When transcription is requested, audio is sent to the configured transcription provider. When translation is requested, subtitle text is sent to the configured translation provider. Video rendering runs locally inside the Actor container.

Sensitive credentials, signed URLs, and full transcripts are not intentionally written to logs.

### Important translation notice

Translations are machine-generated and marked:

```text
machine-translated-unreviewed
```

Technical QC verifies timing, line length, reading speed, gaps, overlaps, and export validity. It does not replace a native-language review.

Human review is particularly important for legal, medical, safety-critical, marketing, and culturally sensitive content.

### Troubleshooting

| Message | What to do |
| --- | --- |
| Social-platform page URLs are not supported | Upload the media or provide a direct media-file URL |
| No readable subtitle cue was found | Check that the file is valid SRT or WebVTT |
| Media has no audio stream | Use an existing external or embedded subtitle source |
| No embedded text subtitle track | Select another text track or provide SRT/VTT |
| Translation failed for one language | Download the successful languages and retry only the failed target |
| Translation is technically non-compliant | Review the generated file and adjust the profile or timing limits |
| Rendering requires a video input | Pair the subtitles with a real video file |
| Mask zone exceeds the frame | Reduce the mask top percentage or height |

### Recommended workflow

1. Export SRT or VTT first.
2. Review timing and machine translation.
3. Correct terminology when needed.
4. Render the final MP4 only after reviewing the subtitle files.

# Actor input Schema

## `mediaFile` (type: `string`):

Upload a video (MP4, MOV, MKV, WEBM) or audio file (MP3, WAV, M4A, AAC, OGG, FLAC). The file is analysed locally before anything is billed.

## `mediaUrl` (type: `string`):

A direct http(s) link to a video or audio FILE. Page URLs from YouTube, TikTok and Instagram are not supported.

## `mediaUrls` (type: `array`):

Process several media files in one run. Each input is handled independently: one failure never stops the others. Maximum 50 inputs per run.

## `subtitleUrl` (type: `string`):

Already have subtitles? Provide them here and transcription is skipped entirely — no audio processing, no transcription cost. The file goes straight to quality control and optional translation.

## `videoSubtitleMode` (type: `string`):

Choose whether video inputs are transcribed, use a paired SRT/VTT file, or reuse a text subtitle track already stored inside the video container. External and embedded modes skip ElevenLabs transcription.

## `videoSubtitleUrl` (type: `string`):

Used only with “Use an SRT/VTT paired with the video”. The timings and text come from this file, while the output MP4 is rendered from the video input. Exactly one video input is allowed in this mode.

## `embeddedSubtitleStreamIndex` (type: `integer`):

Optional global FFprobe stream index. Leave empty to select the default text subtitle track, or the first text track. Bitmap PGS/VobSub tracks require OCR and are refused.

## `languageCode` (type: `string`):

Leave empty to detect the language automatically. You may provide a DeepL BCP-47 source code such as fr, en, pt-BR or zh-Hant when detection needs help.

## `targetLanguages` (type: `array`):

Choose up to 5 targets from the bundled DeepL menu. At runtime the Actor verifies every code against DeepL’s live /v3/languages registry before sending billable text.

## `additionalTargetLanguages` (type: `array`):

Optional BCP-47 target codes not yet present in the static menu, for example a language newly added by DeepL. Codes are verified against DeepL’s live language registry before translation. The combined limit remains 5 targets.

## `outputLanguageMode` (type: `string`):

Choose which subtitle-file language versions are stored and shown in the Dataset. Automatic exports translations only when target languages are selected; otherwise it exports the original language. This setting controls SRT/VTT/TXT/JSON files only; MP4 rendering is controlled separately below.

## `profile` (type: `string`):

Segmentation and QC style. The QC profile follows this choice by default.

## `enableQc` (type: `boolean`):

Run professional QC on the source subtitles and, when enabled below, on every translation. This now includes freshly transcribed subtitles automatically.

## `qcCorrectionMode` (type: `string`):

Report problems only, or report and fix them. Correction re-wraps lines, normalises whitespace, repairs overlaps, gaps and reading speed. Words change only through terminology entries explicitly supplied below.

## `qcProfile` (type: `string`):

Recommended: use the same rule set as the subtitle profile selected below. Choose another profile only when you intentionally want stricter or different QC thresholds.

## `qcAfterTranslation` (type: `boolean`):

Recommended. Run QC again on every translated language because translated text can be longer than the source.

## `sourceTerminologyReplacements` (type: `array`):

Correct names, brands or specialist terms after transcription. Add one entry per line using ‘heard term => correct term’, for example ‘Lumaxis => Lumaxys’. Matching is case-insensitive and only explicit entries can change words.

## `outputFormats` (type: `array`):

Formats produced for every language.

## `renderSubtitles` (type: `boolean`):

Create final MP4 videos with subtitles permanently visible. The renderer automatically fits the selected style to portrait, landscape or square video and guarantees at most two visible text lines.

## `renderLanguages` (type: `string`):

Render the source language, translated languages, or one MP4 for every available language.

## `existingSubtitleMaskMode` (type: `string`):

Use this only when the old subtitles are part of the video pixels. “Box” covers the selected horizontal zone with a configurable colour; “Blur” blurs only that zone before adding the new subtitles.

## `existingSubtitleMaskTopPercent` (type: `number`):

Vertical position where the old-subtitle mask begins, measured from the top of the video.

## `existingSubtitleMaskHeightPercent` (type: `number`):

Height of the old-subtitle mask. A compact 12% default covers most caption bands; adjust it to the real old-text zone. Top plus height must not exceed 100%.

## `existingSubtitleMaskColor` (type: `string`):

Colour used by box mode in #RRGGBB format.

## `existingSubtitleMaskOpacity` (type: `integer`):

Opacity of the cover box. 100% fully hides old burned-in text; lower values intentionally let the original image and possibly some old text show through.

## `existingSubtitleBlurRadius` (type: `integer`):

Strength of the local blur used to hide old burned-in subtitles.

## `subtitleStylePreset` (type: `string`):

Start with a ready-to-use visual style. The final font size is automatically adapted to the video orientation and longest subtitle line. Advanced fields below override the selected preset.

## `subtitleFontFamily` (type: `string`):

Installed open-source font used by FFmpeg. Noto Sans provides the broadest multilingual coverage.

## `subtitleFontSize` (type: `integer`):

Advanced reference size. The renderer scales it for portrait, landscape or square video, then reduces it only when needed to keep every subtitle within two visible lines.

## `subtitleTextColor` (type: `string`):

Advanced. Six-digit hexadecimal colour in #RRGGBB format.

## `subtitleOutlineColor` (type: `string`):

Advanced. Six-digit hexadecimal colour used for the text outline.

## `subtitleOutlineWidth` (type: `number`):

Advanced. Outline thickness at 1080p; automatically scaled to the video resolution.

## `subtitleBackgroundColor` (type: `string`):

Advanced. Colour of the readability box when background opacity is above zero.

## `subtitleBackgroundOpacity` (type: `integer`):

Advanced. Set to 0 for no box or up to 100 for a fully opaque subtitle background.

## `subtitleShadow` (type: `number`):

Advanced. Drop-shadow distance at 1080p; automatically scaled to the video resolution.

## `subtitleBold` (type: `boolean`):

Advanced. Render subtitles using the bold face of the selected font.

## `subtitlePosition` (type: `string`):

Advanced. Place subtitles at the bottom, centre or top of the frame.

## `subtitleMarginPercent` (type: `number`):

Advanced. Distance from the selected top or bottom edge. Social preset uses a larger margin to avoid app controls.

## `diarize` (type: `boolean`):

Detect who speaks when. Supported by the ElevenLabs Scribe provider.

## `includeSpeakerLabels` (type: `boolean`):

Prefix each subtitle with the speaker identifier. Requires speaker identification.

## `transcriptionProvider` (type: `string`):

Only providers that are actually implemented are listed.

## `translationProvider` (type: `string`):

Only providers that are actually implemented are listed.

## `maxMediaMinutes` (type: `integer`):

Safety cap. A file longer than this is refused BEFORE any paid call, so a mistaken upload cannot generate a surprise bill.

## `batchConcurrency` (type: `integer`):

How many inputs to process at once in a batch. Defaults to 1: provider rate limits, not local speed, are the binding constraint, and serial runs have a predictable cost profile.

## `maxCharsPerLine` (type: `integer`):

Advanced. Applies to both segmentation and quality control.

## `maxLinesPerSubtitle` (type: `integer`):

Advanced. SRT and WebVTT output is limited to 2 lines per subtitle.

## `maxCps` (type: `integer`):

Advanced. Broadcast practice is 15-20; accessibility standards are stricter.

## `minSubtitleDurationMs` (type: `integer`):

Advanced. Below roughly 800 ms a subtitle is hard to read.

## `maxSubtitleDurationMs` (type: `integer`):

Advanced. Must be greater than the minimum duration.

## Actor input object example

```json
{
  "mediaUrl": "https://example.com/interview.mp4",
  "mediaUrls": [],
  "subtitleUrl": "https://example.com/interview.srt",
  "videoSubtitleMode": "transcribe",
  "languageCode": "fr",
  "targetLanguages": [],
  "additionalTargetLanguages": [],
  "outputLanguageMode": "auto",
  "profile": "social",
  "enableQc": true,
  "qcCorrectionMode": "check-and-correct",
  "qcProfile": "same",
  "qcAfterTranslation": true,
  "sourceTerminologyReplacements": [],
  "outputFormats": [
    "srt",
    "vtt",
    "txt",
    "json"
  ],
  "renderSubtitles": false,
  "renderLanguages": "all",
  "existingSubtitleMaskMode": "none",
  "existingSubtitleMaskTopPercent": 72,
  "existingSubtitleMaskHeightPercent": 12,
  "existingSubtitleMaskColor": "#000000",
  "existingSubtitleMaskOpacity": 100,
  "existingSubtitleBlurRadius": 14,
  "subtitleStylePreset": "classic",
  "subtitleTextColor": "#FFFFFF",
  "subtitleOutlineColor": "#000000",
  "subtitleBackgroundColor": "#000000",
  "diarize": false,
  "includeSpeakerLabels": false,
  "transcriptionProvider": "elevenlabs",
  "translationProvider": "deepl",
  "maxMediaMinutes": 60,
  "batchConcurrency": 1
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `files` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("lumaxys/media-to-professional-subtitles").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("lumaxys/media-to-professional-subtitles").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call lumaxys/media-to-professional-subtitles --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=lumaxys/media-to-professional-subtitles",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Professional Subtitle Translator & Video Captioner",
        "description": "Transcribe, translate, quality-check, and burn subtitles into videos. Upload video, audio, SRT, or VTT and export SRT, VTT, TXT, JSON, or ready-to-publish MP4. Supports multilingual subtitles with automatic timing and QC.",
        "version": "2.0",
        "x-build-id": "arD9KqbeC1dSxMNAq"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/lumaxys~media-to-professional-subtitles/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-lumaxys-media-to-professional-subtitles",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/lumaxys~media-to-professional-subtitles/runs": {
            "post": {
                "operationId": "runs-sync-lumaxys-media-to-professional-subtitles",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/lumaxys~media-to-professional-subtitles/run-sync": {
            "post": {
                "operationId": "run-sync-lumaxys-media-to-professional-subtitles",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "mediaFile": {
                        "title": "Video or audio file",
                        "type": "string",
                        "description": "Upload a video (MP4, MOV, MKV, WEBM) or audio file (MP3, WAV, M4A, AAC, OGG, FLAC). The file is analysed locally before anything is billed."
                    },
                    "mediaUrl": {
                        "title": "Direct media URL",
                        "type": "string",
                        "description": "A direct http(s) link to a video or audio FILE. Page URLs from YouTube, TikTok and Instagram are not supported."
                    },
                    "mediaUrls": {
                        "title": "Additional media URLs (batch)",
                        "type": "array",
                        "description": "Process several media files in one run. Each input is handled independently: one failure never stops the others. Maximum 50 inputs per run.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "subtitleUrl": {
                        "title": "Existing subtitle file (SRT or VTT)",
                        "type": "string",
                        "description": "Already have subtitles? Provide them here and transcription is skipped entirely — no audio processing, no transcription cost. The file goes straight to quality control and optional translation."
                    },
                    "videoSubtitleMode": {
                        "title": "Subtitle source for video",
                        "enum": [
                            "transcribe",
                            "external",
                            "embedded"
                        ],
                        "type": "string",
                        "description": "Choose whether video inputs are transcribed, use a paired SRT/VTT file, or reuse a text subtitle track already stored inside the video container. External and embedded modes skip ElevenLabs transcription.",
                        "default": "transcribe"
                    },
                    "videoSubtitleUrl": {
                        "title": "SRT/VTT paired with the video",
                        "type": "string",
                        "description": "Used only with “Use an SRT/VTT paired with the video”. The timings and text come from this file, while the output MP4 is rendered from the video input. Exactly one video input is allowed in this mode."
                    },
                    "embeddedSubtitleStreamIndex": {
                        "title": "Embedded subtitle stream index",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Optional global FFprobe stream index. Leave empty to select the default text subtitle track, or the first text track. Bitmap PGS/VobSub tracks require OCR and are refused."
                    },
                    "languageCode": {
                        "title": "Source language",
                        "type": "string",
                        "description": "Leave empty to detect the language automatically. You may provide a DeepL BCP-47 source code such as fr, en, pt-BR or zh-Hant when detection needs help."
                    },
                    "targetLanguages": {
                        "title": "Translate into",
                        "maxItems": 5,
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Choose up to 5 targets from the bundled DeepL menu. At runtime the Actor verifies every code against DeepL’s live /v3/languages registry before sending billable text.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "EN-US",
                                "ES",
                                "FR",
                                "DE",
                                "IT",
                                "PT-BR",
                                "AR",
                                "ZH-HANS",
                                "JA",
                                "KO"
                            ],
                            "enumTitles": [
                                "English (American) — EN-US",
                                "Spanish — ES",
                                "French — FR",
                                "German — DE",
                                "Italian — IT",
                                "Portuguese (Brazilian) — PT-BR",
                                "Arabic — AR",
                                "Chinese (Simplified) — ZH-HANS",
                                "Japanese — JA",
                                "Korean — KO"
                            ]
                        },
                        "default": []
                    },
                    "additionalTargetLanguages": {
                        "title": "Additional or newly released DeepL targets",
                        "maxItems": 5,
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Optional BCP-47 target codes not yet present in the static menu, for example a language newly added by DeepL. Codes are verified against DeepL’s live language registry before translation. The combined limit remains 5 targets.",
                        "items": {
                            "type": "string",
                            "minLength": 2,
                            "maxLength": 20
                        },
                        "default": []
                    },
                    "outputLanguageMode": {
                        "title": "Subtitle language versions to export",
                        "enum": [
                            "auto",
                            "translations",
                            "both",
                            "original"
                        ],
                        "type": "string",
                        "description": "Choose which subtitle-file language versions are stored and shown in the Dataset. Automatic exports translations only when target languages are selected; otherwise it exports the original language. This setting controls SRT/VTT/TXT/JSON files only; MP4 rendering is controlled separately below.",
                        "default": "auto"
                    },
                    "profile": {
                        "title": "Subtitle profile",
                        "enum": [
                            "documentary",
                            "social",
                            "accessibility"
                        ],
                        "type": "string",
                        "description": "Segmentation and QC style. The QC profile follows this choice by default.",
                        "default": "social"
                    },
                    "enableQc": {
                        "title": "Enable quality control",
                        "type": "boolean",
                        "description": "Run professional QC on the source subtitles and, when enabled below, on every translation. This now includes freshly transcribed subtitles automatically.",
                        "default": true
                    },
                    "qcCorrectionMode": {
                        "title": "Quality control mode",
                        "enum": [
                            "check-and-correct",
                            "check-only"
                        ],
                        "type": "string",
                        "description": "Report problems only, or report and fix them. Correction re-wraps lines, normalises whitespace, repairs overlaps, gaps and reading speed. Words change only through terminology entries explicitly supplied below.",
                        "default": "check-and-correct"
                    },
                    "qcProfile": {
                        "title": "Quality control profile",
                        "enum": [
                            "same",
                            "documentary",
                            "social",
                            "accessibility",
                            "custom"
                        ],
                        "type": "string",
                        "description": "Recommended: use the same rule set as the subtitle profile selected below. Choose another profile only when you intentionally want stricter or different QC thresholds.",
                        "default": "same"
                    },
                    "qcAfterTranslation": {
                        "title": "Re-check after translation",
                        "type": "boolean",
                        "description": "Recommended. Run QC again on every translated language because translated text can be longer than the source.",
                        "default": true
                    },
                    "sourceTerminologyReplacements": {
                        "title": "Terminology corrections (optional)",
                        "type": "array",
                        "description": "Correct names, brands or specialist terms after transcription. Add one entry per line using ‘heard term => correct term’, for example ‘Lumaxis => Lumaxys’. Matching is case-insensitive and only explicit entries can change words.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "outputFormats": {
                        "title": "Output formats",
                        "type": "array",
                        "description": "Formats produced for every language.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "srt",
                                "vtt",
                                "txt",
                                "json"
                            ],
                            "enumTitles": [
                                "SubRip (.srt)",
                                "WebVTT (.vtt)",
                                "Plain text (.txt)",
                                "Structured JSON"
                            ]
                        },
                        "default": [
                            "srt",
                            "vtt",
                            "txt",
                            "json"
                        ]
                    },
                    "renderSubtitles": {
                        "title": "Burn subtitles into the video",
                        "type": "boolean",
                        "description": "Create final MP4 videos with subtitles permanently visible. The renderer automatically fits the selected style to portrait, landscape or square video and guarantees at most two visible text lines.",
                        "default": false
                    },
                    "renderLanguages": {
                        "title": "Videos to render",
                        "enum": [
                            "all",
                            "source",
                            "translations"
                        ],
                        "type": "string",
                        "description": "Render the source language, translated languages, or one MP4 for every available language.",
                        "default": "all"
                    },
                    "existingSubtitleMaskMode": {
                        "title": "Hide subtitles already burned into the image",
                        "enum": [
                            "none",
                            "box",
                            "blur"
                        ],
                        "type": "string",
                        "description": "Use this only when the old subtitles are part of the video pixels. “Box” covers the selected horizontal zone with a configurable colour; “Blur” blurs only that zone before adding the new subtitles.",
                        "default": "none"
                    },
                    "existingSubtitleMaskTopPercent": {
                        "title": "Mask zone top (%)",
                        "minimum": 0,
                        "maximum": 99,
                        "type": "number",
                        "description": "Vertical position where the old-subtitle mask begins, measured from the top of the video.",
                        "default": 72
                    },
                    "existingSubtitleMaskHeightPercent": {
                        "title": "Mask zone height (%)",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "number",
                        "description": "Height of the old-subtitle mask. A compact 12% default covers most caption bands; adjust it to the real old-text zone. Top plus height must not exceed 100%.",
                        "default": 12
                    },
                    "existingSubtitleMaskColor": {
                        "title": "Mask box colour",
                        "type": "string",
                        "description": "Colour used by box mode in #RRGGBB format.",
                        "default": "#000000"
                    },
                    "existingSubtitleMaskOpacity": {
                        "title": "Mask box opacity (%)",
                        "minimum": 0,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Opacity of the cover box. 100% fully hides old burned-in text; lower values intentionally let the original image and possibly some old text show through.",
                        "default": 100
                    },
                    "existingSubtitleBlurRadius": {
                        "title": "Mask blur radius",
                        "minimum": 2,
                        "maximum": 40,
                        "type": "integer",
                        "description": "Strength of the local blur used to hide old burned-in subtitles.",
                        "default": 14
                    },
                    "subtitleStylePreset": {
                        "title": "Subtitle visual preset",
                        "enum": [
                            "classic",
                            "social",
                            "cinema",
                            "accessible",
                            "impact",
                            "custom"
                        ],
                        "type": "string",
                        "description": "Start with a ready-to-use visual style. The final font size is automatically adapted to the video orientation and longest subtitle line. Advanced fields below override the selected preset.",
                        "default": "classic"
                    },
                    "subtitleFontFamily": {
                        "title": "Font family",
                        "enum": [
                            "Noto Sans",
                            "DejaVu Sans",
                            "Liberation Sans",
                            "Liberation Serif",
                            "DejaVu Sans Mono"
                        ],
                        "type": "string",
                        "description": "Installed open-source font used by FFmpeg. Noto Sans provides the broadest multilingual coverage."
                    },
                    "subtitleFontSize": {
                        "title": "Font size",
                        "minimum": 16,
                        "maximum": 160,
                        "type": "integer",
                        "description": "Advanced reference size. The renderer scales it for portrait, landscape or square video, then reduces it only when needed to keep every subtitle within two visible lines."
                    },
                    "subtitleTextColor": {
                        "title": "Text colour",
                        "type": "string",
                        "description": "Advanced. Six-digit hexadecimal colour in #RRGGBB format."
                    },
                    "subtitleOutlineColor": {
                        "title": "Outline colour",
                        "type": "string",
                        "description": "Advanced. Six-digit hexadecimal colour used for the text outline."
                    },
                    "subtitleOutlineWidth": {
                        "title": "Outline width",
                        "minimum": 0,
                        "maximum": 12,
                        "type": "number",
                        "description": "Advanced. Outline thickness at 1080p; automatically scaled to the video resolution."
                    },
                    "subtitleBackgroundColor": {
                        "title": "Background colour",
                        "type": "string",
                        "description": "Advanced. Colour of the readability box when background opacity is above zero."
                    },
                    "subtitleBackgroundOpacity": {
                        "title": "Background opacity (%)",
                        "minimum": 0,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Advanced. Set to 0 for no box or up to 100 for a fully opaque subtitle background."
                    },
                    "subtitleShadow": {
                        "title": "Shadow size",
                        "minimum": 0,
                        "maximum": 12,
                        "type": "number",
                        "description": "Advanced. Drop-shadow distance at 1080p; automatically scaled to the video resolution."
                    },
                    "subtitleBold": {
                        "title": "Bold text",
                        "type": "boolean",
                        "description": "Advanced. Render subtitles using the bold face of the selected font."
                    },
                    "subtitlePosition": {
                        "title": "Subtitle position",
                        "enum": [
                            "bottom",
                            "center",
                            "top"
                        ],
                        "type": "string",
                        "description": "Advanced. Place subtitles at the bottom, centre or top of the frame."
                    },
                    "subtitleMarginPercent": {
                        "title": "Vertical safe margin (%)",
                        "minimum": 0,
                        "maximum": 35,
                        "type": "number",
                        "description": "Advanced. Distance from the selected top or bottom edge. Social preset uses a larger margin to avoid app controls."
                    },
                    "diarize": {
                        "title": "Identify speakers",
                        "type": "boolean",
                        "description": "Detect who speaks when. Supported by the ElevenLabs Scribe provider.",
                        "default": false
                    },
                    "includeSpeakerLabels": {
                        "title": "Show speaker labels in subtitles",
                        "type": "boolean",
                        "description": "Prefix each subtitle with the speaker identifier. Requires speaker identification.",
                        "default": false
                    },
                    "transcriptionProvider": {
                        "title": "Transcription provider",
                        "enum": [
                            "elevenlabs"
                        ],
                        "type": "string",
                        "description": "Only providers that are actually implemented are listed.",
                        "default": "elevenlabs"
                    },
                    "translationProvider": {
                        "title": "Translation provider",
                        "enum": [
                            "deepl"
                        ],
                        "type": "string",
                        "description": "Only providers that are actually implemented are listed.",
                        "default": "deepl"
                    },
                    "maxMediaMinutes": {
                        "title": "Maximum media duration (minutes)",
                        "minimum": 1,
                        "maximum": 180,
                        "type": "integer",
                        "description": "Safety cap. A file longer than this is refused BEFORE any paid call, so a mistaken upload cannot generate a surprise bill.",
                        "default": 60
                    },
                    "batchConcurrency": {
                        "title": "Parallel inputs",
                        "minimum": 1,
                        "maximum": 5,
                        "type": "integer",
                        "description": "How many inputs to process at once in a batch. Defaults to 1: provider rate limits, not local speed, are the binding constraint, and serial runs have a predictable cost profile.",
                        "default": 1
                    },
                    "maxCharsPerLine": {
                        "title": "Maximum characters per line",
                        "minimum": 16,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Advanced. Applies to both segmentation and quality control."
                    },
                    "maxLinesPerSubtitle": {
                        "title": "Maximum lines per subtitle",
                        "minimum": 1,
                        "maximum": 2,
                        "type": "integer",
                        "description": "Advanced. SRT and WebVTT output is limited to 2 lines per subtitle."
                    },
                    "maxCps": {
                        "title": "Maximum reading speed (characters per second)",
                        "minimum": 5,
                        "maximum": 40,
                        "type": "integer",
                        "description": "Advanced. Broadcast practice is 15-20; accessibility standards are stricter."
                    },
                    "minSubtitleDurationMs": {
                        "title": "Minimum subtitle duration (ms)",
                        "minimum": 200,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Advanced. Below roughly 800 ms a subtitle is hard to read."
                    },
                    "maxSubtitleDurationMs": {
                        "title": "Maximum subtitle duration (ms)",
                        "minimum": 1000,
                        "maximum": 20000,
                        "type": "integer",
                        "description": "Advanced. Must be greater than the minimum duration."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
