Extract Subtitles from MKV: A Practical Workflow Guide

September 1, 2026 · RenderIO

You've opened an MKV in a player, switched between several subtitle languages, and now need one of those tracks as a standalone file. The obvious command often works for English SRT, then fails completely when the selected track is PGS, VobSub, or a styled ASS file. The reason isn't usually the command. It's the subtitle codec.

To extract subtitles from MKV reliably, inspect the container first, identify the track type, and then choose a lossless extraction or OCR workflow. Text tracks can usually be demuxed directly into SRT or ASS. Image-based tracks can be copied out, but they must be recognized with OCR before they become searchable, editable text. That distinction also matters for accessibility workflows, including projects involving deaf and hard of hearing tech.

Table of Contents

Why Subtitles Live in MKV and What Extraction Actually Means

MKV, formally known as Matroska, is a container format, not a video codec. A single file can hold video, multiple audio languages, chapters, attachments, and several subtitle streams. One track might be an English SRT, another a French ASS file with positioning and styling, while a Japanese PGS track stores rendered subtitle images.

Matroska's subtitle model is formally specified in RFC 9559, standardized in October 2024. The specification defines subtitle tracks and describes subtitle frames through elements such as CuePoint and CueDuration. That structure is why extraction tools can address one stream by its track ID instead of decoding the video and trying to recreate captions from the picture.

The Library of Congress Matroska format profile also describes subtitle and caption support as well defined. Matroska files containing subtitles alone may use the .mks extension, which reflects how subtitles are treated as independent stream data rather than as part of the video image.

A diagram illustrating how an MKV container stores various subtitle formats including SRT, ASS, and PGS.

The codec fork that determines the workflow

The first question is simple:

  • Text-based tracks: SRT, SSA, ASS, and related timed-text formats contain characters and timing information. You can usually copy them out losslessly.
  • Image-based tracks: PGS and VobSub contain subtitle pictures. Extraction preserves the images, but it doesn't create editable text. OCR is a separate stage.
  • Burned-in subtitles: If the letters are part of the video pixels, there's no subtitle stream to demux. You need frame analysis and OCR, not MKV extraction.

This is different from video transcoding, because demuxing a subtitle track normally doesn't re-encode the video or alter its quality. The practical workflow is therefore inspect, classify, extract, validate. Treating every subtitle stream as if it were SRT is how empty files, unreadable output, and mislabeled bitmap streams enter production.

Practical rule: Choose the workflow from the subtitle codec, not from the file extension.

Inspecting an MKV and Extracting Text Subtitles

Start by listing the tracks. Don't guess the subtitle number from its position in a player, because track ordering can change after remuxing.

With MKVToolNix installed, run:

mkvmerge -i input.mkv

For more detailed metadata, use:

mkvinfo input.mkv

Look for subtitle entries and note the numeric Track ID, codec ID, language, and flags. Typical codec identifiers include S_TEXT/UTF8 for SubRip-style text, S_TEXT/SSA or S_TEXT/ASS for styled subtitles, and S_HDMV/PGS for Blu-ray bitmap subtitles. The MKVToolNix extraction documentation describes the track extraction syntax as mkvextract source-filename tracks ... TID:dest-filename.

Screenshot from https://example.com/screenshots/mkvmerge-i-output.png

FFmpeg for quick stream mapping

If the desired subtitle is the first subtitle stream, FFmpeg can copy it with:

ffmpeg -i input.mkv -map 0:s:0 -c:s copy subtitles.srt

The 0:s:0 selector means input file zero, subtitle stream zero. The -c:s copy option tells FFmpeg not to re-encode the stream. For language-based selection, use metadata mapping:

ffmpeg -i input.mkv -map 0:s:m:language:eng -c:s copy english.srt

Language mapping is safer when different files use different stream orders. It still depends on correct language metadata, so inspect the input when the result is ambiguous.

You can also use the dedicated MKVToolNix path:

mkvextract tracks input.mkv 3:english.srt

Here, 3 is the Matroska Track ID discovered during inspection. The documented workflow is track-level and preserves text subtitle data without video decoding.

