53 lines
2.8 KiB
MySQL
53 lines
2.8 KiB
MySQL
|
|
-- Migration 033 — SCTE-35 ad-break markers for playout.
|
||
|
|
--
|
||
|
|
-- Adds the missing SCTE-35 splice feature to the playout (MCR) subsystem. An
|
||
|
|
-- operator can either schedule an ad break on a channel's timeline (relative to
|
||
|
|
-- the active playlist position, or at a wall-clock time) or fire one immediately
|
||
|
|
-- ("splice now"). Each break is recorded here and, when fired, also written to
|
||
|
|
-- the append-only as-run log so it shows in the compliance record alongside the
|
||
|
|
-- clips that aired.
|
||
|
|
--
|
||
|
|
-- type:
|
||
|
|
-- splice_insert — a scheduled break (out → return), duration_s seconds long
|
||
|
|
-- immediate — fire-now splice (operator pressed "Trigger ad break now")
|
||
|
|
-- splice_out — open-ended avail out (provider break start)
|
||
|
|
-- splice_in — return-to-network (provider break end)
|
||
|
|
--
|
||
|
|
-- status: pending → fired (when the engine acts on it) → done (when the break
|
||
|
|
-- window has elapsed). cancelled is set if the operator removes a pending break.
|
||
|
|
--
|
||
|
|
-- The engine (services/playout) acts on a break by logging the cue, marking the
|
||
|
|
-- as-run row, and — where the output path supports it — injecting a real
|
||
|
|
-- SCTE-35 cue (see playout-manager.triggerScte for the injection point/TODO).
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS playout_scte_breaks (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
channel_id UUID NOT NULL REFERENCES playout_channels(id) ON DELETE CASCADE,
|
||
|
|
-- Position on the active playlist this break should fire after (0-based item
|
||
|
|
-- index). NULL for immediate/wall-clock breaks.
|
||
|
|
playlist_pos INTEGER,
|
||
|
|
-- Wall-clock fire time for scheduled breaks. NULL for immediate breaks.
|
||
|
|
scheduled_at TIMESTAMPTZ,
|
||
|
|
duration_s INTEGER NOT NULL DEFAULT 30,
|
||
|
|
-- SCTE-35 event id (the splice_event_id carried in the cue). Auto-assigned.
|
||
|
|
event_id INTEGER NOT NULL DEFAULT 1,
|
||
|
|
type TEXT NOT NULL DEFAULT 'splice_insert',
|
||
|
|
status TEXT NOT NULL DEFAULT 'pending',
|
||
|
|
fired_at TIMESTAMPTZ,
|
||
|
|
created_by UUID REFERENCES users(id) ON DELETE SET NULL,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
CHECK (type IN ('splice_insert','immediate','splice_out','splice_in')),
|
||
|
|
CHECK (status IN ('pending','fired','done','cancelled'))
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_playout_scte_channel ON playout_scte_breaks (channel_id, created_at DESC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_playout_scte_status ON playout_scte_breaks (status);
|
||
|
|
|
||
|
|
-- As-run gains a 'scte' result so fired breaks land in the compliance log next to
|
||
|
|
-- the clips. The original migration constrained result to played/skipped/error;
|
||
|
|
-- widen it.
|
||
|
|
ALTER TABLE playout_as_run DROP CONSTRAINT IF EXISTS playout_as_run_result_check;
|
||
|
|
ALTER TABLE playout_as_run ADD CONSTRAINT playout_as_run_result_check
|
||
|
|
CHECK (result IN ('played','skipped','error','scte'));
|