Search Documentation
Search across all documentation pages
Subtitles

Subtitles

Transcodely supports flexible subtitle processing as part of your transcoding outputs. You can pass through existing subtitle tracks, convert between formats, burn subtitles directly into the video, or extract embedded subtitles as sidecar files.

Subtitle tracks are configured in the subtitle_tracks array of an Output Specification. Each output can include up to 8 subtitle tracks.


The SubtitleTrack object

AttributeTypeRequiredDescription
operationenumYesSubtitle operation. One of: passthrough, convert, burn_in, extract. See Operations.
source_stream_indexintegerOne ofIndex of the subtitle stream in the input file (0—31). Mutually exclusive with source_url.
source_urlstringOne ofURL to an external subtitle file. Supported schemes: gs://, s3://, https://. Mutually exclusive with source_stream_index. Max 2048 characters.
input_formatenumNoInput subtitle format. One of: srt, webvtt, ttml, ass. Auto-detected when omitted.
output_formatenumNoOutput subtitle format. One of: srt, webvtt, ttml, ass. Required for convert and extract operations.
languagestringNoISO 639-2 three-letter language code (e.g., eng, spa, fra, deu).
labelstringNoHuman-readable label (e.g., "English", "Spanish (Latin America)"). Max 64 characters.
is_defaultbooleanNoMark as the default subtitle track for the player.
hearing_impairedbooleanNoFlag for hearing-impaired / closed caption tracks (SDH).
forcedbooleanNoFlag for forced subtitles (e.g., foreign-language dialogue in an otherwise native-language film).
burn_in_styleobjectNoStyling for burn-in subtitles. Only valid when operation is burn_in. See Burn-in styling.
{
  "operation": "convert",
  "source_url": "gs://my-bucket/subs/english.srt",
  "input_format": "srt",
  "output_format": "webvtt",
  "language": "eng",
  "label": "English",
  "is_default": true
}

Operations

Each subtitle track requires exactly one operation that determines how Transcodely processes it.

OperationDescriptionSourceOutput
passthroughCopy the subtitle track to the output without modification.source_stream_index or source_urlPreserves original format.
convertConvert between subtitle formats.source_stream_index or source_urloutput_format required.
burn_inRender subtitles directly into the video frames. Produces a hard-subbed video — subtitles cannot be turned off by the viewer.source_stream_index or source_urlNo sidecar file produced. burn_in_style optional.
extractExtract an embedded subtitle stream as a standalone sidecar file.source_stream_index onlyoutput_format specifies the sidecar file format.

Note: The extract operation only accepts source_stream_index since it extracts subtitles already embedded in the input file. Use convert with source_url for external subtitle files.


Formats

Transcodely supports four subtitle formats for input and output.

FormatAPI ValueExtensionDescription
SRTsrt.srtSubRip Text. The most common subtitle format. Plain text with timestamps. Widely supported by all players.
WebVTTwebvtt.vttWeb Video Text Tracks. Standard for HTML5 <video> and HLS/DASH streaming. Supports styling and positioning.
TTMLttml.ttmlTimed Text Markup Language. XML-based format used in broadcast, DASH, and IMSC1 (Netflix, Disney+).
ASSass.assAdvanced SubStation Alpha. Rich formatting with fonts, colors, and animations. Common in anime and fansubs.

Format compatibility

Not all format conversions are lossless. Converting from a rich format to a simpler one may discard styling information:

FromToNotes
srtwebvttLossless. SRT is a subset of WebVTT.
webvttsrtPositioning and styling cues are stripped.
asssrt / webvttRich formatting (fonts, colors, animations) is stripped.
ttmlsrt / webvttXML styling and layout is stripped.
srt / webvttttmlText content is preserved; no styling added.

Source options

Every subtitle track requires a source — either an embedded stream from the input file or an external subtitle file. The two modes are mutually exclusive.

Embedded stream

Use source_stream_index to reference a subtitle stream embedded in the input file by its zero-based index. Use Input Metadata to discover available subtitle streams and their indices.

{
  "operation": "passthrough",
  "source_stream_index": 0,
  "language": "eng",
  "label": "English"
}

External file

Use source_url to reference a standalone subtitle file by URL. Supported schemes: gs://, s3://, and https://. The subtitle file is downloaded and processed alongside the video.

{
  "operation": "convert",
  "source_url": "gs://my-bucket/subs/spanish.srt",
  "input_format": "srt",
  "output_format": "webvtt",
  "language": "spa",
  "label": "Spanish"
}

Burn-in styling