For a deeper explanation of stream selection, this FFprobe tutorial is useful when you're building scripts rather than handling one file manually.

Validate before editing

Don't assume a successful process exit means the output is usable. Check the file type and inspect its opening and closing cues:

file english.srt
ffprobe english.srt

Open the result in Subtitle Edit or another subtitle editor and verify that the first cue appears at the correct point in the video. If the output is empty, inspect the codec again. An image-based stream may have been selected, or the requested format may not match what that codec can represent.

Handling ASS and SSA Styled Subtitles Without Losing Formatting

ASS and SSA are not just SRT with extra decoration. They can carry positioning, colors, karaoke timing, drawing commands, line breaks, and style definitions. Fansubs, anime title sequences, signs, and dialogue placed away from the lower margin often depend on those features.

Extract the original stream without re-encoding:

mkvextract tracks input.mkv 3:subtitles.ass

Or use FFmpeg when the stream mapping is clearer:

ffmpeg -i input.mkv -map 0:s:0 -c:s copy subtitles.ass

The extension should match the actual subtitle format. Don't save an ASS stream as .srt just because the destination application expects an SRT filename. A mislabeled file can appear empty or produce parsing errors.

Fonts are part of the presentation

ASS files can reference fonts that aren't installed on the target system. Matroska attachments often contain those font files. Extract them with:

mkvextract attachments input.mkv 1:font.ttf 2:font2.otf

Keep the extracted fonts alongside the ASS file, or install them in the rendering environment according to your studio's policy. Without the intended fonts, glyph widths, line wrapping, and visual placement can change even though the subtitle text and timestamps are intact.

If you need to add the extracted track back into a Matroska file, a remux can preserve the subtitle stream:

mkvmerge -o out.mkv input.mkv --language 0:eng --track-name 0:English subtitles.ass

The exact track-selection options should be checked against the input and the desired output order.

What conversion removes

Convert ASS to SRT only when the destination can't render ASS. The result may remain readable, but it won't preserve every visual instruction.

Feature Stays in ASS Survives SRT conversion
Cue text Yes Yes
Timing Yes Yes
Basic line breaks Yes Often, with limitations
Font choice Yes No
Color and styling Yes No
Precise screen positioning Yes No
Karaoke timing Yes No
Drawing commands Yes No

The safe principle is to keep the original ASS as the archival master and generate SRT as a compatibility derivative.

Extracting PGS and VobSub Image-Based Subtitles with OCR

PGS and VobSub look like subtitles to a media player, but they don't contain ordinary character strings. PGS stores timed bitmap regions commonly associated with Blu-ray workflows. VobSub uses bitmap subtitle data with accompanying index information. Both can be extracted without quality loss, but neither becomes editable text through a simple stream copy.

The pipeline has two distinct stages:

  1. Demux the image stream from the MKV.
  2. Run OCR on the extracted subtitle images and proofread the result.

For a PGS track, use its actual Matroska Track ID:

mkvextract tracks input.mkv 3:subtitles.sup

FFmpeg can also copy a mapped subtitle stream:

ffmpeg -i input.mkv -map 0:s:0 -c:s copy subtitles.sup

For VobSub, the output normally consists of a .sub file and its matching .idx file. Preserve both. The index contains timing and placement information that the image data alone doesn't provide.

OCR tools make different compromises

Subtitle Edit is usually the practical desktop choice for PGS because it can render subtitle images, send them through OCR, and let an operator correct the resulting cues. Its workflow is well suited to one-off jobs and quality-controlled localization.

VobSub2SRT is focused on converting VobSub material into SRT. It can be efficient when the source has clean, conventional lettering, but stylized fonts and complex backgrounds can create more correction work.

Tesseract is flexible when you control the preprocessing pipeline. A typical approach renders subtitle regions to PNG files, improves contrast, and invokes OCR with a suitable page segmentation mode, such as:

tesseract subtitle.png stdout --psm 6

The exact setting depends on the rendered crop. Tesseract doesn't understand subtitle timing by itself, so your pipeline must preserve the original timestamps and associate recognized text with each image frame.

Cloud OCR services such as Google Vision or AWS Textract can fit studio automation, especially when a queue already handles uploads, retries, and review. They introduce transmission, cost, privacy, and integration considerations, so they aren't automatically preferable to local OCR.

Engine Best for Accuracy Speed Format support
Subtitle Edit OCR Operator-assisted PGS workflows Strong with review Interactive PGS and VobSub imports, text subtitle export
VobSub2SRT Straightforward VobSub conversion Source-dependent Fast for clean material VobSub to SRT
Tesseract Custom rendered-image pipelines Preprocessing-dependent Automation-friendly Image input, text output
Cloud OCR Managed studio queues Service and image dependent Scales with job architecture Image input, text output

Where OCR fails

Drop shadows can merge with characters. Anti-aliased edges can confuse letter boundaries. Overlapping dialogue blocks, forced subtitle events, unusual colors, and inverted regions require human review or specialized preprocessing. OCR may also recognize the words correctly while leaving timing or line segmentation unsuitable for delivery.

A useful quality check compares every cue against the video, with special attention to names, punctuation, forced signs, and overlapping speakers. If a short sequence contains difficult artwork, manual timing correction can cost less than tuning an OCR pipeline that will only be used once.

OCR produces a draft subtitle file. It doesn't produce a mastered subtitle file.

Batch Extraction and Cloud FFmpeg API Workflows

A single command is fine for one MKV. A directory of multilingual files needs a manifest-driven process. The first step is to enumerate subtitle streams with ffprobe, capturing stream index, codec name, language tag, and disposition flags before extraction begins.

A compact inspection loop might look like this:

