mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-11-12 20:15:10 +00:00
fix(subtitles): strip X-TIMESTAMP-MAP so WebVTT cues are not offset on conversion
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
from unshackle.core.tracks.subtitle import Subtitle
|
||||
|
||||
|
||||
def test_strips_timestamp_map_keeps_cues():
|
||||
text = "WEBVTT\nX-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000\n\n00:00:22.690 --> 00:00:24.710\nHi\n"
|
||||
out = Subtitle.strip_webvtt_timestamp_map(text)
|
||||
assert "X-TIMESTAMP-MAP" not in out
|
||||
assert "00:00:22.690 --> 00:00:24.710" in out
|
||||
assert out.startswith("WEBVTT\n")
|
||||
|
||||
|
||||
def test_strips_lowercase_timestamp_map():
|
||||
# SubtitleEdit honours the header case-insensitively, so the strip must too
|
||||
text = "WEBVTT\nx-timestamp-map=MPEGTS:900000,LOCAL:00:00:00.000\n\n00:00:22.690 --> 00:00:24.710\nHi\n"
|
||||
out = Subtitle.strip_webvtt_timestamp_map(text)
|
||||
assert "x-timestamp-map" not in out.lower()
|
||||
assert "00:00:22.690 --> 00:00:24.710" in out
|
||||
|
||||
|
||||
def test_no_timestamp_map_is_untouched():
|
||||
text = "WEBVTT\n\n00:00:01.000 --> 00:00:02.000\nHi\n"
|
||||
assert Subtitle.strip_webvtt_timestamp_map(text) == text
|
||||
@@ -257,6 +257,7 @@ class Subtitle(Track):
|
||||
self.convert(Subtitle.Codec.WebVTT)
|
||||
elif self.codec == Subtitle.Codec.WebVTT:
|
||||
text = self.path.read_text("utf8")
|
||||
text = Subtitle.strip_webvtt_timestamp_map(text)
|
||||
if self.descriptor == Track.Descriptor.DASH:
|
||||
if len(self.data["dash"]["segment_durations"]) > 1:
|
||||
text = merge_segmented_webvtt(
|
||||
@@ -303,6 +304,17 @@ class Subtitle(Track):
|
||||
# Keep the sanitized version even if parsing failed
|
||||
self.path.write_text(text, encoding="utf8")
|
||||
|
||||
@staticmethod
|
||||
def strip_webvtt_timestamp_map(text: str) -> str:
|
||||
"""
|
||||
Remove X-TIMESTAMP-MAP header lines (RFC 8216 §3.5, HLS only).
|
||||
|
||||
Cue times are already absolute, but SubtitleEdit reads the header and offsets
|
||||
every cue by it during conversion.
|
||||
"""
|
||||
# IGNORECASE: SubtitleEdit matches the header case-insensitively, so must the strip
|
||||
return re.sub(r"^[ \t]*X-TIMESTAMP-MAP[^\n]*\n?", "", text, flags=re.MULTILINE | re.IGNORECASE)
|
||||
|
||||
@staticmethod
|
||||
def sanitize_webvtt_timestamps(text: str) -> str:
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user