heygen-com/hyperframes · error
Unsupported output extension: ${ext}. Use .webm (VP9 alpha),
Error message
Unsupported output extension: ${ext}. Use .webm (VP9 alpha), .mov (ProRes 4444), or .png. What it means
Thrown by inferOutputFormat when the output path's extension is not one of .webm, .mov, or .png (case-insensitive). The background-removal pipeline only produces alpha-capable outputs: VP9-with-alpha (.webm), ProRes 4444 (.mov), or a single RGBA still (.png). Formats without an alpha channel (.mp4, .avi, .mkv) are rejected here because the matte cannot be represented. Called by resolveRenderTargets at the start of render, before any ffmpeg spawn.
Source
Thrown at packages/cli/src/background-removal/pipeline.ts:91
format: OutputFormat;
}
const VIDEO_EXTENSIONS = new Set([".mp4", ".mov", ".webm", ".mkv", ".avi"]);
const IMAGE_EXTENSIONS = new Set([".jpg", ".jpeg", ".png", ".webp"]);
interface MediaInfo {
width: number;
height: number;
fps: number;
frameCount: number;
}
export function inferOutputFormat(outputPath: string): OutputFormat {
const ext = extname(outputPath).toLowerCase();
if (ext === ".webm") return "webm";
if (ext === ".mov") return "mov";
if (ext === ".png") return "png";
throw new Error(
`Unsupported output extension: ${ext}. Use .webm (VP9 alpha), .mov (ProRes 4444), or .png.`,
);
}
export function inferInputKind(inputPath: string): "video" | "image" {
const ext = extname(inputPath).toLowerCase();
if (VIDEO_EXTENSIONS.has(ext)) return "video";
if (IMAGE_EXTENSIONS.has(ext)) return "image";
throw new Error(
`Unsupported input: ${ext}. Use a video (mp4/mov/webm/mkv/avi) or image (jpg/png/webp).`,
);
}
interface EngineMetadata {
width: number;
height: number;
fps: number;
durationSeconds: number;View on GitHub (pinned to c2996c8626)
Solutions
- Use .webm for browser-targeted alpha video, .mov for editing round-trips (ProRes 4444), or .png for a single still.
- Do NOT use .mp4 — H.264/H.265 have no standardized alpha channel.
- If a matte-free output is acceptable, run the source through a standard transcode instead of background removal.
- Ensure backgroundOutputPath (if set) is .webm or .mov, not .png.
Example fix
// before
render({ inputPath: 'clip.mp4', outputPath: 'out.mp4' }); // throws
// after
render({ inputPath: 'clip.mp4', outputPath: 'out.webm' }); // VP9 alpha Defensive patterns
Strategy: validation
Validate before calling
import { extname } from 'node:path';
const ALPHA_OUTPUTS = new Set(['.webm', '.mov', '.png']);
function assertAlphaOutput(outputPath: string): void {
if (!ALPHA_OUTPUTS.has(extname(outputPath).toLowerCase())) {
throw new Error(`output must be .webm/.mov/.png, got ${extname(outputPath)}`);
}
} Type guard
import { extname } from 'node:path';
const isAlphaOutput = (p: string): boolean =>
['.webm', '.mov', '.png'].includes(extname(p).toLowerCase()); Prevention
- Default background-removal outputs to .webm (browser alpha) or .mov (editor alpha).
- Never use .mp4 — it has no alpha channel.
- If a backgroundOutputPath is set, ensure it is .webm or .mov (not .png).
When it happens
Trigger: Passing an outputPath ending in .mp4, .avi, .mkv, .gif, or with no extension; an uppercase extension is handled (lowercased) but .MP4 is still rejected as unsupported. Also fires for backgroundOutputPath if its extension isn't .webm/.mov.
Common situations: Defaulting the output to .mp4 (the common video format) without realizing background removal needs alpha; a user typing .mov for input and .mp4 for output; missing extension from a path built by string concatenation.
Related errors
- ONNX session is missing input or output bindings
- Unsupported input: ${ext}. Use a video (mp4/mov/webm/mkv/avi
- Image input requires a .png output (got ${extname(outputPath
- Video input requires a .webm or .mov output (got .png). Use
- --background-output is not supported for image inputs. Use a
AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12).
Data as JSON: /api/errors/0e9f04e126998248.
Report an issue: GitHub.