{"record":{"id":"244bfea1b3790535","repo":"remotion-dev/remotion","slug":"pts-is-required","errorCode":null,"errorMessage":"PTS is required","messagePattern":"PTS is required","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/media-parser/src/containers/transport-stream/parse-pes.ts","lineNumber":58,"sourceCode":"\tconst ptsPresent = iterator.getBits(1);\n\tconst dtsPresent = iterator.getBits(1);\n\tif (!ptsPresent && dtsPresent) {\n\t\tthrow new Error(\n\t\t\t`DTS is present but not PTS, this is not allowed in the spec`,\n\t\t);\n\t}\n\n\titerator.getBits(1); // escr flag\n\titerator.getBits(1); // es rate flag\n\titerator.getBits(1); // dsm trick mode flag\n\titerator.getBits(1); // additional copy info flag\n\titerator.getBits(1); // crc flag\n\titerator.getBits(1); // extension flag\n\tconst pesHeaderLength = iterator.getBits(8);\n\tconst offsetAfterHeader = iterator.counter.getOffset();\n\tlet pts: number | null = null;\n\tif (!ptsPresent) {\n\t\tthrow new Error(`PTS is required`);\n\t}\n\n\tconst fourBits = iterator.getBits(4);\n\tif (fourBits !== 0b0011 && fourBits !== 0b0010) {\n\t\tthrow new Error(`Invalid PTS marker bits: ${fourBits}`);\n\t}\n\n\tconst pts1 = iterator.getBits(3);\n\titerator.getBits(1); // marker bit\n\tconst pts2 = iterator.getBits(15);\n\titerator.getBits(1); // marker bit\n\tconst pts3 = iterator.getBits(15);\n\titerator.getBits(1); // marker bit\n\tpts = (pts1 << 30) | (pts2 << 15) | pts3;\n\n\tlet dts: number | null = null;\n\tif (dtsPresent) {\n\t\tconst _fourBits = iterator.getBits(4);","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/media-parser/src/containers/transport-stream/parse-pes.ts#L40-L76","documentation":"Thrown at parse-pes.ts:58 when the PTS_DTS_flags indicate PTS is not present. Although the MPEG-TS spec allows PTS to be absent for some stream types, this library mandates PTS for every PES packet it processes so that timestamps can always be derived for samples.","triggerScenarios":"After reading ptsPresent/dtsPresent, parsePes checks !ptsPresent and throws. Triggered by streams that legitimately omit PTS (e.g. some padding streams, program_stream_map, or low-overhead private streams) or by corruption that clears the flag.","commonSituations":"Elementary streams with sparse PTS; private-stream PES packets; non-AV streams (e.g. DVB subtitles, teletext) routed through the AV path; partial captures where the flag byte is wrong.","solutions":["Re-mux with ffmpeg so every PES packet carries PTS: ffmpeg -i in.ts -c copy -mpegts_flags +resend_headers out.ts.","Filter out non-AV PIDs before parsing if only audio/video is needed.","Use a different source if the file is a damaged capture.","If the stream type is genuinely PTS-less, transcode to a container that always carries timestamps (e.g. MP4)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await parseMedia({src}); }\ncatch (e) {\n  if (e instanceof Error && e.message === 'PTS is required') {\n    // re-encode to force PTS on every PES packet\n    await runFfmpeg(['-i', src, '-c:v', 'libx264', '-c:a', 'aac', '-f', 'mpegts', out]);\n    await parseMedia({src: out});\n  } else throw e;\n}","preventionTips":["Filter out non-AV PIDs before parsing.","Re-encode streams that omit PTS to MP4 or remuxed MPEG-TS.","Avoid feeding private-stream/subtitle PES packets into the AV path."],"tags":["media-parser","transport-stream","mpegts","pes","pts"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}