AI Subtitle Translation

Translate an existing subtitle file into another language, optionally applying the platform's built-in subtitle styles and colors, or producing bilingual subtitles.

This capability does not perform speech recognition and does not accept audio or video input. To generate subtitles from a video or audio file, use AI Subtitle Recognition.

AI Subtitle RecognitionAI Subtitle Translation (this page)
InputAudio or video fileSubtitle file .ass / .srt
What it doesSpeech recognition to generate subtitles (can also translate)Translates existing subtitles
BillingPer video minutePer character (per 1,000 characters)

Use this capability when you already have proofread subtitles and want another language: it does not re-run speech recognition, and it does not overwrite your existing proofreading.

⚠️ Behavior change (2026-08-22): As of 2026-08-22, this API strips Chinese and English commas and periods from the translated subtitle text by default (strip_punctuation defaults to true, see the parameter table below), so identical requests produce different subtitle text than before the upgrade; timecodes, line counts, and all other output fields are unchanged. To keep the previous behavior, pass strip_punctuation: false explicitly.

Create Task

Basic Information

ItemValue
Request MethodPOST
Request Path/task/subtitle_translate
Content-Typeapplication/json
AuthenticationRaw API key in the Authorization header

Request Body

ParameterTypeRequiredDefaultDescription
file_idstringYes-Uploaded subtitle file ID. Only .ass / .srt are accepted; audio or video files are rejected
languagestringYes-Subtitle source language code. See the full supported list below
translate_languagestringYes-Target language code for translation. It uses the same supported set as language
output_formatstringNoFollows inputOutput format: ass or srt. When omitted, .ass in produces .ass out and .srt in produces .srt out
line_modestringNo"resegment"Translation granularity. See "Translation Granularity" below
lingual_typestringNo"monolingual"monolingual or bilingual (source and translation shown together). Only effective for ass output
subtitle_typestringNo"default"Subtitle style preset: default, outline, cinema_yellow, immersive_box, wide_spacing, deep_shadow, or boxed. Only effective for ass output
subtitle_colorstringNo"雅黑"Subtitle color preset: 雅黑, 淡绿, 森林绿, 湖蓝, 道奇蓝, 钢蓝, 浅粉红, 深橙, 珊瑚橙, 橙红, or 土豪金. Only effective for ass output
video_sizearrayNo[1920, 1080]Canvas geometry [width, height], which determines how translated lines are wrapped. See "Canvas Geometry" below
strip_punctuationbooleanNotruePunctuation stripping for the translated subtitle text: stripping is on by default (punctuation looks poor in subtitles) — Chinese , 。 and English , . are replaced with spaces, in-word forms are exempt (decimals 3.5, domains example.com, thousands separators 1,000 stay intact), and all other punctuation (quotes, question marks, exclamation marks, dashes, etc.) is kept; consecutive spaces collapse to one and line edges are trimmed. Only the subtitle text is affected — timecodes, line counts, and all other output fields are unchanged. Pass false explicitly to keep punctuation intact

Supported Language Codes

language and translate_language use the same language set as AI Subtitle Recognition, supporting these 11 languages:

Language codeLanguage name
zh-CHTTraditional Chinese
zh-CHSSimplified Chinese
zh-CNChinese
ja-JPJapanese
en-USEnglish
es-ESSpanish
ru-RURussian
ko-KRKorean
fr-FRFrench
pt-PTPortuguese
vi-VNVietnamese

Translation Granularity (line_mode)

A single sentence is often split across several adjacent subtitle lines. How those breaks are handled determines both how natural the translation reads and whether the timeline stays intact — you cannot have both, so choose by need.

ValueHow it worksWhat you getTrade-off
resegment (default)Merges adjacent lines back into full sentences before translating, then re-wraps for the target languageMore natural translation, with line breaks that suit the target languageLine count and timeline change; they no longer map one-to-one to the input
keepTranslates strictly line by line, never merging across linesTimeline matches the input line for line, so the track can directly replace the originalLine-by-line translation lacks context, and short gaps between the original lines are preserved

Use keep when the translated track must drop straight back into an existing edit and the timecodes have to line up. Use the default resegment when you simply want a translation that reads well.

Canvas Geometry (video_size)

A translation is rarely the same length as the source, so lines must be re-wrapped to the picture width — which requires knowing the canvas size. Resolution order:

  1. This video_size parameter
  2. PlayRes in the .ass file header
  3. Server default 1920x1080 (landscape)

.srt files carry no canvas information, so nothing can be inferred from the file. For portrait output, always pass video_size explicitly; otherwise lines are wrapped for landscape and may run past the edge of the picture.

How Styles Relate to Output Format

subtitle_type, subtitle_color, and lingual_type all rely on the ASS format to carry style information. The SRT format carries no styling.

