remotion-dev/remotion · error · Error
Free bitrate not supported
Error message
Free bitrate not supported
What it means
Thrown while parsing an MP3 frame header when the 4-bit bitrate index decodes to the 'free' bitrate mode (index 0000). In MP3, 'free' means the bitrate is not encoded in the frame and must be derived from frame size; @remotion/media-parser declines to do that and rejects such files outright. The check happens in parse-packet-header.ts right after getBitrateKB returns the sentinel string 'free'.
Source
Thrown at packages/media-parser/src/containers/mp3/parse-packet-header.ts:224
throw new Error('Expected Layer I, II or III');
}
const layer = layerBits === 0b11 ? 1 : layerBits === 0b10 ? 2 : 3;
iterator.getBits(1); // 0b1 means that there is no CRC, 0b0 means there is. Not validating checksum though
const bitrateIndex = iterator.getBits(4);
const bitrateInKbit = getBitrateKB({
bits: bitrateIndex,
mpegVersion,
level: layer as Level,
});
if (bitrateInKbit === 'bad') {
throw new Error('Invalid bitrate');
}
if (bitrateInKbit === 'free') {
throw new Error('Free bitrate not supported');
}
const samplingFrequencyIndex = iterator.getBits(2);
const baseSampleRate = getSamplingFrequency({
bits: samplingFrequencyIndex,
mpegVersion,
});
const sampleRate =
audioVersionId === 0b00 ? baseSampleRate / 2 : baseSampleRate;
const padding = Boolean(iterator.getBits(1));
iterator.getBits(1); // private bit
const channelMode = iterator.getBits(2); // channel mode
iterator.getBits(2); // mode extension
iterator.getBits(1); // copyright
iterator.getBits(1); // original
iterator.getBits(2); // emphasis
View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Re-encode the MP3 with a standard fixed bitrate (e.g. 128/192/320 kbit) using a mainstream encoder like LAME or ffmpeg: ffmpeg -i input.mp3 -c:a libmp3lame -b:a 192k output.mp3
- If the file is valid free-format MP3 that you must support, pre-scan and reject it before passing to parseMediaStream so the error is handled upstream.
- Verify the file is actually MPEG audio and not a mislabeled container by checking the first frame sync (0xFFE/0xFFF) before invoking the parser.
Example fix
// before
await parseMediaStream({src: freeFormatMp3Url, fields: {durationInSeconds: true}});
// after: re-encode to a constrained-bitrate MP3 first
// ffmpeg -i input.mp3 -c:a libmp3lame -b:a 192k output.mp3
await parseMediaStream({src: 'output.mp3', fields: {durationInSeconds: true}}); Defensive patterns
Strategy: validation
Validate before calling
// Read the 4-bit bitrate index of the first MP3 frame and reject 'free' (index 0) up front.
function isFreeBitrateMp3(firstFrame: Uint8Array): boolean {
if (firstFrame.length < 4) return false;
const b2 = firstFrame[2];
const bitrateIndex = (b2 >> 4) & 0x0f;
return bitrateIndex === 0b0000; // 'free' bitrate
}
if (isFreeBitrateMp3(firstFrame)) {
throw new Error('Rejecting free-bitrate MP3 before parsing');
} Type guard
null
Try / catch
try {
await parseMediaStream({src: mp3Url, fields: {durationInSeconds: true}});
} catch (err) {
if (err instanceof Error && err.message === 'Free bitrate not supported') {
// re-encode to a fixed-bitrate MP3, then retry
} else throw err;
} Prevention
- Standardize all MP3 assets on a fixed bitrate (128/192/320 kbit) via ffmpeg libmp3lame.
- Pre-scan uploads for free-bitrate frames and reject or transcode them.
- Do not feed untrusted/experimental MP3s directly to parseMediaStream.
When it happens
Trigger: Parsing an MP3 whose frame header has bitrateIndex bits == 0b0000. Most common with files produced by experimental/old encoders (LAME --cbr with free-format, or custom encoders) or with the first frame being a non-MPEG filler.
Common situations: Hand-edited or truncated MP3s, free-format MP3 files, MP3s wrapped/transcoded by toolchains that emit free-bitrate frames, or random/corrupt data misidentified as MP3.
Related errors
- Unexpected audio object type ${audioObjectType}
- Only supporting MPEG-4 for .aac
- Unsupported level: ${level.toString(16)}
- Cannot determine timestamp
- MPEG Layer I is not supported
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/b37f2acd5b4d1b23.
Report an issue: GitHub.