The burn_in_style object controls the appearance of burned-in subtitles. All fields are optional with sensible defaults.

AttributeTypeDefaultDescription
font_familystring"Arial"Font family name. Max 64 characters.
font_sizeinteger24Font size in pixels (8—120).
font_colorstring"#FFFFFF"Text color as hex (e.g., "#FFFFFF" for white).
outline_colorstring"#000000"Outline color as hex (e.g., "#000000" for black).
outline_widthinteger2Outline thickness in pixels (0—10). Set to 0 for no outline.
margin_bottominteger30Bottom margin in pixels (0—200). Distance from the bottom of the video frame.
{
  "burn_in_style": {
    "font_family": "Helvetica",
    "font_size": 28,
    "font_color": "#FFFF00",
    "outline_color": "#000000",
    "outline_width": 3,
    "margin_bottom": 40
  }
}

Tip: For maximum readability across different video content, use a white font with a black outline (outline_width of 2—3). Increase font_size for 4K outputs where the default 24px may appear small.


Examples

Passthrough embedded subtitle

Pass through an embedded subtitle track from the input file into an HLS output without modification.

{
  "type": "hls",
  "video": [
    {"codec": "h264", "resolution": "1080p", "quality": "standard"}
  ],
  "subtitle_tracks": [
    {
      "operation": "passthrough",
      "source_stream_index": 0,
      "language": "eng",
      "label": "English",
      "is_default": true
    }
  ]
}

Convert SRT to WebVTT

Convert an external SRT file to WebVTT format for HLS streaming compatibility.

{
  "type": "hls",
  "video": [
    {"codec": "h264", "resolution": "1080p", "quality": "standard"}
  ],
  "subtitle_tracks": [
    {
      "operation": "convert",
      "source_url": "gs://my-bucket/subs/english.srt",
      "input_format": "srt",
      "output_format": "webvtt",
      "language": "eng",
      "label": "English",
      "is_default": true
    }
  ]
}

Burn-in with custom styling

Burn subtitles directly into the video frames with custom font, color, and positioning. The resulting video will have permanently visible subtitles.

{
  "type": "mp4",
  "video": [
    {"codec": "h264", "resolution": "1080p", "quality": "standard"}
  ],
  "subtitle_tracks": [
    {
      "operation": "burn_in",
      "source_url": "https://cdn.example.com/subs/spanish.srt",
      "language": "spa",
      "burn_in_style": {
        "font_family": "Helvetica",
        "font_size": 28,
        "font_color": "#FFFF00",
        "outline_color": "#000000",
        "outline_width": 3,
        "margin_bottom": 40
      }
    }
  ]
}

Multi-language streaming with SDH

Configure multiple subtitle tracks for adaptive streaming, including hearing-impaired and forced subtitle variants.

{
  "type": "adaptive",
  "video": [
    {"codec": "h264", "resolution": "1080p", "quality": "standard"},
    {"codec": "h264", "resolution": "720p", "quality": "standard"}
  ],
  "subtitle_tracks": [
    {
      "operation": "convert",
      "source_url": "gs://my-bucket/subs/en.srt",
      "output_format": "webvtt",
      "language": "eng",
      "label": "English",
      "is_default": true
    },
    {
      "operation": "convert",
      "source_url": "gs://my-bucket/subs/en-sdh.srt",
      "output_format": "webvtt",
      "language": "eng",
      "label": "English (SDH)",
      "hearing_impaired": true
    },
    {
      "operation": "convert",
      "source_url": "gs://my-bucket/subs/es.srt",
      "output_format": "webvtt",
      "language": "spa",
      "label": "Spanish"
    },
    {
      "operation": "passthrough",
      "source_stream_index": 2,
      "language": "fra",
      "label": "French (Forced)",
      "forced": true
    }
  ]
}

Validation rules

Transcodely validates subtitle track configuration at job creation time. The following constraints are enforced:

RuleDescription
Maximum 8 tracksEach output supports up to 8 subtitle_tracks entries.
Mutually exclusive sourceExactly one of source_stream_index or source_url must be set per track.
extract requires stream indexThe extract operation only accepts source_stream_index, not source_url.
convert requires output formatThe convert operation requires output_format to be set.
burn_in_style requires burn-inThe burn_in_style object is only valid when operation is burn_in.
Language formatlanguage must be a valid ISO 639-2 three-letter code matching ^[a-z]{3}$.
Stream index rangesource_stream_index must be between 0 and 31 (inclusive).
URL schemessource_url must use gs://, s3://, or https:// scheme. Max 2048 characters.
Label lengthlabel must not exceed 64 characters.