Skip to content
Naming and matching

Naming and matching

Whether subtrace works well on your library is mostly decided by how your folders are named. This page explains exactly what it reads.

Ids first

subtrace was built around a library that follows the Plex / TRaSH naming convention, with an external id in the folder name:

/media/Movies/Heat (1995) {tmdb-949}/Heat (1995) Bluray-1080p.mkv
/media/TV Shows/1923 {tmdb-157744}/Season 02/1923 - S02E01 - The Killing Season.mkv

That id is pulled out of the path and sent to the provider as an exact lookup (tmdb_id, imdb_id), so the provider returns subtitles for that title rather than for whatever its search engine thought you meant.

Recognized id tags, case-insensitive, in {} or [], with - or =:

TagExamples
TMDB{tmdb-949}, {tmdbid-949}, [tmdbid=949]
TVDB{tvdb-121361}, [tvdbid=121361]
IMDB{imdb-tt0113277}, [imdbid=tt0113277]

The filename is checked first, then each parent directory up to the library root — so an id on the show folder covers every episode inside it.

Without an id

If no id is found, subtrace falls back to a title-and-year query built from the path (plus season/episode for TV). It is not nothing, but it is a fuzzy string search against a provider’s catalogue: expect misses on anything with a common title, a foreign title, a remake, or an unusual release name.

Renaming to the Plex/TRaSH convention is the fix, and Radarr/Sonarr do it automatically. Support for other layouts is welcome — see Contributing.

Title, year, season, episode

From the same path subtrace also derives:

  • Title — for an episode, the show directory under the root; for a movie, the movie’s own folder, falling back to the filename. Id tags are stripped first, . and _ become spaces.
  • Year — the last (YYYY) in the name, accepted between 1880 and 2999, so a title that itself contains a year (1923 (2022)) does not confuse it.
  • Season / episodeS01E02, s01e02, S01E02-E03, 1x05. If the filename carries only an episode marker (E05 - Title), the season is taken from a parent directory named Season 02, Season.2, Series 2, Staffel 2, or S02.

A file with an SxxEyy tag is treated as TV even if it sits in a kind = "movie" root, so a stray file in the wrong place is still handled correctly.

What counts as “already has subtitles”

A video needs subtitles when no sidecar for a configured language sits next to it. All the variants Plex understands count:

Movie.srt              # no language tag — assumed to be your first configured language
Movie.en.srt
Movie.en.forced.srt
Movie.en.sdh.srt
Movie.english.srt      # full English name, for the 24 languages with a known name

The check is a prefix match on the video’s basename plus one of subtitles.extensions (.srt, .ass, .ssa, .sub, .vtt by default), so .ass files already on disk stop subtrace from fetching an .srt.

Two switches change the rule:

  • subtitles.skip_if_any_language = true — any subtitle file at all satisfies the video, whatever its language.
  • subtitles.overwrite = true — ignore what is there and fetch anyway.
Embedded subtitle tracks are not examined. That would mean running ffprobe against every file in the library. If your rips carry embedded subtitles, subtrace will still fetch sidecars for them.

Where the new file is written

subtitles.naming is a template rendered next to the video:

PlaceholderExpands to
{basename}video filename without its extension (required)
{lang}the language code being fetched
{ext}the video’s extension, without the dot

The default {basename}.{lang}.srt is what Plex auto-detects. A config whose naming lacks {basename} is rejected at load time.