Test files › Subtitles and captions › comma-separator.vtt

Sample WebVTT file (comma separator)

WebVTT that uses the SRT comma decimal separator in its timestamps instead of a full stop.

↓ Download comma-separator.vtt
Filenamecomma-separator.vtt
FormatWebVTT
Size176 bytes (176 bytes)
MIME typetext/vtt; charset=utf-8
SHA-2564750082833b28bd77e218973efbe11e0b9a9763ae226c99a24ecb0a20f9c8d6b
What this file catchesThe classic result of renaming a .srt to .vtt. The signature is present and the structure looks right, so a lenient parser may accept it, but the timestamps are invalid WebVTT and cues are commonly dropped or mistimed rather than reported as an error.

Handle it in code

Each snippet below was run against this exact file with Python 3.14.4 and Node 24.15.0 when this page was built, and the output shown is what it printed.

Python

SRT puts a comma before the milliseconds and WebVTT a full stop, and WebVTT files must start with WEBVTT. Players differ on the rest: overlapping cues are legal in WebVTT, but many SRT players show only one of them.

import re

TIME = r"(?:(\d+):)?(\d{2}):(\d{2})([.,])(\d{3})"
CUE = re.compile(TIME + r"\s+-->\s+" + TIME)

def ms(h, m, s, sep, frac):
    return ((int(h or 0) * 60 + int(m)) * 60 + int(s)) * 1000 + int(frac)

name = "comma-separator.vtt"
vtt = name.lower().endswith(".vtt")
with open(name, encoding="utf-8-sig") as f:
    text = f.read()
problems, cues = [], []
if vtt and not text.startswith("WEBVTT"):
    problems.append("line 1: no WEBVTT signature")
for n, line in enumerate(text.splitlines(), 1):
    m = CUE.search(line)
    if not m:
        continue
    g = m.groups()
    right = "." if vtt else ","
    if g[3] != right or g[8] != right:
        problems.append(f"line {n}: {'WebVTT' if vtt else 'SRT'} needs {right!r} before the milliseconds")
    start, end = ms(*g[:5]), ms(*g[5:])
    if end < start:
        problems.append(f"line {n}: the cue ends before it starts")
    elif end == start:
        problems.append(f"line {n}: zero length, so it never shows")
    if cues:
        prev_start, prev_end = cues[-1]
        if start < prev_start:
            problems.append(f"line {n}: starts before the previous cue (out of order)")
        overlap = min(end, prev_end) - max(start, prev_start)
        if overlap > 0:
            problems.append(f"line {n}: overlaps the previous cue by {overlap} ms")
    cues.append((start, end))
print(f"{len(cues)} cues:", "valid" if not problems else f"{len(problems)} problem{'s' * (len(problems) != 1)}")
for p in problems:
    print("  " + p)

Run against this file, it prints: 2 cues: 2 problems line 3: WebVTT needs '.' before the milliseconds line 6: WebVTT needs '.' before the milliseconds

Related guides and tools

Character encodingsVerify its SHA-256

Download & verify

curl -fsSL -o "comma-separator.vtt" "https://files.hexaqa.com/subtitle/comma-separator.vtt"
curl -fsSL "https://files.hexaqa.com/subtitle/comma-separator.vtt" | sha256sum # expect: 4750082833b28bd77e218973efbe11e0b9a9763ae226c99a24ecb0a20f9c8d6b

More subtitles and captions test files

missing-signature.vttoverlapping-cues.srtvalid.srtvalid.vtt

← All Subtitles and captions files