remotion-dev/remotion · error · Error

PTS is required

Error message

PTS is required

What it means

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.

Source

Thrown at packages/media-parser/src/containers/transport-stream/parse-pes.ts:58

	const ptsPresent = iterator.getBits(1);
	const dtsPresent = iterator.getBits(1);
	if (!ptsPresent && dtsPresent) {
		throw new Error(
			`DTS is present but not PTS, this is not allowed in the spec`,
		);
	}

	iterator.getBits(1); // escr flag
	iterator.getBits(1); // es rate flag
	iterator.getBits(1); // dsm trick mode flag
	iterator.getBits(1); // additional copy info flag
	iterator.getBits(1); // crc flag
	iterator.getBits(1); // extension flag
	const pesHeaderLength = iterator.getBits(8);
	const offsetAfterHeader = iterator.counter.getOffset();
	let pts: number | null = null;
	if (!ptsPresent) {
		throw new Error(`PTS is required`);
	}

	const fourBits = iterator.getBits(4);
	if (fourBits !== 0b0011 && fourBits !== 0b0010) {
		throw new Error(`Invalid PTS marker bits: ${fourBits}`);
	}

	const pts1 = iterator.getBits(3);
	iterator.getBits(1); // marker bit
	const pts2 = iterator.getBits(15);
	iterator.getBits(1); // marker bit
	const pts3 = iterator.getBits(15);
	iterator.getBits(1); // marker bit
	pts = (pts1 << 30) | (pts2 << 15) | pts3;

	let dts: number | null = null;
	if (dtsPresent) {
		const _fourBits = iterator.getBits(4);

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Re-mux with ffmpeg so every PES packet carries PTS: ffmpeg -i in.ts -c copy -mpegts_flags +resend_headers out.ts.
  2. Filter out non-AV PIDs before parsing if only audio/video is needed.
  3. Use a different source if the file is a damaged capture.
  4. If the stream type is genuinely PTS-less, transcode to a container that always carries timestamps (e.g. MP4).
Defensive patterns

Strategy: try-catch

Try / catch

try { await parseMedia({src}); }
catch (e) {
  if (e instanceof Error && e.message === 'PTS is required') {
    // re-encode to force PTS on every PES packet
    await runFfmpeg(['-i', src, '-c:v', 'libx264', '-c:a', 'aac', '-f', 'mpegts', out]);
    await parseMedia({src: out});
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12). Data as JSON: /api/errors/244bfea1b3790535. Report an issue: GitHub.