remotion-dev/remotion · error

Only supporting MPEG-4 for .aac

Error message

Only supporting MPEG-4 for .aac

What it means

Thrown by parseAac when the MPEG 'ID' bit in an ADTS header is 1, meaning the stream is MPEG-2 (ISO 13818-7) rather than MPEG-4 (ISO 14496-3). The parser only supports MPEG-4 AAC, so it rejects MPEG-2 streams. This is a deliberate scope limitation of the @remotion/media-parser ADTS parser.

Source

Thrown at packages/media-parser/src/containers/aac/parse-aac.ts:24

import {convertAudioOrVideoSampleToWebCodecsTimestamps} from '../../convert-audio-or-video-sample';
import type {ParseResult} from '../../parse-result';
import {registerAudioTrack} from '../../register-track';
import type {ParserState} from '../../state/parser-state';
import {WEBCODECS_TIMESCALE} from '../../webcodecs-timescale';

export const parseAac = async (state: ParserState): Promise<ParseResult> => {
	const {iterator} = state;
	const startOffset = iterator.counter.getOffset();

	iterator.startReadingBits();
	const syncWord = iterator.getBits(12);
	if (syncWord !== 0xfff) {
		throw new Error('Invalid syncword: ' + syncWord);
	}

	const id = iterator.getBits(1);
	if (id !== 0) {
		throw new Error('Only supporting MPEG-4 for .aac');
	}

	const layer = iterator.getBits(2);
	if (layer !== 0) {
		throw new Error('Only supporting layer 0 for .aac');
	}

	const protectionAbsent = iterator.getBits(1); // protection absent
	const audioObjectType = iterator.getBits(2); // 1 = 'AAC-LC'

	const samplingFrequencyIndex = iterator.getBits(4);
	const sampleRate = getSampleRateFromSampleFrequencyIndex(
		samplingFrequencyIndex,
	);
	iterator.getBits(1); // private bit
	const channelConfiguration = iterator.getBits(3);
	const codecPrivate = createAacCodecPrivate({
		audioObjectType,

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Re-encode to MPEG-4 AAC: `ffmpeg -i input.aac -c:a aac -f adts output.aac` (ffmpeg defaults to MPEG-4 ID).
  2. Switch to Mediabunny (https://www.remotion.dev/docs/mediabunny/metadata) which may support MPEG-2 AAC.
  3. If you cannot re-encode, use ffprobe to extract metadata instead of @remotion/media-parser.
  4. Report the file to the Remotion team to gauge whether MPEG-2 support is worth adding.
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check: verify MPEG-4 ID bit (bit 12 of ADTS header is 0)
async function isMpeg4Adts(filePath: string): Promise<boolean> {
  const buf = await readFile(filePath);
  if (buf.length < 2) return false;
  // Byte 1, bit 3 (0-indexed from MSB) = ID bit; should be 0 for MPEG-4
  return (buf[1] & 0x08) === 0x00;
}

Try / catch

try {
  const result = await parseMedia({src, fields: {/* ... */}});
} catch (e) {
  if (e instanceof Error && e.message === 'Only supporting MPEG-4 for .aac') {
    console.error('File is MPEG-2 AAC. Re-encode: ffmpeg -i input.aac -c:a aac -f adts output.aac');
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Parsing a .aac file whose ADTS frames carry the MPEG-2 ID bit set (id=1). This occurs with legacy MPEG-2 AAC files or files produced by older encoders that default to MPEG-2 transport.

Common situations: Legacy audio files encoded with old tools (e.g. early FAAD/FAAC builds) that default to MPEG-2 AAC. Files from older broadcast or telephony systems. Some test suites still ship MPEG-2 AAC samples.

Related errors


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