Rich media (t1): media_assets (migration 038) + /media module — multipart upload with magic-byte sniffing, size caps, auth-scoped serve with ETag/same-origin; the publishing 'text only' gate lifted to accept 0..4 validated mediaAssetIds with optional positional altTexts. Producer intake (t3): video_processing_jobs gains kind compose|mix + input_json + produced_asset_id (migration 039), video_assets.derived_from; POST /video/:id/produce validates overlays/voiceover strictly and queues the job for the media-worker runner (landing separately).
43 lines
2.3 KiB
PL/PgSQL
43 lines
2.3 KiB
PL/PgSQL
-- 039: producer job intake — a producer can ask for a NEW asset derived from an
|
|
-- existing one (burned-in lower thirds/logos/clock, an optional voiceover mix).
|
|
--
|
|
-- WHY COLUMNS AND NOT A NEW TABLE: video_processing_jobs (009) already models the
|
|
-- per-asset work queue (state machine, progress, output_key, RLS, tenant-immutability
|
|
-- triggers, workspace-scoped grants). Intake only needs to distinguish WHAT a queued
|
|
-- row asks the media-worker to do and carry the request payload; that is two columns
|
|
-- on the existing queue plus a nullable pointer to the row it produces. A second
|
|
-- table would duplicate the state machine and the isolation policy for no gain.
|
|
--
|
|
-- kind 'probe' — the 009 behaviour: ingest + ffprobe + no-op transcode.
|
|
-- 'compose' — burn overlays (and optionally a logo PNG) over the source.
|
|
-- 'mix' — compose AND replace/duck the audio bed with a voiceover.
|
|
-- Default 'probe' keeps every existing row and INSERT (009 code path)
|
|
-- meaning exactly what it meant before this migration.
|
|
-- input_json the validated producer request ({...request, requestedBy}), only
|
|
-- ever written by the API after strict allowlist parsing; the worker
|
|
-- re-validates. NULL for probe rows.
|
|
-- produced_asset_id the video_assets row the job writes when it finishes, so a
|
|
-- finished job points forward to its output.
|
|
-- video_assets.derived_from the SOURCE asset id of a produced row; NULL for ingested
|
|
-- uploads. Produced rows are ordinary video_assets rows, so they appear
|
|
-- in the library listing and inherit its tenant isolation unchanged.
|
|
--
|
|
-- The kind enum is CHECK-constrained so an undecodable row cannot exist.
|
|
|
|
BEGIN;
|
|
|
|
ALTER TABLE video_processing_jobs
|
|
ADD COLUMN kind text NOT NULL DEFAULT 'probe'
|
|
CHECK (kind IN ('probe', 'compose', 'mix')),
|
|
ADD COLUMN input_json jsonb,
|
|
ADD COLUMN produced_asset_id uuid;
|
|
|
|
ALTER TABLE video_assets
|
|
ADD COLUMN derived_from uuid REFERENCES video_assets(id);
|
|
|
|
-- Jobs that produce a derived asset are claimed by the media-worker by kind.
|
|
CREATE INDEX video_processing_jobs_kind_queued
|
|
ON video_processing_jobs (kind, created_at DESC)
|
|
WHERE state = 'queued';
|
|
|
|
COMMIT;
|