remotion-dev/remotion · error · Error

no video and no audio tracks

Error message

no video and no audio tracks

What it means

Thrown by getSeekingByteFromFragmentedMp4 when the `tracks` array contains neither a track with type 'video' nor one with type 'audio'. The function picks firstVideoTrack then falls back to first audio track; if both lookups miss, there is nothing to seek on. This is fundamentally a state bug: the parser reached seek resolution without having registered any playable track.

Source

Thrown at packages/media-parser/src/containers/iso-base-media/get-seeking-byte-from-fragmented-mp4.ts:52

	mp4HeaderSegment,
}: {
	info: IsoBaseMediaSeekingHints;
	time: number;
	logLevel: MediaParserLogLevel;
	currentPosition: number;
	isoState: IsoBaseMediaState;
	structure: StructureState;
	tracks: MediaParserTrack[];
	isLastChunkInPlaylist: boolean;
	mp4HeaderSegment: IsoBaseMediaStructure | null;
}): Promise<SeekResolution> => {
	const firstVideoTrack = tracks.find((t) => t.type === 'video');

	// If there is both video and audio, seek based on video, but if not then audio is also okay
	const firstTrack = firstVideoTrack ?? tracks.find((t) => t.type === 'audio');

	if (!firstTrack) {
		throw new Error('no video and no audio tracks');
	}

	const moov = getMoovBoxFromState({
		structureState: structure,
		isoState,
		mp4HeaderSegment,
		mayUsePrecomputed: true,
	});
	if (!moov) {
		throw new Error('No moov atom found');
	}

	const trakBox = getTrakBoxByTrackId(moov, firstTrack.trackId);

	if (!trakBox) {
		throw new Error('No trak box found');
	}

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Defer seeking until at least one video or audio track has been registered (wait for onVideoTrack/onAudioTrack).
  2. Inspect the file's tracks with `ffprobe -show_streams` and confirm it has a video or audio stream.
  3. If the file legitimately has only metadata tracks, do not attempt media seeking.
  4. Re-mux to ensure the moov declares standard video/audio traks.

Example fix

// before
await parser.seek(timeInSeconds);

// after
if (!tracks.some((t) => t.type === 'video' || t.type === 'audio')) {
  throw new Error('No playable track — waiting for track registration or file has only metadata tracks');
}
await parser.seek(timeInSeconds);
Defensive patterns

Strategy: validation

Validate before calling

import type {MediaParserTrack} from '../../get-tracks';
function hasPlayableTrack(tracks: MediaParserTrack[]): boolean {
  return tracks.some((t) => t.type === 'video' || t.type === 'audio');
}

Type guard

import type {MediaParserTrack} from '../../get-tracks';
function hasMediaTrack(tracks: MediaParserTrack[]): boolean {
  return tracks.some((t) => t.type === 'video' || t.type === 'audio');
}

Try / catch

try {
  await parser.seek(time);
} catch (err) {
  if (/no video and no audio tracks/i.test(String(err?.message))) {
    // Defer seek until at least one media track is registered
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: Reached during fragmented MP4 seek when state.tracks has no video and no audio entries — e.g. only 'other' tracks (timed metadata, hint tracks), or the tracks array was emptied/reset before seek. Also reachable if track.type uses an unexpected value due to a parser change.

Common situations: MP4 with only hint or metadata tracks (rare for consumer media). A bug in track registration that never produces video/audio tracks. Calling seek before any onVideoTrack/onAudioTrack callback has fired. Streams where the moov declares only subtitle/metadata traks.

Related errors


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