for file in ./mkv/*.mkv; do
  echo "FILE: $file"
  ffprobe -v error -select_streams s \
    -show_entries stream=index,codec_name:stream_tags=language,title \
    -of csv=p=0 "$file"
done

The output should drive the next step rather than a fixed 0:s:0 assumption. Duplicate language codes are common, and some tracks are marked und for undefined language. Default and forced flags also need to be recorded, because the first English track may be full dialogue while another contains only forced signs.

For a controlled batch, create explicit mappings after inspection:

ffmpeg -i input.mkv \
  -map 0:4 -c:s copy output.en.ass \
  -map 0:5 -c:s copy output.fr.srt

Use the correct output extension for the codec. For PGS, write .sup, then send that file to an OCR stage instead of pretending it's SRT.

A five-step batch extraction workflow diagram showing how to extract subtitle files from media content using FFprobe and FFmpeg.

When a cloud worker makes sense

A cloud FFmpeg API can separate extraction jobs from a workstation, especially when a back catalogue arrives in bursts or several files need processing in parallel. The trade-off is operational rather than magical. You exchange local control and local file access for remote storage handling, authentication, job monitoring, and service costs.

A typical request needs an input URL, an FFmpeg command, and an output destination. The exact endpoint and authentication format depend on the provider, so keep those values in environment variables rather than embedding credentials in a script.

A provider such as RenderIO can run custom FFmpeg commands in isolated processing environments and return outputs through signed URLs, which fits a subtitle demuxing job when your source and destination already live in object storage. It can also expose asynchronous status handling, so the caller doesn't need to hold an HTTP request open while a batch runs.

A Python client can follow this general pattern:

import os
import time
import requests

job = requests.post(
    os.environ["RENDERIO_JOBS_URL"],
    headers={"Authorization": f"Bearer {os.environ['RENDERIO_TOKEN']}"},
    json={
        "input_url": os.environ["INPUT_MKV_URL"],
        "command": "ffmpeg -i input.mkv -map 0:s:0 -c:s copy subtitles.srt",
        "output_destination": os.environ["OUTPUT_URL"]
    },
).json()

while True:
    status = requests.get(
        job["status_url"],
        headers={"Authorization": f"Bearer {os.environ['RENDERIO_TOKEN']}"}
    ).json()

    if status["status"] in {"completed", "failed"}:
        print(status)
        break

    time.sleep(5)

For adjacent media queues, teams often apply the same pattern to tasks such as batch converting MP3 to AAC. Keep local processing when files must not leave the workstation, the queue is small, or debugging depends on direct filesystem access.

Automating Subtitle Extraction in n8n and Zapier

Automation should fail clearly when an MKV has no usable subtitle stream. Don't let a workflow interpret a missing text track as an empty successful delivery.

An n8n flow can start with a file event from a watched folder, Google Drive, or a CMS webhook. The workflow uploads the MKV to a presigned storage URL, submits an HTTP request containing the input URL and FFmpeg extraction command, polls the job status, and then writes the returned .srt, .ass, or .sup file to Dropbox or Google Drive.

A practical node sequence looks like this:

  1. Watch or webhook trigger: Receive the source file and metadata.
  2. Upload node: Store the MKV at a signed URL with an expiration policy.
  3. HTTP Request node: Submit the extraction job and retain its job ID.
  4. Polling branch: Check status until the job completes or returns an error.
  5. Download node: Save the output with a name based on source ID, language, and codec.

For direct integration details, see the RenderIO FFmpeg n8n integration.

Screenshot from https://example.com/screenshots/n8n-subtitle-extraction-flow.png

Zapier needs the same control points

In Zapier, use Webhooks by Zapier to submit the job and Code by Zapier to parse the returned JSON. Store the job ID, then use a delay or scheduled follow-up step to retrieve status. The final action can place the subtitle file in Dropbox, Google Drive, or another storage connector.

Authentication headers should be kept in the platform's credential or secret fields. Don't put long-lived tokens in form data or filenames. Signed input and output URLs should expire, and the workflow should remove unnecessary media metadata when the business process doesn't require it.

Define explicit error paths for:

  • No subtitle streams: Stop and notify the operator instead of creating a blank sidecar.
  • Image-based codec: Route .sup or .sub output to OCR.
  • Duplicate language tags: Require a title, disposition, or human selection.
  • Failed polling: Record the provider response and retain the source job ID.
  • Expired URL: Request a fresh signed URL before retrying.

Once the flow works, save it as a reusable template with configurable input URL, track selector, output format, and destination. That makes the automation repeatable without hiding the codec decision that determines whether extraction is sufficient.

Decision Tree and Common Pitfalls

Use this decision tree before choosing a command:

  • SRT or another text track: Extract with FFmpeg or mkvextract, preserving the original stream.
  • ASS or SSA: Extract as .ass or .ssa, and retain fonts and attachments.
  • PGS: Extract to .sup, then run OCR.
  • VobSub: Preserve the .sub and .idx pair, then run OCR.
  • No subtitle stream: Extraction can't create one. Use transcription or OCR on burned-in pixels.

For a text track, a useful starting command is:

ffmpeg -i input.mkv -map 0:s:0 -c:s copy output.srt

For an image track, keep the intermediate format honest:

mkvextract tracks input.mkv 3:subtitle.sup

Then process the .sup file through an OCR workflow such as Subtitle Edit. The MKVToolNix documentation supports this track-oriented model, while the Matroska specification explains why subtitle frames can be addressed independently of the video.

Mistakes that break delivery

  • Using -c:s copy on PGS: The result is still bitmap subtitle data. Saving it with an .srt extension creates a misleading file, not readable text.
  • Dropping ASS attachments: The subtitle script may extract correctly, but missing fonts can alter glyph rendering, line wrapping, and placement.
  • Hard-coding stream indexes: Different MKVs can assign different stream orders. Parse the track list and resolve language, codec, title, default, and forced metadata before writing output names.
  • Skipping validation: A completed command doesn't prove that the selected language or format is correct.

Log the source filename, Track ID, stream index, codec, language, flags, output path, and processing result in a manifest. That record makes retries safe and gives localization or accessibility teams a traceable link between the delivered sidecar and its source stream.


RenderIO can run custom FFmpeg subtitle extraction jobs against remote media, return processed outputs through signed URLs, and support asynchronous polling for automated queues. If you're moving beyond one-off files, visit RenderIO to evaluate an API-based workflow for MKV subtitle extraction.