mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-14 18:01:20 +08:00
d2ca45ef75
Adds `hyperframes remove-background` — a local-AI subcommand that mattes a video or image with the u2net_human_seg ONNX model and emits a transparent WebM (VP9-alpha), ProRes 4444 .mov, or RGBA PNG. Drops directly into any composition's <video> tag — no green screen, no API keys, no upload. Auto-picks the fastest available execution provider via onnxruntime-node: CoreML on Apple Silicon, CUDA when HYPERFRAMES_CUDA=1, CPU otherwise. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
97 lines
3.2 KiB
TypeScript
97 lines
3.2 KiB
TypeScript
import { existsSync, mkdirSync } from "node:fs";
|
|
import { homedir, platform, arch } from "node:os";
|
|
import { join } from "node:path";
|
|
import { downloadFile } from "../utils/download.js";
|
|
|
|
export const MODELS_DIR = join(homedir(), ".cache", "hyperframes", "background-removal", "models");
|
|
|
|
export const DEFAULT_MODEL = "u2net_human_seg" as const;
|
|
export type ModelId = typeof DEFAULT_MODEL;
|
|
|
|
const MODEL_URLS: Record<ModelId, string> = {
|
|
u2net_human_seg:
|
|
"https://github.com/danielgatis/rembg/releases/download/v0.0.0/u2net_human_seg.onnx",
|
|
};
|
|
|
|
export const MODEL_MEMORY_MB: Record<ModelId, number> = {
|
|
u2net_human_seg: 1500,
|
|
};
|
|
|
|
export const DEVICES = ["auto", "cpu", "coreml", "cuda"] as const;
|
|
export type Device = (typeof DEVICES)[number];
|
|
|
|
export function isDevice(value: unknown): value is Device {
|
|
return typeof value === "string" && (DEVICES as readonly string[]).includes(value);
|
|
}
|
|
|
|
export interface ProviderChoice {
|
|
providers: string[];
|
|
label: "CoreML" | "CUDA" | "CPU";
|
|
}
|
|
|
|
export function selectProviders(device: Device = "auto"): ProviderChoice {
|
|
if (device === "cpu") return { providers: ["cpu"], label: "CPU" };
|
|
|
|
const available = listAvailableProviders();
|
|
const hasCoreML = available.includes("coreml");
|
|
const hasCUDA = available.includes("cuda");
|
|
|
|
if (device === "coreml") {
|
|
if (!hasCoreML) {
|
|
throw new Error(
|
|
"CoreML execution provider not available. Install onnxruntime-node on Apple Silicon, or use --device cpu.",
|
|
);
|
|
}
|
|
return { providers: ["coreml", "cpu"], label: "CoreML" };
|
|
}
|
|
if (device === "cuda") {
|
|
if (!hasCUDA) {
|
|
throw new Error(
|
|
"CUDA execution provider not available. Use --device cpu or install an onnxruntime-node build with CUDA support.",
|
|
);
|
|
}
|
|
return { providers: ["cuda", "cpu"], label: "CUDA" };
|
|
}
|
|
|
|
if (hasCoreML && platform() === "darwin" && arch() === "arm64") {
|
|
return { providers: ["coreml", "cpu"], label: "CoreML" };
|
|
}
|
|
if (hasCUDA) return { providers: ["cuda", "cpu"], label: "CUDA" };
|
|
return { providers: ["cpu"], label: "CPU" };
|
|
}
|
|
|
|
let _cachedProviders: string[] | undefined;
|
|
export function listAvailableProviders(): string[] {
|
|
if (_cachedProviders) return _cachedProviders;
|
|
|
|
// The npm onnxruntime-node ships with CPU on every platform and bundles the
|
|
// CoreML EP only on darwin-arm64. CUDA is opt-in via a separate gpu build —
|
|
// gate behind an env var so we don't try to bind to a missing EP.
|
|
const out: string[] = ["cpu"];
|
|
if (platform() === "darwin" && arch() === "arm64") out.push("coreml");
|
|
if (process.env["HYPERFRAMES_CUDA"] === "1") out.push("cuda");
|
|
_cachedProviders = out;
|
|
return out;
|
|
}
|
|
|
|
export function modelPath(model: ModelId = DEFAULT_MODEL): string {
|
|
return join(MODELS_DIR, `${model}.onnx`);
|
|
}
|
|
|
|
export async function ensureModel(
|
|
model: ModelId = DEFAULT_MODEL,
|
|
options?: { onProgress?: (message: string) => void },
|
|
): Promise<string> {
|
|
const dest = modelPath(model);
|
|
if (existsSync(dest)) return dest;
|
|
|
|
mkdirSync(MODELS_DIR, { recursive: true });
|
|
options?.onProgress?.(`Downloading ${model} weights (~168 MB)...`);
|
|
await downloadFile(MODEL_URLS[model], dest);
|
|
|
|
if (!existsSync(dest)) {
|
|
throw new Error(`Model download failed: ${model}`);
|
|
}
|
|
return dest;
|
|
}
|