{"record":{"id":"b1bddb5820ad10f0","repo":"nilaoda/N_m3u8DL-RE","slug":"missing-timescale-for-vtt-content","errorCode":null,"errorMessage":"Missing timescale for VTT content!","messagePattern":"Missing timescale for VTT content!","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/N_m3u8DL-RE.Parser/Mp4/MP4VttUtil.cs","lineNumber":39,"sourceCode":"                    throw new Exception(\"MDHD version can only be 0 or 1\");\n                timescale = MP4Parser.ParseMDHD(box.Reader, box.Version);\n            })\n            .Box(\"minf\", MP4Parser.Children)\n            .Box(\"stbl\", MP4Parser.Children)\n            .FullBox(\"stsd\", MP4Parser.SampleDescription)\n            .Box(\"wvtt\", _ => {\n                // A valid vtt init segment, though we have no actual subtitles yet.\n                sawWVTT = true;\n            })\n            .Parse(data);\n\n        return (sawWVTT, timescale);\n    }\n\n    public static WebVttSub ExtractSub(IEnumerable<string> files, uint timescale)\n    {\n        if (timescale == 0)\n            throw new Exception(\"Missing timescale for VTT content!\");\n\n        List<SubCue> cues = [];\n\n        foreach (var item in files)\n        {\n            var dataSeg = File.ReadAllBytes(item);\n\n            bool sawTFDT = false;\n            bool sawTRUN = false;\n            bool sawMDAT = false;\n            byte[]? rawPayload = null;\n            ulong baseTime = 0;\n            ulong defaultDuration = 0;\n            List<Sample> presentations = [];\n\n\n            // parse media\n            new MP4Parser()","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/nilaoda/N_m3u8DL-RE/blob/e113dee70c924ee08dae5460624909b04d84cb76/src/N_m3u8DL-RE.Parser/Mp4/MP4VttUtil.cs#L21-L57","documentation":"MP4VttUtil.ExtractSub converts per-segment media times to real timestamps using a timescale obtained from the init segment (CheckInit). If the caller passes timescale 0 — meaning CheckInit never found a usable mdhd/timescale — cues would get nonsensical timestamps, so ExtractSub refuses to proceed.","triggerScenarios":"Calling ExtractSub(files, timescale) with timescale == 0, typically because CheckInit returned (false, 0) — no wvtt sample description or no readable mdhd in the init segment — and the caller ignored that result.","commonSituations":"The 'file list' contains media segments whose init segment lacks a wvtt box or a parseable mdhd, the wrong init segment was parsed, or the caller hardcoded 0 instead of using the value returned by CheckInit.","solutions":["Make sure CheckInit is called on the correct init segment and its returned timescale is passed to ExtractSub.","Verify the init segment actually contains a wvtt sample entry (it must be a WebVTT-in-MP4 track).","If CheckInit returns sawWVTT == false / timescale 0, treat the stream as not being VTT-in-MP4 and use a different subtitle path.","Catch the exception and skip subtitle extraction instead of aborting the whole download."],"exampleFix":"// before\nvar (sawWvtt, timescale) = MP4VttUtil.CheckInit(initBytes);\nvar sub = MP4VttUtil.ExtractSub(segmentFiles, timescale); // throws when timescale==0\n\n// after\nvar (sawWvtt, timescale) = MP4VttUtil.CheckInit(initBytes);\nif (timescale == 0)\n{\n    Log.Warning(\"No timescale found; subtitle track is not WebVTT-in-MP4\");\n    return null;\n}\nvar sub = MP4VttUtil.ExtractSub(segmentFiles, timescale);","handlingStrategy":"validation","validationCode":"var (sawWvtt, timescale) = MP4VttUtil.CheckInit(initBytes);\nif (timescale == 0)\n    throw new InvalidDataException(\"No timescale in init segment; not a VTT-in-MP4 track\");\nMP4VttUtil.ExtractSub(segmentFiles, timescale);","typeGuard":null,"tryCatchPattern":"try { var sub = MP4VttUtil.ExtractSub(files, ts); }\ncatch (Exception ex) when (ex.Message.Contains(\"Missing timescale\"))\n{ /* skip subtitle extraction for this stream */ }","preventionTips":["Never hardcode 0 as timescale — always pass the value returned by CheckInit.","Check sawWvtt/timescale from CheckInit before proceeding to ExtractSub.","Verify the init segment contains a wvtt sample entry."],"tags":["mp4","webvtt","subtitle","validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"e113dee70c924ee08dae5460624909b04d84cb76","analyzedAt":"2026-09-13T02:43:21.078Z","contentChangedAt":"2026-09-13T02:43:21.078Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}