{"record":{"id":"f936906fd582330d","repo":"heygen-com/hyperframes","slug":"video-input-requires-a-webm-or-mov-output-got","errorCode":null,"errorMessage":"Video input requires a .webm or .mov output (got .png). Use an image input for .png.","messagePattern":"Video input requires a \\.webm or \\.mov output \\(got \\.png\\)\\. Use an image input for \\.png\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cli/src/background-removal/pipeline.ts","lineNumber":246,"sourceCode":"/**\n * Resolve and validate the input/output combination before any I/O. Pure;\n * exported so unit tests can pin the error messages without spawning ffmpeg.\n */\nexport function resolveRenderTargets(\n  inputPath: string,\n  outputPath: string,\n  backgroundOutputPath?: string,\n): RenderTargets {\n  const format = inferOutputFormat(outputPath);\n  const inputKind = inferInputKind(inputPath);\n\n  if (inputKind === \"image\" && format !== \"png\") {\n    throw new Error(\n      `Image input requires a .png output (got ${extname(outputPath)}). Use a video input for .webm/.mov.`,\n    );\n  }\n  if (inputKind === \"video\" && format === \"png\") {\n    throw new Error(\n      `Video input requires a .webm or .mov output (got .png). Use an image input for .png.`,\n    );\n  }\n\n  let bgFormat: OutputFormat | undefined;\n  if (backgroundOutputPath) {\n    if (inputKind === \"image\") {\n      throw new Error(\n        \"--background-output is not supported for image inputs. Use a video input (mp4/mov/webm) to produce both a cutout and a background plate.\",\n      );\n    }\n    bgFormat = inferOutputFormat(backgroundOutputPath);\n    if (bgFormat === \"png\") {\n      throw new Error(\n        \"--background-output must be .webm or .mov; .png is only valid for single-image inputs.\",\n      );\n    }\n  }","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/background-removal/pipeline.ts#L228-L264","documentation":"Thrown by resolveRenderTargets() when a video input is paired with a .png output. PNG output is a single still with alpha; a video has many frames, so encoding it to one PNG would silently drop all but one frame. The guard rejects the combination up front rather than producing a misleading single-frame result.","triggerScenarios":"Calling render({ inputPath: 'clip.mp4', outputPath: 'frame.png' }) — any video input with a .png output path. resolveRenderTargets detects (video, format===png).","commonSituations":"User wants the first frame as a PNG but the API is not designed for that (use ffmpeg directly); a pipeline template hardcodes .png outputs; confusion between the still-image and video modes of the tool.","solutions":["Use a .webm or .mov output for video inputs to get the per-frame alpha matte.","If you only need one PNG from a video, extract it directly with ffmpeg: `ffmpeg -i clip.mp4 -frames:v 1 frame.png`.","Switch the input to a single image if you truly want a .png cutout."],"exampleFix":"// before\nawait render({ inputPath: 'clip.mp4', outputPath: 'clip.png' });\n// after\nawait render({ inputPath: 'clip.mp4', outputPath: 'clip.webm' });","handlingStrategy":"validation","validationCode":"function assertVideoOutputNotPng(inputPath: string, outputPath: string) {\n  const inExt = extname(inputPath).toLowerCase();\n  const isVideo = ['.mp4','.mov','.webm','.mkv','.avi'].includes(inExt);\n  const outExt = extname(outputPath).toLowerCase();\n  if (isVideo && outExt === '.png') {\n    throw new Error('Video input requires .webm or .mov output; use an image input for .png.');\n  }\n}\nassertVideoOutputNotPng(options.inputPath, options.outputPath);\nawait render(options);","typeGuard":"function isVideoPngMismatch(inputPath: string, outputPath: string): boolean {\n  const isVideo = ['.mp4','.mov','.webm','.mkv','.avi'].includes(extname(inputPath).toLowerCase());\n  return isVideo && extname(outputPath).toLowerCase() === '.png';\n}","tryCatchPattern":null,"preventionTips":["Never pair a video input with a .png output in templates.","For first-frame PNG extraction, use ffmpeg directly instead of the background-removal API.","Add a pre-flight assertion in your render orchestrator."],"tags":["validation","format-mismatch","background-removal","pre-io"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}