2025-09-12 17:27:24 EDT

M: Trying to extract a subtitle file from an MKV, period. How would I go about it? FFmpeg seems to be my go-to tool.

G: [Non-text content: thoughts; content_type=thoughts]

G: [Non-text content: reasoning_recap; content_type=reasoning_recap]

G: Here’s the quick, no-nonsense way to pull subs out of an MKV with FFmpeg.

TL;DR

  1. Identify the subtitle stream index.
  2. Extract it losslessly with -map and -c:s copy.
  3. Use the correct file extension for the subtitle codec (text vs image).

1) Inspect the MKV to find the subtitle track(s)

ffprobe -hide_banner -loglevel error -show_streams -select_streams s input.mkv

Look for lines like:

You’ll also see the stream index as index=N or can count 0:s:0, 0:s:1, etc.

2) Extract a specific subtitle track (lossless copy)

If it’s text (SRT/ASS)

# First subtitle stream (0:s:0), SubRip text
ffmpeg -nostdin -i input.mkv -map 0:s:0 -c:s copy output.srt

# If it's ASS
ffmpeg -nostdin -i input.mkv -map 0:s:1 -c:s copy output.ass

If it’s PGS (image-based)

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

PGS is not text; to turn it into SRT you need OCR in a separate tool (e.g., Subtitle Edit).

If it’s VobSub (DVD)

Best done with MKVToolNix; FFmpeg doesn’t directly dump .idx/.sub pairs as files. Example with mkvextract (optional alternative you may already have):

mkvextract tracks input.mkv 3:output.idx

(Replace 3 with the VobSub track ID shown by mkvmerge -i input.mkv.)

3) Pick by language instead of index (optional)

If your file has language tags:

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

4) Extract all subtitle tracks at once (text-only friendly)

FFmpeg can’t auto-choose extensions per track type. If you know they’re all SubRip:

ffmpeg -nostdin -i input.mkv -map 0:s -c:s copy sub_%02d.srt

Adjust extension to .ass if they’re all ASS. Mixed types are better handled one-by-one.

5) Grab embedded fonts (useful for ASS)

ffmpeg -nostdin -dump_attachment:t "" -i input.mkv -map 0:t? -c copy

This writes attached fonts to the current directory so your .ass renders correctly.


Common pitfalls, solved

That’s the whole workflow end to end.

2025-09-12 17:38:20 EDT

