Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,88 @@
import { spawn } from "node:child_process";
import { mkdir, mkdtemp, rm, stat } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import ffmpegInstaller from "@ffmpeg-installer/ffmpeg";
/** Path of the on-the-fly fixture video. Cached per Vitest worker. */
let fixturePath: string | undefined;
let fixtureDir: string | undefined;
/**
* Synthesise a 5-second 320×240 colour-gradient MP4 once per worker and return
* its absolute path. Subsequent calls return the cached path. Uses ffmpeg's
* `lavfi` virtual source so no checked-in binary is required.
*/
export async function getFixtureVideo(): Promise<string> {
if (fixturePath !== undefined) {
return fixturePath;
}
const dir = await mkdtemp(join(tmpdir(), "vt-fixture-"));
const out = join(dir, "fixture.mp4");
await new Promise<void>((resolve, reject) => {
const child = spawn(
ffmpegInstaller.path,
[
"-y",
"-f",
"lavfi",
"-i",
"testsrc=duration=5:size=320x240:rate=10",
"-pix_fmt",
"yuv420p",
"-c:v",
"libx264",
"-preset",
"ultrafast",
"-tune",
"zerolatency",
out,
],
{ stdio: "pipe" }
);
let stderr = "";
child.stderr.on("data", (chunk) => {
stderr += String(chunk);
});
child.once("error", reject);
child.once("exit", (code) => {
if (code === 0) {
resolve();
} else {
reject(new Error(`ffmpeg fixture build failed: ${stderr}`));
}
});
});
const fileStat = await stat(out);
if (fileStat.size === 0) {
throw new Error("fixture video has zero bytes");
}
fixtureDir = dir;
fixturePath = out;
return out;
}
/** Create a unique tmp output directory for one test. */
export async function makeOutputDir(label: string): Promise<string> {
const dir = await mkdtemp(join(tmpdir(), `vt-${label}-`));
await mkdir(dir, { recursive: true });
return dir;
}
/** Best-effort cleanup; safe to ignore failures (Windows / locked files). */
export async function safeRm(path: string): Promise<void> {
try {
await rm(path, { recursive: true, force: true });
} catch {
// ignored
}
}
/** Clear the cached fixture (used by setup teardown). */
export async function clearFixtureCache(): Promise<void> {
if (fixtureDir !== undefined) {
await safeRm(fixtureDir);
}
fixturePath = undefined;
fixtureDir = undefined;
}