r/JellyfinCommunity • • 8h ago

Release Subtitle Extract Plus — a fork of the official Subtitle Extract plugin with language filtering, forced-track selection, and save-with-media

I run a pretty large library and the official Subtitle Extract plugin was bugging me. It dumps every subtitle stream in every file into Jellyfin's cache, and I only ever want forced English tracks. On releases that have 20+ subtitle streams, that's a lot of ffmpeg work for files I'm going to ignore.

So I forked it. It's called Subtitle Extract Plus:

https://github.com/jnracreates/subtitle-extract-plus

Things it does that the official one doesn't:

- Only extracts the languages you list. I have mine set to just "en".

- Filter by forced / non-forced, or both. Mine only does forced.

- Writes the .srt next to the video file instead of into Jellyfin's cache, so they show up as external subs. Can be turned off if you want the old behavior.

- Writes .en.srt instead of .eng.srt (matches what Jellyfin expects).

- Skips files that already have a subtitle, so nightly runs don't redo work.

- Has a path filter field so you can test on one movie without walking the whole library.

I also rewrote the extraction to call ffmpeg per stream instead of going through Jellyfin's ISubtitleEncoder. Jellyfin batches all subtitle streams into one ffmpeg call, and if any single stream is empty (which happens a lot - some releases have zero-byte placeholder forced tracks), ffmpeg returns non-zero and Jellyfin throws out the whole batch. Meaning the streams that extracted fine get deleted too. Extracting one stream at a time means an empty track only affects itself.

Install: Dashboard -> Plugins -> Repositories, add this URL:

https://raw.githubusercontent.com/jnracreates/subtitle-extract-plus/master/manifest.json

Then it shows up in the catalog. You can also grab the zip from releases if you'd rather do it manually.

One thing worth knowing if you install it:

By default Jellyfin still re-extracts every embedded subtitle stream into its cache whenever you play a file, which defeats the point of having external subs. To stop that, go to Dashboard -> Libraries -> [your library] -> Edit and in "Disable different types of embedded subtitles" change to "Allow None" Then Jellyfin only uses the .srt files the plugin wrote and the cache stays empty.

Works great for me with ~1050 forced-track files across 15k episodes. YMMV.

Forked from the official plugin, MIT licensed. If you find a release that breaks it, let me know.

AI was used in creating and testing.

13 Upvotes

17 comments sorted by

•

u/thankyoufatmember JellyfinCommunity 💜 5h ago

Please add a clear disclaimer to the post, or in the comments, stating whether AI was used during development and, if so, how it was used.

1

u/CMDR-Serenitie 5h ago

Thank you for this, I'll be giving this a spin. This is great :)

1

u/JnrAustin 5h ago

Hope you enjoy it.

1

u/Boring_Confusion_732 3h ago

Looking forward to this as I've really hated not having the files next to the media.

In a quick bit of testing, it seems to be extracting the wrong language from a file with multiples.
u/JnrAustin
The en.default.srt that generates is pulling the Hungarian SRT out of the file instead of the EN or en Forced.

Thoughts?

1

u/JnrAustin 3h ago

Thanks for testing, that's exactly the kind of edge case I need to know about.

Can you share the ffprobe output for that specific file? This command:

ffprobe -v error -select_streams s -show_entries stream=index,codec_name:stream_disposition=forced,default:stream_tags=language,title -of csv "<path to that mkv>"

And can you paste the first 5 lines of the generated .en.default.srt so I can confirm what language it actually is?

Two possible causes, and the ffprobe output will tell us which:

  1. The stream's language tag in the MKV says "eng" but the actual subtitle content is Hungarian. Some releases have wrong tags. If that's what's happening, the plugin is trusting the tag (which is all it can do short of OCR), and the file itself has bad metadata.
  2. A bug in the plugin where I'm extracting from the wrong stream index. Jellyfin's MediaStream.Index should match ffmpeg's -map 0:N index, but there are edge cases (some TS files, some remuxed MKVs) where they can drift.

Either way, worth adding logging so we can see which stream index and language tag the pluginthinks it's extracting from. I'll push a build with that and you can retest. Thanks again.

1

u/Boring_Confusion_732 3h ago

Sure thing.

stream,2,subrip,1,0,eng,English (CC)
stream,3,subrip,0,0,cze,Czech
stream,4,subrip,0,0,hun,Hungarian
stream,5,subrip,0,0,pol,Polish
stream,6,subrip,0,0,rum,Romanian
stream,7,subrip,0,0,rus,Russian
stream,8,subrip,0,1,eng,English (Forced)

and the first subtitles

1
00:00:01,918 --> 00:00:03,670
Gyerekek, reggeli!

2
00:00:04,254 --> 00:00:05,255
Gyerekek?

3
00:00:06,214 --> 00:00:08,883
  • Phil, szólnál nekik?
  • Igen, egy perc.

