fix(cli): encode background-removal WebM colors as BT.709 (#5278)

This commit is contained in:
Abdullah M. Nazif
2026-10-08 20:13:46 +00:00
committed by GitHub
parent 072de48e08
commit 2295ed5ea6
4 changed files with 26 additions and 6 deletions
@@ -67,6 +67,23 @@ describe("background-removal/pipeline — buildEncoderArgs", () => {
expect(args[rangeIdx + 1]).toBe("tv");
});
it.each(["fast", "balanced", "best"] as const)(
"converts raw RGBA to the tagged BT.709 matrix at %s quality",
(quality) => {
const args = buildEncoderArgs("webm", 64, 64, 30, "/tmp/cutout.webm", quality);
const filter = args[args.indexOf("-vf") + 1];
expect(filter).toContain("out_color_matrix=bt709");
expect(filter).toContain("out_range=tv");
expect(args[args.indexOf("-pix_fmt") + 1]).toBe("rgba");
expect(args).toContain("yuva420p");
},
);
it.each(["mov", "png"] as const)("keeps the %s output color path", (format) => {
const args = buildEncoderArgs(format, 64, 64, 30, `/tmp/cutout.${format}`);
expect(args).not.toContain("-vf");
});
it("webm quality presets map to crf 30/18/12", () => {
const fast = buildEncoderArgs("webm", 1920, 1080, 30, "/tmp/o.webm", "fast");
const balanced = buildEncoderArgs("webm", 1920, 1080, 30, "/tmp/o.webm", "balanced");
@@ -20,7 +20,11 @@ import { basename, dirname, extname, join } from "node:path";
import { findFFmpeg, findFFprobe, getFFmpegInstallHint } from "../browser/ffmpeg.js";
import { createSession, type Session } from "./inference.js";
import { type Device, type ModelId } from "./manager.js";
import { DEFAULT_VP9_CPU_USED, renderProvenanceArgs } from "@hyperframes/engine";
import {
DEFAULT_VP9_CPU_USED,
SDR_RGB_TO_BT709_FILTER,
renderProvenanceArgs,
} from "@hyperframes/engine";
export type OutputFormat = "webm" | "mov" | "png";
@@ -152,6 +156,8 @@ export function buildEncoderArgs(
if (format === "webm") {
return [
...base,
"-vf",
SDR_RGB_TO_BT709_FILTER,
"-c:v",
"libvpx-vp9",
"-b:v",
@@ -168,11 +174,6 @@ export function buildEncoderArgs(
"0",
"-pix_fmt",
"yuva420p",
// Tag the output as BT.709 limited range so browsers use the same
// YUV→RGB matrix the source video was encoded with. Without these tags
// ffmpeg's default RGB→YUV conversion is BT.601, which causes a visible
// color shift (red/skin tones in particular) when the matted overlay is
// composited over the original mp4.
"-colorspace",
"bt709",
"-color_primaries",
@@ -35,6 +35,7 @@ vi.mock("./inference.js", () => ({
}));
vi.mock("@hyperframes/engine", () => ({
DEFAULT_VP9_CPU_USED: 4,
SDR_RGB_TO_BT709_FILTER: "scale=out_color_matrix=bt709:out_range=tv:flags=neighbor",
renderProvenanceArgs: () => [],
extractMediaMetadata: async () => ({ width: 1, height: 1, fps: 1, durationSeconds: 1 }),
}));
+1
View File
@@ -60,6 +60,7 @@ export {
type EngineConfig,
type ExtractCacheDirResolution,
} from "./config.js";
export { SDR_RGB_TO_BT709_FILTER } from "./utils/sdrCaptureColor.js";
export {
DEFAULT_VP9_CPU_USED,
MAX_VP9_CPU_USED,