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).
This commit is contained in:
parent
1183d69849
commit
d9e8cdf789
18 changed files with 2384 additions and 20 deletions
32
apps/media-worker/src/env.ts
Normal file
32
apps/media-worker/src/env.ts
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue