import re
import io
-from .utils import int_or_none
+from .utils import int_or_none, timetuple_from_msec
from .compat import (
compat_str as str,
compat_Pattern,
))
+# While the specification <https://www.w3.org/TR/webvtt1/#webvtt-timestamp>
+# prescribes that hours must be *2 or more* digits, timestamps with a single
+# digit for the hour part has been seen in the wild.
+# See https://github.com/yt-dlp/yt-dlp/issues/921
_REGEX_TS = re.compile(r'''(?x)
- (?:([0-9]{2,}):)?
+ (?:([0-9]{1,}):)?
([0-9]{2}):
([0-9]{2})\.
([0-9]{3})?
Convert an MPEG PES timestamp into a WebVTT timestamp.
This will lose sub-millisecond precision.
"""
-
- ts = int((ts + 45) // 90)
- ms , ts = divmod(ts, 1000) # noqa: W504,E221,E222,E203
- s , ts = divmod(ts, 60) # noqa: W504,E221,E222,E203
- min, h = divmod(ts, 60) # noqa: W504,E221,E222
- return '%02u:%02u:%02u.%03u' % (h, min, s, ms)
+ return '%02u:%02u:%02u.%03u' % timetuple_from_msec(int((ts + 45) // 90))
class Block(object):
_REGEX_TSMAP = re.compile(r'X-TIMESTAMP-MAP=')
_REGEX_TSMAP_LOCAL = re.compile(r'LOCAL:')
_REGEX_TSMAP_MPEGTS = re.compile(r'MPEGTS:([0-9]+)')
+ _REGEX_TSMAP_SEP = re.compile(r'[ \t]*,[ \t]*')
@classmethod
def __parse_tsmap(cls, parser):
raise ParseError(parser)
else:
raise ParseError(parser)
- if parser.consume(','):
+ if parser.consume(cls._REGEX_TSMAP_SEP):
continue
if parser.consume(_REGEX_NL):
break
'settings': self.settings,
}
+ def __eq__(self, other):
+ return self.as_json == other.as_json
+
+ @classmethod
+ def from_json(cls, json):
+ return cls(
+ id=json['id'],
+ start=json['start'],
+ end=json['end'],
+ text=json['text'],
+ settings=json['settings']
+ )
+
+ def hinges(self, other):
+ if self.text != other.text:
+ return False
+ if self.settings != other.settings:
+ return False
+ return self.start <= self.end == other.start <= other.end
+
def parse_fragment(frag_content):
"""