Files
Curator/docs/modules/core.subtitles.md

2.7 KiB

src/core/subtitles.py

External subtitle sidecars — attach, discover, keep in sync on rename.

Curator does not mux/embed subtitles. Jellyfin plays an external subtitle file natively as long as it shares the video's filename stem, with an optional language code and flag suffix::

Title (rok) [tmdbid-N].mkv
Title (rok) [tmdbid-N].cs.srt          # language
Title (rok) [tmdbid-N].cs.forced.srt   # + a flag (forced / sdh / default)

Subtitle presence is a filesystem fact, like NFO — nothing is cached in the pool index. What Curator does own: copying a picked file into place with the right name (attach_subtitle), and moving a subtitle along whenever its video gets renamed so it never silently detaches (rename_subtitles_with).

Source: src/core/subtitles.py

Classes

SubtitleFile

class · line 30

class SubtitleFile:

One subtitle sidecar found next to a video.

SubtitleFile.label

property · line 38

label -> str

Human-readable jazyk (flag) for display, e.g. cs (forced).

Functions

subtitle_filename

function · line 44

subtitle_filename(video_stem: str, ext: str, language: Optional[str]=None, flag: Optional[str]=None) -> str

Canonical subtitle filename: {video_stem}[.language][.flag]{ext}.

_parse_subtitle_name

function · line 57

_parse_subtitle_name(video_stem: str, filename: str) -> Optional[tuple[Optional[str], Optional[str]]]

(language, flag) if filename is a subtitle sidecar of video_stem.

find_subtitles

function · line 83

find_subtitles(video_path: Path) -> list[SubtitleFile]

Every external subtitle sidecar sitting next to video_path, sorted.

attach_subtitle

function · line 101

attach_subtitle(video_path: Path, source: Path, *, language: Optional[str]=None, flag: Optional[str]=None, move: bool=False) -> Path

Copy (or move) source next to video_path, named to match it.

An existing subtitle already at that exact name (e.g. replacing the Czech track) is overwritten; nothing else next to the video is touched.

Raises: ValueError: source's extension isn't a recognised subtitle format.

rename_subtitles_with

function · line 128

rename_subtitles_with(old_video_path: Path, new_video_path: Path) -> list[Path]

Move every subtitle sidecar of old_video_path to match new_video_path.

Call this wherever a video gets renamed/moved so an attached subtitle never silently detaches (its stem would stop matching and Jellyfin would drop it). No-op when the video's path didn't actually change. Returns the new paths.