remotion-dev/remotion · error

Invalid AAC codec private length

Error message

Invalid AAC codec private length

What it means

Thrown by parseAacCodecPrivate() when the supplied AAC codec-private byte array has fewer than 2 bytes. The parser needs at least 2 bytes (16 bits) to decode the audioObjectType (5 bits), samplingFrequencyIndex (4 bits), and channelConfiguration (4 bits) fields that form the minimal AAC AudioSpecificConfig. Any codec private data shorter than this is structurally invalid and cannot represent a real AAC stream.

Source

Thrown at packages/media-parser/src/aac-codecprivate.ts:144

	const bits = `${audioObjectType.toString(2).padStart(5, '0')}${getConfigForSampleRate(sampleRate).toString(2).padStart(4, '0')}${channelConfiguration.toString(2).padStart(4, '0')}000`;
	if (bits.length !== 16) {
		throw new Error('Invalid AAC codec private ' + bits.length);
	}

	if (channelConfiguration === 0 || channelConfiguration > 7) {
		throw new Error('Invalid channel configuration ' + channelConfiguration);
	}

	const firstByte = parseInt(bits.slice(0, 8), 2);
	const secondByte = parseInt(bits.slice(8, 16), 2);

	return new Uint8Array([firstByte, secondByte]);
};

export const parseAacCodecPrivate = (bytes: Uint8Array) => {
	if (bytes.length < 2) {
		throw new Error('Invalid AAC codec private length');
	}

	const bits = [...bytes].map((b) => b.toString(2).padStart(8, '0')).join('');

	let offset = 0;
	const audioObjectType = parseInt(bits.slice(offset, offset + 5), 2);
	offset += 5;

	const samplingFrequencyIndex = parseInt(bits.slice(offset, offset + 4), 2);
	offset += 4;

	if (samplingFrequencyIndex === 0xf) {
		offset += 24;
	}

	const channelConfiguration = parseInt(bits.slice(offset, offset + 4), 2);
	offset += 4;

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Validate the media file integrity by re-muxing it with ffmpeg: `ffmpeg -i input.mp4 -c copy output.mp4` to repair the codec private data.
  2. If you control the caller, guard with `if (bytes.length >= 2) { parseAacCodecPrivate(bytes); }` before invoking the parser.
  3. Switch from the deprecated @remotion/media-parser to Mediabunny (https://www.remotion.dev/docs/mediabunny/metadata) which may handle the malformed input more gracefully.
  4. Report the file as a bug to the Remotion team with the reproducer if the file plays correctly in standard players like VLC or ffprobe.

Example fix

// before
import {parseAacCodecPrivate} from '@remotion/media-parser';
const info = parseAacCodecPrivate(track.codecPrivate); // throws if < 2 bytes

// after
import {parseAacCodecPrivate} from '@remotion/media-parser';
if (track.codecPrivate && track.codecPrivate.length >= 2) {
  const info = parseAacCodecPrivate(track.codecPrivate);
} else {
  throw new Error(`Track has invalid AAC codec private: ${track.codecPrivate?.length ?? 0} bytes`);
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate codec private length before parsing
function hasValidAacCodecPrivate(bytes: Uint8Array | null | undefined): bytes is Uint8Array {
  return bytes instanceof Uint8Array && bytes.length >= 2;
}

// Usage:
if (hasValidAacCodecPrivate(track.codecPrivate)) {
  const info = parseAacCodecPrivate(track.codecPrivate);
} else {
  console.warn('Skipping track: AAC codec private too short');
}

Type guard

function isParseableAacCodecPrivate(bytes: unknown): bytes is Uint8Array {
  return bytes instanceof Uint8Array && bytes.length >= 2;
}

Try / catch

try {
  const info = parseAacCodecPrivate(bytes);
} catch (e) {
  if (e instanceof Error && e.message === 'Invalid AAC codec private length') {
    // Handle truncated codec private data
    console.warn('AAC codec private data is too short, skipping track');
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling parseAacCodecPrivate() (or parseMedia on a file whose track carries AAC codec data) where the codec-private bytes array has length 0 or 1. This happens when an MP4/Matroska/WebM container stores an empty or truncated CodecPrivate element for an AAC audio track, or when an internal caller passes a zero-length Uint8Array.

Common situations: Corrupt or partially downloaded media files where the AAC track's esds/CodecPrivate box is truncated. Hand-crafted or test fixtures with missing codec data. Files produced by buggy muxers that write a placeholder empty CodecPrivate for AAC tracks. Files misidentified as AAC that are actually another codec.

Related errors


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