Therefore, if output_format is srt and any of those three parameters is also supplied, the request is rejected at task creation and no credits are charged.

The check is based on the output format, not the input format. Using a .srt input while requesting ass output with styles is entirely valid — that is the normal way to upgrade plain-text subtitles into styled ones.

Size Limits

Each task has subtitle size limits. Exceeding any of them rejects the request at task creation with no charge:

DimensionLimit
Subtitle entries2000
Total characters80000
File size8 MB

Split the file and submit in batches when you exceed a limit. For reference, a 90-minute feature film typically has 1,200–1,800 subtitle entries.

Request Example

curl -X POST https://api.ai-mcn.tv:10000/task/subtitle_translate \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file_id": "537489015178246",
    "language": "zh-CN",
    "translate_language": "en-US",
    "output_format": "ass",
    "line_mode": "resegment",
    "lingual_type": "bilingual",
    "subtitle_type": "boxed",
    "subtitle_color": "珊瑚橙",
    "video_size": [1920, 1080]
  }'

Success Response Example

{
  "code": 200,
  "msg": "success",
  "data": {
    "task_id": "537489015178247",
    "task_type": "subtitle_translate",
    "status": "queued"
  }
}

Query Task Result

Basic Information

ItemValue
Request MethodGET
Request Path/task/subtitle_translate/{task_id}
AuthenticationRaw API key in the Authorization header

Response Fields (output_result)

ParameterTypeDescription
subtitle_file_idstringTranslated subtitle file ID
subtitle_file_download_urlstringTranslated subtitle download link
output_formatstringActual output format (ass or srt)
line_modestringTranslation granularity actually used
statsobjectEntry counts, see below
degradedobjectDegradation flags, see below

stats object

ParameterTypeDescription
input_linesintegerNumber of input subtitle entries
output_linesintegerNumber of output entries (differing from the input is expected under resegment)
skipped_totalintegerTotal entries skipped across all stages

skipped_total covers zero-duration entries and malformed blocks dropped while reading, zero-duration entries newly produced by re-wrapping, and empty text segments dropped while writing. A non-zero value is worth a quick check of the output.

degraded object

Three booleans. Any true means the output has a perceptible but non-failing quality difference, which you can use to decide whether to re-run:

ParameterMeaning
summaryContext summary could not be produced; terminology consistency across the file may be lower
width_budgetRender width budget could not be computed; lines were wrapped by semantic length only, so some may run past the edge of the picture
translationThe translation pipeline fell back to chunked retry or machine translation; translation quality may be lower

Success Response Example

{
  "code": 200,
  "msg": "success",
  "data": {
    "task_id": "537489015178247",
    "status": "completed",
    "progress": 100,
    "output_result": {
      "subtitle_file_id": "537489015178249",
      "subtitle_file_download_url": "https://api.ai-mcn.tv:9000/cloud/file/ef/537489015178249.ass",
      "output_format": "ass",
      "line_mode": "resegment",
      "stats": {
        "input_lines": 420,
        "output_lines": 386,
        "skipped_total": 2
      },
      "degraded": {
        "summary": false,
        "width_budget": false,
        "translation": false
      }
    },
    "create_time": "2026-04-05T08:00:00Z",
    "update_time": "2026-04-05T08:01:30Z"
  }
}

Billing

Billed per character, at 1 credit per 1,000 characters.

  • Billable units = total subtitle characters ÷ 1000 (fractional units are preserved)
  • Characters are counted as Unicode code points; one Chinese, Japanese, or Korean character counts as 1 character
  • The final charge is rounded up to a whole credit; any non-empty subtitle costs at least 1 credit
Total charactersCharge
1,0001 credit
1,5002 credits
50,00050 credits
80,000 (limit)80 credits

Only subtitle text counts toward billing; timecodes and entry numbers do not. Every request rejected at task creation (invalid parameters, format conflict, size limit exceeded, or an unusable subtitle file) is free of charge.

Error Codes

Error codeHTTP statusDescriptionResolution
6013400Missing file_id, language, or translate_languageSupply the required parameters
6014400File type mismatchThis capability accepts only .ass / .srt; for audio or video use AI Subtitle Recognition
6016400Invalid parameter value, srt output conflicting with style parameters, size limit exceeded, or an unusable subtitle file (empty, malformed, or multi-layer bilingual)Adjust per the error message; none of these are charged
5202404File does not existVerify the file_id
6502401Authentication failedCheck the Authorization header
6201402Insufficient balanceTop up from the dashboard

Submitting a bilingual subtitle file (two entries covering the same time range) is rejected: there is no reliable way to tell which layer is the source, and guessing wrong would translate an already-translated line a second time. Split out the layer you want translated first.