#!/usr/bin/env bun
/**
* Encodes a source video into an immutable HLS (fMP4) package plus scrub sprite sheets:
* bun scripts/video/prepare.ts --source in.mov --id intro --version v1 [--out dir]
* Needs ffmpeg/ffprobe (libx264, aac) and cwebp. Upload the result with scripts/video/upload.ts.
*/
import { mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
import { join, resolve } from "node:path";
import { parseArgs } from "node:util";
import { SCRUB_MANIFEST, type ScrubManifest } from "../../src/lib/video";
const LADDER = [
{ height: 240, bitrate: 400_000, audio: "64k" },
{ height: 360, bitrate: 1_000_000, audio: "96k" },
{ height: 720, bitrate: 3_000_000, audio: "128k" },
{ height: 1080, bitrate: 6_000_000, audio: "128k" },
{ height: 1440, bitrate: 10_000_000, audio: "160k" },
{ height: 2160, bitrate: 20_000_000, audio: "160k" },
];
const SEGMENT_SECONDS = 4;
const SCRUB = { width: 256, height: 144, columns: 10, rows: 10, maxFrames: 1000 };
const MAX_FRAME_RATE = 60;
const QUARTER_TURN = 90;
const HALF_TURN = 180;
const ID = /^[a-z0-9][a-z0-9-]{0,63}$/;
async function run(argv: string[]): Promise<string> {
const proc = Bun.spawn(argv, { stdout: "pipe", stderr: "pipe" });
const [out, err, code] = await Promise.all([
new Response(proc.stdout).text(),
new Response(proc.stderr).text(),
proc.exited,
]);
if (code !== 0) throw new Error(`${argv[0]} exited ${code}: ${err.trim()}`);
return out;
}
interface Probe {
width: number;
height: number;