{"record":{"id":"b0b37b576a1f0c78","repo":"remotion-dev/remotion","slug":"the-input-does-not-contain-a-video-track","errorCode":null,"errorMessage":"The input does not contain a video track.","messagePattern":"The input does not contain a video track\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/video-matting/src/separate-video-layers.ts","lineNumber":258,"sourceCode":"\t\t\t: new BlobSource(src);\n\n\treturn new Input({formats: ALL_FORMATS, source});\n};\n\nconst probeVideoInput = async ({\n\tinput,\n\tvideoQuality,\n}: {\n\tinput: Input;\n\tvideoQuality: Quality;\n}): Promise<{videoTrack: InputVideoTrack; width: number; height: number}> => {\n\tif (!(await input.canRead())) {\n\t\tthrow new Error('The input is not a supported media file.');\n\t}\n\n\tconst videoTrack = await input.getPrimaryVideoTrack();\n\tif (videoTrack === null) {\n\t\tthrow new Error('The input does not contain a video track.');\n\t}\n\n\tif (!(await videoTrack.canDecode())) {\n\t\tthrow new Error('The primary video track cannot be decoded.');\n\t}\n\n\tconst [width, height] = await Promise.all([\n\t\tvideoTrack.getDisplayWidth(),\n\t\tvideoTrack.getDisplayHeight(),\n\t]);\n\tif (\n\t\t!Number.isInteger(width) ||\n\t\twidth <= 0 ||\n\t\t!Number.isInteger(height) ||\n\t\theight <= 0\n\t) {\n\t\tthrow new Error('The input video has invalid dimensions.');\n\t}","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/remotion-dev/remotion/blob/b2f4e34732f3c6c222ea029413e22dc402218cd7/packages/video-matting/src/separate-video-layers.ts#L240-L276","documentation":"The input was readable as a media container, but mediabunny's input.getPrimaryVideoTrack() returned null, meaning the container has no video track. Video layer separation requires video frames, so the library throws. This typically means the source is audio-only or the video track is in a separate stream.","triggerScenarios":"Calling separateVideoLayers on an MP3/M4A audio file, an audio-only WebM/MP4, or a media file whose video track was stripped during transcoding.","commonSituations":"Processing podcast/audio exports by mistake; a transcode pipeline that dropped video; HLS/DASH setups where only the audio segment was handed to the API.","solutions":["Check the file actually contains a video stream (e.g. `ffprobe <file>` shows a video: stream).","Point src at the video file, not the extracted audio file.","If the video track is genuinely missing, re-mux/re-encode the source to include video before calling."],"exampleFix":"// before\nawait separateVideoLayers({src: 'podcast-episode.m4a'});\n// after\nif (await hasVideoTrack('episode.mp4')) {\n  await separateVideoLayers({src: 'episode.mp4'});\n}","handlingStrategy":"validation","validationCode":"const input = new Input({source: new BlobSource(file), formats: ALL_FORMATS});\nconst track = await input.getPrimaryVideoTrack();\nif (!track) throw new Error('File has no video track — pick a video file');","typeGuard":null,"tryCatchPattern":"try {\n  await separateVideoLayers({src});\n} catch (e) {\n  if (e instanceof Error && e.message.includes('no video track')) {\n    showUserError('This file is audio-only. Select a file with video.');\n  } else throw e;\n}","preventionTips":["Filter uploads by MIME type video/* and probe tracks before processing.","Be explicit in docs/UI that audio-only files are unsupported."],"tags":["mediabunny","video-track","audio-only","input"],"backgroundTag":"resource-not-found","analyzedSha":"b2f4e34732f3c6c222ea029413e22dc402218cd7","analyzedAt":"2026-09-09T13:27:51.281Z","contentChangedAt":"2026-09-09T13:27:51.281Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}