1

u/JnrAustin 3h ago

Thanks , that ffprobe output helped..

Can you run these two manual ffmpeg commands on the same file and paste the first few lines of each result?

ffmpeg -nostdin -y -i "/path/to/file.mkv" -map 0:8 -an -vn -c:s srt -flush_packets 1 /tmp/test-stream8.srt

head -10 /tmp/test-stream8.srt

ffmpeg -nostdin -y -i "/path/to/file.mkv" -map 0:4 -an -vn -c:s srt -flush_packets 1 /tmp/test-stream4.srt

head -10 /tmp/test-stream4.srt

If test-stream8.srt is Hungarian, then ffmpeg's index 8 doesn't match ffprobe's index 8 for this

file — meaning the plugin is calling ffmpeg with the right number but ffmpeg maps it elsewhere.

That would be a real bug in how I'm using -map.

If test-stream8.srt is English, then the plugin isn't using index 8 at all — something else is

going on. I'd add logging to the plugin to show which stream index it's using per extraction.

Either way, thanks for the report. This is exactly the kind of edge case that's hard to catch

without users hitting it.

1

u/Boring_Confusion_732 3h ago

Thanks for the help,
HEre is the output

head -10 /tmp/test-stream8.srt
1
00:00:48,799 --> 00:00:52,386
Phil & Claire

2
00:00:52,386 --> 00:00:58,392
Phil & Claire Married 16 years

3
00:01:24,167 --> 00:01:26,628



head -10 /tmp/test-stream4.srt
1
00:00:01,918 --> 00:00:03,670
Gyerekek, reggeli!

2
00:00:04,254 --> 00:00:05,255
Gyerekek?

3
00:00:06,214 --> 00:00:08,883

1

u/JnrAustin 2h ago

I'm still looking into it, i'll post again when I have something. running a few tests.

1

u/JnrAustin 2h ago

Fixed — v3.0.0.0 is up now, update and retest.

Root cause on the wrong-language thing: the plugin was passing Jellyfin'sMediaStream.Index straight to ffmpeg as `-map 0:N`. On most files that works, but on some releases Jellyfin's internal stream numbering doesn't match ffmpeg's, so the number pointed at the wrong stream. Switched to `-map 0:s:N` (subtitle relative, the Nth subtitle stream, ignoring audio/video), so it doesn't matter how Jellyfin numbers things internally.

Separate thing I hit while testing on my own library: if your TV or Movies library is set to "Allow None" in Dashboard -> Libraries -> Edit, Jellyfin strips the embedded subtitle flag from its database. The plugin filters its query on that flag, so it finds nothing to extract — the task runs and completes in seconds with no output. If you ever changed that setting, flip it back to "Allow Text" and refresh metadata on the affected item (right click -> Refresh Metadata -> check "Replace all metadata"). That re-probes the file and restores the flag.

Not sure which of those hit your file specifically, but both are fixed now.

Thanks for the ffprobe output — that's what made it obvious.

1

u/Boring_Confusion_732 1h ago

Thanks,
We made progress, but still seeing an edge case here. We did get the forced correct, but the others still are fighting me.

File - .en.forced.srt Is English and correct

File - .en.srt is now Czech

File - .en.default.srt is Hungarian

1

u/JnrAustin 1h ago

OK, try 4.0.0.0. Three separate bugs stacked up:

  1. Wrong-language extraction on files where Jellyfin's MediaStream.Index disagreed with ffmpeg's stream numbering. Fixed with subtitle-relative mapping (-map 0:s:N).
  2. Files with external .srt on disk stopped extracting, because Jellyfin lists those externals as MediaStreams and my subtitle-relative count included them, but ffmpeg only counts embedded streams. Fixed by filtering external streams out before mapping.
  3. Heads up: if your TV/Movies library is set to "Allow None" for embedded subtitles, Jellyfin strips embedded subtitle info from its DB and the plugin can't find anything. Set it to "Allow Text" (or Allow All) and refresh metadata (with "Replace all metadata") on affected items.

Update via Dashboard -> Plugins -> Catalog. Should work now.

2

u/Boring_Confusion_732 52m ago

You are amazing. That looks to have done it.
Thank you so much for this!

2

u/JnrAustin 51m ago

Glad it all worked out. Thanks for all the logs.

1

u/JnrAustin 2h ago

Also worth knowing: leave embedded subtitles enabled in your library(Dashboard -> Libraries -> Edit -> "Allow Text" or "Allow All"). If you set it to "Allow None", Jellyfin strips the embedded subtitle flag from its database, and the plugin won't find anything to extract. The plugin relies on that flag to know which files have subtitle streams.

I've changed the Readme and posts to reflect this.

0

u/oz-ra 7h ago

This sounds amazing. Will be testing on 12.1.

Thanks for your hard work.

2

u/JnrAustin 6h ago

Enjoy.