heygen-com/hyperframes · error
Unsupported input: ${ext}. Use a video (mp4/mov/webm/mkv/avi
Error message
Unsupported input: ${ext}. Use a video (mp4/mov/webm/mkv/avi) or image (jpg/png/webp). What it means
Thrown by inferInputKind() when the input file's extension matches neither VIDEO_EXTENSIONS (.mp4/.mov/.webm/.mkv/.avi) nor IMAGE_EXTENSIONS (.jpg/.jpeg/.png/.webp). The background-removal pipeline only accepts raster video or image inputs because it feeds raw RGB24 frames to an ONNX inference session. Any other extension (e.g. .gif, .tiff, .bmp, no extension, or a typo) is rejected before any ffmpeg probe runs.
Source
Thrown at packages/cli/src/background-removal/pipeline.ts:100
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;
}
async function probeMedia(inputPath: string): Promise<MediaInfo> {
const isImage = inferInputKind(inputPath) === "image";
const engine = (await import("@hyperframes/engine")) as {
extractMediaMetadata: (path: string) => Promise<EngineMetadata>;
};
const meta = await engine.extractMediaMetadata(inputPath);
View on GitHub (pinned to c2996c8626)
Solutions
- Convert the input to a supported format: video → .mp4/.mov/.webm, still → .png/.jpg/.webp (ffmpeg or an image tool).
- Check the file extension is spelled correctly and present: run `ls -la <inputPath>` and confirm the ext.
- If you genuinely need .gif, extract frames first: `ffmpeg -i in.gif -vsync 0 frame%04d.png` then pass a frame, or convert to mp4.
Example fix
// before
await render({ inputPath: 'clip.gif', outputPath: 'out.webm' });
// after (convert first)
// $ ffmpeg -i clip.gif -movflags faststart clip.mp4
await render({ inputPath: 'clip.mp4', outputPath: 'out.webm' }); Defensive patterns
Strategy: validation
Validate before calling
import { extname } from 'node:path';
const VIDEO = new Set(['.mp4','.mov','.webm','.mkv','.avi']);
const IMAGE = new Set(['.jpg','.jpeg','.png','.webp']);
function assertSupportedInput(p: string) {
const ext = extname(p).toLowerCase();
if (!VIDEO.has(ext) && !IMAGE.has(ext)) {
throw new Error(`Unsupported input extension ${ext}. Convert to mp4/mov/webm/mkv/avi (video) or jpg/png/webp (image).`);
}
}
assertSupportedInput(options.inputPath);
await render(options); Type guard
import { extname } from 'node:path';
function isSupportedInput(p: string): boolean {
const ext = extname(p).toLowerCase();
return new Set(['.mp4','.mov','.webm','.mkv','.avi','.jpg','.jpeg','.png','.webp']).has(ext);
} Prevention
- Validate the input extension with inferInputKind (or a mirror of it) before calling render().
- When building a CLI wrapper, surface the supported extension list in --help.
- Reject paths with no extension early in your own argument parsing.
When it happens
Trigger: Calling render() or resolveRenderTargets() with an inputPath whose extname is outside the two extension sets. Examples: input '/clip.gif', input 'photo.tiff', input 'frame' (no ext), or a typo like 'video.mp4' written as 'video.mp4 ' with a trailing space.
Common situations: User passes a .gif or .tiff thinking it is a supported image; a glob or shell expansion produced an unexpected file (e.g. a .txt sidecar); the path lost its extension during a rename; a case mismatch where the file is actually .MP4 but extname returns it correctly after toLowerCase (works) — real failures are unsupported formats or missing extensions.
Related errors
- 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
- --background-output must be .webm or .mov; .png is only vali
- ONNX session is missing input or output bindings
AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12).
Data as JSON: /api/errors/642499ce4a7c7327.
Report an issue: GitHub.