Repository: yt-dlp/yt-dlp

Issue:
[Broken] webvtt parser error in PBS subtitles
Ok so using the same link as when I created this issue I added the `--write-subs` flag and got this as output
```
[debug] Command-line config: ['https://www.pbs.org/video/in-the-shadow-of-911-wkijvb/', '--write-subs', '--verbose']
[debug] Encodings: locale cp1252, fs utf-8, out utf-8, pref cp1252
[debug] yt-dlp version 2021.09.02 (exe)
[debug] Python version 3.9.5 (CPython 64bit) - Windows-10-10.0.19043-SP0
[debug] exe versions: ffmpeg 4.4-full_build-www.gyan.dev, ffprobe 4.4-full_build-www.gyan.dev
[debug] Optional libraries: mutagen, pycryptodome, sqlite, websockets
[debug] Proxy map: {}
[debug] Using fake IP 6.44.180.11 (US) as X-Forwarded-For
[pbs] Downloading JSON metadata
[debug] [pbs] Extracting URL: https://www.pbs.org/video/in-the-shadow-of-911-wkijvb/
[pbs] in-the-shadow-of-911-wkijvb: Downloading webpage
[pbs] in-the-shadow-of-911-wkijvb: Downloading widget/partnerplayer page
[pbs] in-the-shadow-of-911-wkijvb: Downloading portalplayer page
[pbs] in-the-shadow-of-911-wkijvb: Downloading 0 video url info
[pbs] in-the-shadow-of-911-wkijvb: Downloading m3u8 information
[pbs] in-the-shadow-of-911-wkijvb: Downloading 1 video url info
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, vcodec:vp9.2(10), acodec, filesize, fs_approx, tbr, vbr, abr, asr, proto, vext, aext, hasaud, source, id
[debug] Downloading subtitles: en
[debug] Default format spec: bestvideo*+bestaudio/best
[info] 3057558971: Downloading 1 format(s): hls-6906
[info] Writing video subtitles to: FRONTLINE - In the Shadow of 9_11 [3057558971].en.vtt
[debug] Invoking downloader on "https://ga.video.cdn.pbs.org/videos/frontline/f216432b-e95e-468c-adbf-0bf69a9ecbeb/2000247732/hd-16x9-mezzanine-1080p/00004007-captions.m3u8"
[hlsnative] Downloading m3u8 manifest
[hlsnative] Total fragments: 38
[download] Destination: FRONTLINE - In the Shadow of 9_11 [3057558971].en.vtt
[download]   2.6% of ~112.89KiB at Unknown speed ETA 00:03ERROR: Parse error at position 37 (near ' LOCAL:00:00:00.000\n')
Traceback (most recent call last):
  File "yt_dlp\YoutubeDL.py", line 1218, in wrapper
  File "yt_dlp\YoutubeDL.py", line 1256, in __extract_info
  File "yt_dlp\YoutubeDL.py", line 1306, in process_ie_result
  File "yt_dlp\YoutubeDL.py", line 2332, in process_video_result
  File "yt_dlp\YoutubeDL.py", line 2588, in process_info
  File "yt_dlp\YoutubeDL.py", line 2473, in dl
  File "yt_dlp\downloader\common.py", line 386, in download
  File "yt_dlp\downloader\hls.py", line 344, in real_download
  File "yt_dlp\downloader\fragment.py", line 423, in download_and_append_fragments
  File "yt_dlp\downloader\fragment.py", line 401, in append_fragment
  File "yt_dlp\downloader\hls.py", line 259, in pack_fragment
  File "yt_dlp\webvtt.py", line 363, in parse_fragment
  File "yt_dlp\webvtt.py", line 217, in parse
  File "yt_dlp\webvtt.py", line 196, in __parse_tsmap
yt_dlp.webvtt.ParseError: Parse error at position 37 (near ' LOCAL:00:00:00.000\n')
```

_Originally posted by @faizjamil in https://github.com/yt-dlp/yt-dlp/issues/836#issuecomment-914876831_


Discussion:

Resolving patch:
diff --git a/yt_dlp/webvtt.py b/yt_dlp/webvtt.py
--- a/yt_dlp/webvtt.py
+++ b/yt_dlp/webvtt.py
@@ -89,8 +89,12 @@ def __init__(self, parser):
         ))
 
 
+# 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})?
@@ -172,6 +176,7 @@ class Magic(HeaderBlock):
     _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):
@@ -194,7 +199,7 @@ 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


Test patch: