fix(subtitle): resolve SDH stripping crash with VTT files

Fixes #34
This commit is contained in:
Andy
2025-10-31 14:51:25 +00:00
parent 351a606258
commit 6ebdfa8818
3 changed files with 57 additions and 31 deletions

View File

@@ -845,20 +845,22 @@ class dl:
# strip SDH subs to non-SDH if no equivalent same-lang non-SDH is available # strip SDH subs to non-SDH if no equivalent same-lang non-SDH is available
# uses a loose check, e.g, wont strip en-US SDH sub if a non-SDH en-GB is available # uses a loose check, e.g, wont strip en-US SDH sub if a non-SDH en-GB is available
for subtitle in title.tracks.subtitles: # Check if automatic SDH stripping is enabled in config
if subtitle.sdh and not any( if config.subtitle.get("strip_sdh", True):
is_close_match(subtitle.language, [x.language]) for subtitle in title.tracks.subtitles:
for x in title.tracks.subtitles if subtitle.sdh and not any(
if not x.sdh and not x.forced is_close_match(subtitle.language, [x.language])
): for x in title.tracks.subtitles
non_sdh_sub = deepcopy(subtitle) if not x.sdh and not x.forced
non_sdh_sub.id += "_stripped" ):
non_sdh_sub.sdh = False non_sdh_sub = deepcopy(subtitle)
title.tracks.add(non_sdh_sub) non_sdh_sub.id += "_stripped"
events.subscribe( non_sdh_sub.sdh = False
events.Types.TRACK_MULTIPLEX, title.tracks.add(non_sdh_sub)
lambda track: (track.strip_hearing_impaired()) if track.id == non_sdh_sub.id else None, events.subscribe(
) events.Types.TRACK_MULTIPLEX,
lambda track: (track.strip_hearing_impaired()) if track.id == non_sdh_sub.id else None,
)
with console.status("Sorting tracks by language and bitrate...", spinner="dots"): with console.status("Sorting tracks by language and bitrate...", spinner="dots"):
video_sort_lang = v_lang or lang video_sort_lang = v_lang or lang

View File

@@ -979,20 +979,33 @@ class Subtitle(Track):
stdout=subprocess.DEVNULL, stdout=subprocess.DEVNULL,
) )
else: else:
sub = Subtitles(self.path) if config.subtitle.get("convert_before_strip", True) and self.codec != Subtitle.Codec.SubRip:
self.path = self.convert(Subtitle.Codec.SubRip)
self.codec = Subtitle.Codec.SubRip
try: try:
sub.filter(rm_fonts=True, rm_ast=True, rm_music=True, rm_effects=True, rm_names=True, rm_author=True) sub = Subtitles(self.path)
except ValueError as e: try:
if "too many values to unpack" in str(e):
# Retry without name removal if the error is due to multiple colons in time references
# This can happen with lines like "at 10:00 and 2:00"
sub = Subtitles(self.path)
sub.filter( sub.filter(
rm_fonts=True, rm_ast=True, rm_music=True, rm_effects=True, rm_names=False, rm_author=True rm_fonts=True, rm_ast=True, rm_music=True, rm_effects=True, rm_names=True, rm_author=True
) )
except ValueError as e:
if "too many values to unpack" in str(e):
# Retry without name removal if the error is due to multiple colons in time references
# This can happen with lines like "at 10:00 and 2:00"
sub = Subtitles(self.path)
sub.filter(
rm_fonts=True, rm_ast=True, rm_music=True, rm_effects=True, rm_names=False, rm_author=True
)
else:
raise
sub.save()
except (IOError, OSError) as e:
if "is not valid subtitle file" in str(e):
self.log.warning(f"Failed to strip SDH from {self.path.name}: {e}")
self.log.warning("Continuing without SDH stripping for this subtitle")
else: else:
raise raise
sub.save()
def reverse_rtl(self) -> None: def reverse_rtl(self) -> None:
""" """

View File

@@ -1,3 +1,10 @@
# API key for The Movie Database (TMDB)
tmdb_api_key: ""
# Client ID for SIMKL API (optional, improves metadata matching)
# Get your free client ID at: https://simkl.com/settings/developer/
simkl_client_id: ""
# Group or Username to postfix to the end of all download filenames following a dash # Group or Username to postfix to the end of all download filenames following a dash
tag: user_tag tag: user_tag
@@ -333,22 +340,26 @@ filenames:
chapters: "Chapters_{title}_{random}.txt" chapters: "Chapters_{title}_{random}.txt"
subtitle: "Subtitle_{id}_{language}.srt" subtitle: "Subtitle_{id}_{language}.srt"
# API key for The Movie Database (TMDB)
tmdb_api_key: ""
# Client ID for SIMKL API (optional, improves metadata matching)
# Get your free client ID at: https://simkl.com/settings/developer/
simkl_client_id: ""
# conversion_method: # conversion_method:
# - auto (default): Smart routing - subby for WebVTT/SAMI, standard for others # - auto (default): Smart routing - subby for WebVTT/SAMI, pycaption for others
# - subby: Always use subby with advanced processing # - subby: Always use subby with advanced processing
# - pycaption: Use only pycaption library (no SubtitleEdit, no subby) # - pycaption: Use only pycaption library (no SubtitleEdit, no subby)
# - subtitleedit: Prefer SubtitleEdit when available, fall back to pycaption # - subtitleedit: Prefer SubtitleEdit when available, fall back to pycaption
# - pysubs2: Use pysubs2 library (supports SRT/SSA/ASS/WebVTT/TTML/SAMI/MicroDVD/MPL2/TMP) # - pysubs2: Use pysubs2 library (supports SRT/SSA/ASS/WebVTT/TTML/SAMI/MicroDVD/MPL2/TMP)
subtitle: subtitle:
conversion_method: auto conversion_method: auto
# sdh_method: Method to use for SDH (hearing impaired) stripping
# - auto (default): Try subby (SRT only), then SubtitleEdit (if available), then subtitle-filter
# - subby: Use subby library (SRT only)
# - subtitleedit: Use SubtitleEdit tool (Windows only, falls back to subtitle-filter)
# - filter-subs: Use subtitle-filter library directly
sdh_method: auto sdh_method: auto
# strip_sdh: Automatically create stripped (non-SDH) versions of SDH subtitles
# Set to false to disable automatic SDH stripping entirely (default: true)
strip_sdh: true
# convert_before_strip: Auto-convert VTT/other formats to SRT before using subtitle-filter
# This ensures compatibility when subtitle-filter is used as fallback (default: true)
convert_before_strip: true
# Configuration for pywidevine's serve functionality # Configuration for pywidevine's serve functionality
serve: serve: