mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-04 07:19:52 +00:00
test(cli): harden media treatment parity
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
||||||
import { tmpdir } from "node:os";
|
import { tmpdir } from "node:os";
|
||||||
import { join } from "node:path";
|
import { basename, join } from "node:path";
|
||||||
import { runCommand } from "citty";
|
import { runCommand } from "citty";
|
||||||
import { describe, expect, it, vi } from "vitest";
|
import { describe, expect, it, vi } from "vitest";
|
||||||
import {
|
import {
|
||||||
@@ -211,11 +211,13 @@ describe("applyMediaTreatmentToHtml", () => {
|
|||||||
|
|
||||||
it("resolves nested composition media through the shared project-root contract", () => {
|
it("resolves nested composition media through the shared project-root contract", () => {
|
||||||
const project = mkdtempSync(join(tmpdir(), "hf-media-treatment-assets-"));
|
const project = mkdtempSync(join(tmpdir(), "hf-media-treatment-assets-"));
|
||||||
|
const escapedAsset = join(project, "..", `${basename(project)}-escape.mp4`);
|
||||||
mkdirSync(join(project, "capture"), { recursive: true });
|
mkdirSync(join(project, "capture"), { recursive: true });
|
||||||
mkdirSync(join(project, "assets"), { recursive: true });
|
mkdirSync(join(project, "assets"), { recursive: true });
|
||||||
writeFileSync(join(project, "capture", "talking-head.mp4"), "");
|
writeFileSync(join(project, "capture", "talking-head.mp4"), "");
|
||||||
writeFileSync(join(project, "assets", "photo.webp"), "");
|
writeFileSync(join(project, "assets", "photo.webp"), "");
|
||||||
writeFileSync(join(project, "assets", "My Clip.mp4"), "");
|
writeFileSync(join(project, "assets", "My Clip.mp4"), "");
|
||||||
|
writeFileSync(escapedAsset, "");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
expect(
|
expect(
|
||||||
@@ -248,8 +250,16 @@ describe("applyMediaTreatmentToHtml", () => {
|
|||||||
expect(() =>
|
expect(() =>
|
||||||
resolveMediaTreatmentSource(project, "compositions/scene.html", "missing.mp4"),
|
resolveMediaTreatmentSource(project, "compositions/scene.html", "missing.mp4"),
|
||||||
).toThrow(/Media file not found/);
|
).toThrow(/Media file not found/);
|
||||||
|
expect(() =>
|
||||||
|
resolveMediaTreatmentSource(
|
||||||
|
project,
|
||||||
|
"compositions/scene.html",
|
||||||
|
`../../${basename(escapedAsset)}`,
|
||||||
|
),
|
||||||
|
).toThrow(/Media file not found/);
|
||||||
} finally {
|
} finally {
|
||||||
rmSync(project, { recursive: true, force: true });
|
rmSync(project, { recursive: true, force: true });
|
||||||
|
rmSync(escapedAsset, { force: true });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,26 @@ lavfi.signalstats.UAVG=125
|
|||||||
lavfi.signalstats.VAVG=135
|
lavfi.signalstats.VAVG=135
|
||||||
lavfi.signalstats.SATAVG=60`;
|
lavfi.signalstats.SATAVG=60`;
|
||||||
|
|
||||||
|
const UNDEREXPOSED_SIGNALSTATS = `frame:0 pts:0 pts_time:0
|
||||||
|
lavfi.signalstats.YMIN=2
|
||||||
|
lavfi.signalstats.YLOW=8
|
||||||
|
lavfi.signalstats.YAVG=50
|
||||||
|
lavfi.signalstats.YHIGH=120
|
||||||
|
lavfi.signalstats.YMAX=135
|
||||||
|
lavfi.signalstats.UAVG=128
|
||||||
|
lavfi.signalstats.VAVG=128
|
||||||
|
lavfi.signalstats.SATAVG=30`;
|
||||||
|
|
||||||
|
const BLOWN_HIGHLIGHT_SIGNALSTATS = `frame:0 pts:0 pts_time:0
|
||||||
|
lavfi.signalstats.YMIN=70
|
||||||
|
lavfi.signalstats.YLOW=90
|
||||||
|
lavfi.signalstats.YAVG=200
|
||||||
|
lavfi.signalstats.YHIGH=248
|
||||||
|
lavfi.signalstats.YMAX=255
|
||||||
|
lavfi.signalstats.UAVG=128
|
||||||
|
lavfi.signalstats.VAVG=128
|
||||||
|
lavfi.signalstats.SATAVG=30`;
|
||||||
|
|
||||||
const PROBE: GradeMediaProbe = {
|
const PROBE: GradeMediaProbe = {
|
||||||
duration: 4,
|
duration: 4,
|
||||||
colorSpace: "bt2020nc",
|
colorSpace: "bt2020nc",
|
||||||
@@ -36,8 +56,8 @@ const PROBE: GradeMediaProbe = {
|
|||||||
pixelFormat: "yuv420p10le",
|
pixelFormat: "yuv420p10le",
|
||||||
};
|
};
|
||||||
|
|
||||||
function productResult() {
|
function productResult(signalStats = SIGNALSTATS) {
|
||||||
const frames = parseMediaTreatmentSignalStats(SIGNALSTATS);
|
const frames = parseMediaTreatmentSignalStats(signalStats);
|
||||||
const summary = summarizeMediaTreatmentAnalysis(PROBE, frames);
|
const summary = summarizeMediaTreatmentAnalysis(PROBE, frames);
|
||||||
return {
|
return {
|
||||||
frames,
|
frames,
|
||||||
@@ -47,13 +67,13 @@ function productResult() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function vendoredResult() {
|
async function vendoredResult(signalStats = SIGNALSTATS) {
|
||||||
const moduleUrl = new URL(
|
const moduleUrl = new URL(
|
||||||
"../../../skills/media-use/scripts/lib/grade-analyzer.mjs",
|
"../../../skills/media-use/scripts/lib/grade-analyzer.mjs",
|
||||||
import.meta.url,
|
import.meta.url,
|
||||||
);
|
);
|
||||||
const analyzer = await import(moduleUrl.href);
|
const analyzer = await import(moduleUrl.href);
|
||||||
const frames = analyzer.parseMediaTreatmentSignalStats(SIGNALSTATS);
|
const frames = analyzer.parseMediaTreatmentSignalStats(signalStats);
|
||||||
const summary = analyzer.summarizeMediaTreatmentAnalysis(PROBE, frames);
|
const summary = analyzer.summarizeMediaTreatmentAnalysis(PROBE, frames);
|
||||||
return {
|
return {
|
||||||
frames,
|
frames,
|
||||||
@@ -67,4 +87,14 @@ describe("vendored media grade analyzer parity", () => {
|
|||||||
it("keeps the standalone skill copy aligned with the typed product module", async () => {
|
it("keeps the standalone skill copy aligned with the typed product module", async () => {
|
||||||
expect(await vendoredResult()).toEqual(productResult());
|
expect(await vendoredResult()).toEqual(productResult());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
["underexposed", UNDEREXPOSED_SIGNALSTATS, 1],
|
||||||
|
["blown-highlight", BLOWN_HIGHLIGHT_SIGNALSTATS, -1],
|
||||||
|
])("covers the %s exposure branch", async (_, signalStats, expectedSign) => {
|
||||||
|
const product = productResult(signalStats);
|
||||||
|
|
||||||
|
expect(Math.sign(product.adjust.adjust.exposure)).toBe(expectedSign);
|
||||||
|
expect(await vendoredResult(signalStats)).toEqual(product);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user