128 lines
5.2 KiB
SQL
128 lines
5.2 KiB
SQL
CREATE TABLE post_recording_parts (
|
|
id TEXT PRIMARY KEY,
|
|
show_id TEXT NOT NULL REFERENCES shows(id) ON DELETE CASCADE,
|
|
label TEXT NOT NULL,
|
|
position INTEGER NOT NULL CHECK (position >= 0),
|
|
media_file_path TEXT NOT NULL DEFAULT '',
|
|
frame_rate REAL CHECK (frame_rate IS NULL OR (frame_rate > 0 AND frame_rate <= 240)),
|
|
timebase INTEGER CHECK (timebase IS NULL OR (timebase > 0 AND timebase <= 240)),
|
|
created_at_utc TEXT NOT NULL,
|
|
UNIQUE (show_id, position)
|
|
);
|
|
|
|
CREATE INDEX idx_post_recording_parts_show
|
|
ON post_recording_parts(show_id, position);
|
|
|
|
CREATE TABLE post_source_files (
|
|
id TEXT PRIMARY KEY,
|
|
show_id TEXT NOT NULL REFERENCES shows(id) ON DELETE CASCADE,
|
|
recording_part_id TEXT REFERENCES post_recording_parts(id) ON DELETE SET NULL,
|
|
original_name TEXT NOT NULL,
|
|
storage_name TEXT NOT NULL UNIQUE,
|
|
sha256 TEXT NOT NULL,
|
|
byte_size INTEGER NOT NULL CHECK (byte_size > 0),
|
|
content TEXT NOT NULL,
|
|
transcript_text TEXT NOT NULL DEFAULT '',
|
|
timecodes_json TEXT NOT NULL DEFAULT '[]',
|
|
imported_at_utc TEXT NOT NULL,
|
|
UNIQUE (show_id, sha256)
|
|
);
|
|
|
|
CREATE INDEX idx_post_source_files_show
|
|
ON post_source_files(show_id, imported_at_utc);
|
|
|
|
CREATE TABLE post_items (
|
|
id TEXT PRIMARY KEY,
|
|
show_id TEXT NOT NULL REFERENCES shows(id) ON DELETE CASCADE,
|
|
kind TEXT NOT NULL CHECK (kind IN ('youtube', 'clip', 'highlight')),
|
|
title TEXT NOT NULL,
|
|
status TEXT NOT NULL CHECK (status IN ('draft', 'review', 'approved', 'editing', 'done', 'published')),
|
|
recording_part_id TEXT REFERENCES post_recording_parts(id) ON DELETE SET NULL,
|
|
source_file_id TEXT REFERENCES post_source_files(id) ON DELETE SET NULL,
|
|
piece_id TEXT REFERENCES pieces(id) ON DELETE SET NULL,
|
|
notes TEXT NOT NULL DEFAULT '',
|
|
revision INTEGER NOT NULL DEFAULT 1 CHECK (revision >= 1),
|
|
position INTEGER NOT NULL CHECK (position >= 0),
|
|
created_at_utc TEXT NOT NULL,
|
|
updated_at_utc TEXT NOT NULL,
|
|
UNIQUE (show_id, kind, position)
|
|
);
|
|
|
|
CREATE INDEX idx_post_items_show_kind
|
|
ON post_items(show_id, kind, position);
|
|
|
|
CREATE TABLE post_youtube_videos (
|
|
item_id TEXT PRIMARY KEY REFERENCES post_items(id) ON DELETE CASCADE,
|
|
description TEXT NOT NULL DEFAULT '',
|
|
title_variants_json TEXT NOT NULL DEFAULT '[]',
|
|
thumbnail_concept TEXT NOT NULL DEFAULT '',
|
|
thumbnail_text TEXT NOT NULL DEFAULT '',
|
|
publication_status TEXT NOT NULL DEFAULT 'unpublished'
|
|
CHECK (publication_status IN ('unpublished', 'scheduled', 'published')),
|
|
published_at_utc TEXT,
|
|
youtube_url TEXT NOT NULL DEFAULT '',
|
|
video_format TEXT NOT NULL DEFAULT '16:9'
|
|
);
|
|
|
|
CREATE TABLE post_social_clips (
|
|
item_id TEXT PRIMARY KEY REFERENCES post_items(id) ON DELETE CASCADE,
|
|
clip_type TEXT NOT NULL DEFAULT 'other'
|
|
CHECK (clip_type IN ('storytime', 'opinion', 'explanation', 'gaming', 'humor', 'other')),
|
|
original_transcript TEXT NOT NULL DEFAULT '',
|
|
start_seconds INTEGER CHECK (start_seconds IS NULL OR start_seconds >= 0),
|
|
end_seconds INTEGER CHECK (end_seconds IS NULL OR end_seconds >= 0),
|
|
dramaturgy_notes TEXT NOT NULL DEFAULT '',
|
|
edit_instructions TEXT NOT NULL DEFAULT '',
|
|
shorts_title TEXT NOT NULL DEFAULT '',
|
|
shorts_description TEXT NOT NULL DEFAULT '',
|
|
shorts_hashtags TEXT NOT NULL DEFAULT '',
|
|
tiktok_caption TEXT NOT NULL DEFAULT '',
|
|
instagram_caption TEXT NOT NULL DEFAULT '',
|
|
social_hashtags TEXT NOT NULL DEFAULT '',
|
|
primary_hook TEXT NOT NULL DEFAULT '',
|
|
alternative_hooks TEXT NOT NULL DEFAULT '',
|
|
endcard_text TEXT NOT NULL DEFAULT '',
|
|
alternative_endcards TEXT NOT NULL DEFAULT '',
|
|
framing_notes TEXT NOT NULL DEFAULT '',
|
|
subtitle_notes TEXT NOT NULL DEFAULT '',
|
|
subtitle_srt TEXT NOT NULL DEFAULT '',
|
|
video_format TEXT NOT NULL DEFAULT '9:16',
|
|
target_tiktok INTEGER NOT NULL DEFAULT 1 CHECK (target_tiktok IN (0, 1)),
|
|
target_instagram INTEGER NOT NULL DEFAULT 1 CHECK (target_instagram IN (0, 1)),
|
|
target_shorts INTEGER NOT NULL DEFAULT 1 CHECK (target_shorts IN (0, 1)),
|
|
CHECK (end_seconds IS NULL OR start_seconds IS NULL OR end_seconds > start_seconds)
|
|
);
|
|
|
|
CREATE TABLE post_twitch_highlights (
|
|
item_id TEXT PRIMARY KEY REFERENCES post_items(id) ON DELETE CASCADE,
|
|
description TEXT NOT NULL DEFAULT '',
|
|
original_transcript TEXT NOT NULL DEFAULT '',
|
|
start_seconds INTEGER CHECK (start_seconds IS NULL OR start_seconds >= 0),
|
|
end_seconds INTEGER CHECK (end_seconds IS NULL OR end_seconds >= 0),
|
|
edit_instructions TEXT NOT NULL DEFAULT '',
|
|
publication_notes TEXT NOT NULL DEFAULT '',
|
|
video_format TEXT NOT NULL DEFAULT '16:9',
|
|
twitch_url TEXT NOT NULL DEFAULT '',
|
|
CHECK (end_seconds IS NULL OR start_seconds IS NULL OR end_seconds > start_seconds)
|
|
);
|
|
|
|
CREATE TABLE post_thumbnails (
|
|
id TEXT PRIMARY KEY,
|
|
youtube_item_id TEXT NOT NULL REFERENCES post_youtube_videos(item_id) ON DELETE CASCADE,
|
|
storage_name TEXT NOT NULL UNIQUE,
|
|
original_name TEXT NOT NULL,
|
|
mime_type TEXT NOT NULL,
|
|
byte_size INTEGER NOT NULL CHECK (byte_size > 0),
|
|
alt_text TEXT NOT NULL DEFAULT '',
|
|
position INTEGER NOT NULL CHECK (position >= 0),
|
|
is_selected INTEGER NOT NULL DEFAULT 0 CHECK (is_selected IN (0, 1)),
|
|
created_at_utc TEXT NOT NULL,
|
|
UNIQUE (youtube_item_id, position)
|
|
);
|
|
|
|
CREATE INDEX idx_post_thumbnails_item
|
|
ON post_thumbnails(youtube_item_id, position);
|
|
|
|
CREATE UNIQUE INDEX idx_post_one_selected_thumbnail
|
|
ON post_thumbnails(youtube_item_id) WHERE is_selected = 1;
|