T-HUB/apps/media-worker/src/env.ts
glass beadian d9e8cdf789 feat: produce worker deployment + web producer/collective/branding UI + mobile CSS (wave-2c)
Deployment (t4g2): media-worker gains font-dejavu (drawtext lower-thirds)
and a dedicated produce-worker compose service running src/produce.ts —
claims video_processing_jobs compose|mix by lane, renders assembled/
overlaid/voiced cuts, registers derived library assets. Deliberately its
own process so a remote-lane box needs only Postgres + S3 + ffmpeg.

Web: compose media attachments UI (t2), Producer panel in the video
drawer (t5), collective creation + branding settings + shell branding
(brandweb), mobile CSS (mcss: touch targets, icon sizing, safe areas).
2026-10-14 20:40:49 +00:00

32 lines
1.5 KiB
TypeScript

/**
* Produce worker env parsing: the two settings a produce box needs that are not
* plain pass-throughs — the lane this worker claims, and the lower-third font.
*
* Both are validated loudly at boot (a silently-defaulted lane would claim the
* wrong rows; a missing font fails every compose job at encode time, far too late).
*/
import { accessSync, constants } from "node:fs";
/** `MEDIA_WORKER_LANE`: default worker claims local-or-NULL, a remote worker only remote. */
export function laneFromEnv(value: string | undefined): "local" | "remote" {
if (value === undefined || value === "") return "local";
if (value === "local" || value === "remote") return value;
throw new Error(`MEDIA_WORKER_LANE must be 'local' or 'remote' (got ${JSON.stringify(value)})`);
}
/**
* `MEDIA_PRODUCE_FONT`: absolute path to a readable .ttf. Defaults to the
* DejaVu face present on the worker's base image; validated now (ENOENT at
* encode time is a 15-minute-late failure for the first job that needs it).
*/
export function resolveProduceFont(value: string | undefined): string {
const font = value ?? "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf";
if (!font.startsWith("/")) throw new Error("MEDIA_PRODUCE_FONT must be an absolute path");
if (!font.endsWith(".ttf")) throw new Error("MEDIA_PRODUCE_FONT must point to a .ttf");
try {
accessSync(font, constants.R_OK);
} catch {
throw new Error(`MEDIA_PRODUCE_FONT is not readable: ${font}`);
}
return font;
}