Initial Commit
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
Reference in New Issue
Block a user