remotion-dev/remotion · error · Error

Cannot get duration of VBR MP3 file - no frames

Error message

Cannot get duration of VBR MP3 file - no frames

What it means

Thrown by `getDurationFromMp3Xing` when computing the duration of a variable-bitrate (VBR) MP3 file from its Xing header, but `xingData.numberOfFrames` is zero or falsy. The Xing/VBR header's frame count field is required to compute duration; without it the calculation is impossible.

Source

Thrown at packages/media-parser/src/containers/mp3/get-duration.ts:15

import type {ParserState} from '../../state/parser-state';
import {getMpegFrameLength} from './get-frame-length';
import type {XingData} from './parse-xing';
import {getSamplesPerMpegFrame} from './samples-per-mpeg-file';

export const getDurationFromMp3Xing = ({
	xingData,
	samplesPerFrame,
}: {
	xingData: XingData;
	samplesPerFrame: number;
}) => {
	const xingFrames = xingData.numberOfFrames;
	if (!xingFrames) {
		throw new Error('Cannot get duration of VBR MP3 file - no frames');
	}

	const {sampleRate} = xingData;
	if (!sampleRate) {
		throw new Error('Cannot get duration of VBR MP3 file - no sample rate');
	}

	const xingSamples = xingFrames * samplesPerFrame;
	return xingSamples / sampleRate;
};

export const getDurationFromMp3 = (state: ParserState): number | null => {
	const mp3Info = state.mp3.getMp3Info();
	const mp3BitrateInfo = state.mp3.getMp3BitrateInfo();
	if (!mp3Info || !mp3BitrateInfo) {
		return null;
	}

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Re-encode the MP3 file with a standard encoder (e.g., LAME) that writes a complete Xing header.
  2. Try converting the file to CBR MP3 to avoid the VBR/Xing path entirely.
  3. If the file is user-supplied, validate it with an audio tool (e.g., `ffprobe`) before parsing.
  4. Wrap `parseMedia` in a try-catch and fall back to a different file or format.
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate an MP3 file's Xing header before parsing
async function hasValidXingFrames(file: File): Promise<boolean> {
  const buf = await file.slice(0, 4096).arrayBuffer();
  const bytes = new Uint8Array(buf);
  const text = new TextDecoder().decode(bytes);
  const xingIdx = text.indexOf('Xing');
  if (xingIdx === -1) return true; // not VBR, no issue
  // Xing flags + frame count are at xingIdx+4 (flags) and xingIdx+8 (frames)
  if (xingIdx + 12 > bytes.length) return false;
  const view = new DataView(buf, xingIdx + 8, 4);
  return view.getUint32(0) > 0;
}

Try / catch

try {
  await parseMedia({src, fields: {durationInSeconds: true}});
} catch (e) {
  if (e instanceof Error && e.message.includes('no frames')) {
    console.error('The VBR MP3 has a corrupt Xing header with no frame count.');
    // Re-encode or use a different file
  }
  throw e;
}

Prevention

When it happens

Trigger: An MP3 file with a Xing header where the `numberOfFrames` field is 0 or missing. The `parseXing` function parsed the header successfully but the frame-count bytes were zero, indicating a corrupt or incomplete Xing table of contents.

Common situations: Corrupt or truncated MP3 files with a damaged Xing header. Files produced by encoders that write a Xing marker but don't populate the frame count. Files that have been concatenated or re-tagged in ways that corrupt the VBR header region.

Related errors


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