M: it looks like it's an ass fille. this is what i put in and what happened: ffmpeg -nostdin -i "s01e10 [Judas] Ishuzoku Reviewers (Interspecies Reviewers) - 10 [UNCENSORED 1080p][HEVC x265 10bit][Eng-Subs].mkv" -map 0:2:1 -c:2 copy output.ass ffmpeg version 7.1.1 Copyright (c) 2000-2025 the FFmpeg developers built with gcc 15 (GCC) configuration: --prefix=/usr --bindir=/usr/bin --datadir=/usr/share/ffmpeg --docdir=/usr/share/doc/ffmpeg --incdir=/usr/include/ffmpeg --libdir=/usr/lib64 --mandir=/usr/share/man --arch=x86_64 --optflags='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wno-complain-wrong-lang -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer' --extra-ldflags='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,--build-id=sha1 -specs=/usr/lib/rpm/redhat/redhat-package-notes ' --extra-cflags=' -I/usr/include/rav1e' --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libvo-amrwbenc --enable-version3 --enable-bzlib --enable-chromaprint --enable-fontconfig --enable-frei0r --enable-gcrypt --enable-gnutls --enable-ladspa --enable-lcms2 --enable-libaom --enable-libaribb24 --enable-libaribcaption --enable-libdav1d --enable-libass --enable-libbluray --enable-libbs2b --enable-libcodec2 --enable-libcdio --enable-libdrm --enable-libjack --enable-libjxl --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libharfbuzz --enable-libilbc --enable-liblc3 --enable-libmp3lame --enable-libmysofa --enable-nvenc --enable-openal --enable-opencl --enable-opengl --enable-libopenh264 --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-libplacebo --enable-librsvg --enable-librav1e --enable-librubberband --enable-libqrencode --enable-libsmbclient --enable-version3 --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtesseract --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libv4l2 --enable-libvidstab --enable-libvmaf --enable-version3 --enable-vapoursynth --enable-libvpx --enable-libvvenc --enable-vulkan --enable-libshaderc --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --enable-libxml2 --enable-libzimg --enable-libzmq --enable-libzvbi --enable-lv2 --enable-avfilter --enable-libmodplug --enable-postproc --enable-pthreads --disable-static --enable-shared --enable-gpl --disable-debug --disable-stripping --shlibdir=/usr/lib64 --enable-lto --enable-libvpl --enable-runtime-cpudetect libavutil 59. 39.100 / 59. 39.100 libavcodec 61. 19.101 / 61. 19.101 libavformat 61. 7.100 / 61. 7.100 libavdevice 61. 3.100 / 61. 3.100 libavfilter 10. 4.100 / 10. 4.100 libswscale 8. 3.100 / 8. 3.100 libswresample 5. 3.100 / 5. 3.100 libpostproc 58. 3.100 / 58. 3.100 Input #0, matroska,webm, from 's01e10 [Judas] Ishuzoku Reviewers (Interspecies Reviewers) - 10 [UNCENSORED 1080p][HEVC x265 10bit][Eng-Subs].mkv': Metadata: encoder : libebml v1.3.10 + libmatroska v1.5.2 creation_time : 2020-03-15T03:06:37.000000Z Duration: 00:23:29.53, start: -0.006000, bitrate: 1932 kb/s Stream #0:0(jpn): Video: hevc (Main 10), yuv420p10le(tv), 1920x1080, SAR 1:1 DAR 16:9, 23.98 fps, 23.98 tbr, 1k tbn (default) Metadata: title : [Judas] x265 10b BPS-eng : 1813365 DURATION-eng : 00:23:29.492000000 NUMBER_OF_FRAMES-eng: 33794 NUMBER_OF_BYTES-eng: 319490520 _STATISTICS_WRITING_APP-eng: mkvmerge v43.0.0 ('The Quartermaster') 64-bit _STATISTICS_WRITING_DATE_UTC-eng: 2020-03-15 03:06:37 _STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES Stream #0:1(jpn): Audio: opus, 48000 Hz, stereo, fltp (default) Metadata: title : [Judas] JAP Stereo (Opus 112Kbps) ENCODER : Lavc58.75.100 libopus BPS-eng : 113916 DURATION-eng : 00:23:29.531000000 NUMBER_OF_FRAMES-eng: 70477 NUMBER_OF_BYTES-eng: 20071136 _STATISTICS_WRITING_APP-eng: mkvmerge v43.0.0 ('The Quartermaster') 64-bit _STATISTICS_WRITING_DATE_UTC-eng: 2020-03-15 03:06:37 _STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES Stream #0:2(eng): Subtitle: ass (ssa) (default) Metadata: title : English BPS-eng : 126 DURATION-eng : 00:23:17.450000000 NUMBER_OF_FRAMES-eng: 348 NUMBER_OF_BYTES-eng: 22099 _STATISTICS_WRITING_APP-eng: mkvmerge v43.0.0 ('The Quartermaster') 64-bit _STATISTICS_WRITING_DATE_UTC-eng: 2020-03-15 03:06:37 _STATISTICS_TAGS-eng: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES Stream #0:3: Attachment: otf Metadata: filename : GandhiSans-BoldItalic.otf mimetype : application/vnd.ms-opentype Stream #0:4: Attachment: ttf Metadata: filename : GillSansCondExtraNova.ttf mimetype : application/x-truetype-font Stream #0:5: Attachment: otf Metadata: filename : KOSMIK-PLAINTHREE.OTF mimetype : application/vnd.ms-opentype Stream #0:6: Attachment: otf Metadata: filename : GandhiSans-Bold.otf mimetype : application/vnd.ms-opentype Trailing garbage after stream specifier: 1 Failed to set value '0:2:1' for option 'map': Invalid argument Error parsing options for output file output.ass. Error opening output files: Invalid argument (base) [david@new-host-1 s1]$

G: [Non-text content: thoughts; content_type=thoughts]

G: [Non-text content: reasoning_recap; content_type=reasoning_recap]

G: You were this close—the errors are just stream-specifier syntax.

What went wrong

Correct one-liners (ASS track at Stream #0:2)

# Simplest: refer to the stream index directly
ffmpeg -nostdin -i "s01e10 ... .mkv" -map 0:2 -c copy "output.ass"

# Or, use subtitle-class mapping (first subtitle stream)
ffmpeg -nostdin -i "s01e10 ... .mkv" -map 0:s:0 -c:s copy "output.ass"

# Or, pick by language tag (eng)
ffmpeg -nostdin -i "s01e10 ... .mkv" -map 0:s:m:language:eng -c:s copy "output.ass"

If you want the fonts the ASS references

ffmpeg -nostdin -dump_attachment:t "" -i "s01e10 ... .mkv" -map 0:t? -c copy
# writes GandhiSans-*.otf, etc., into the current directory

Quick sanity check (no write)

ffprobe -hide_banner -select_streams s -show_entries stream=index,codec_name,tag:language -of default=nw=1 "s01e10 ... .mkv"

That will extract the embedded ASS subtitles cleanly as output.ass.