-- 카페 BGM 연속재생 타임라인 (2026-05-20, BGM Phase 2). -- -- 점주가 [웰컴 멘트 TTS] → [BGM] → [신메뉴 멘트 TTS] → [BGM] ... 를 순서대로 조합. -- 기존 playlists(sql/013, 예약방송 전용)와 별개 — BGM 전용 신규 테이블. -- -- 핵심 원칙(재생 경로 GPU 0): -- - bgm 슬롯 = music_themes(글로벌) 또는 user_music(Phase 4) 참조 → Storage 파일. -- - tts_ment 슬롯 = 멘트 텍스트를 **사전 생성**(타임라인 저장/편집 시 TTS 1회) → -- ment_audio_path 에 저장. 재생 시엔 이 파일만 서빙 (실시간 TTS 아님). -- ment_status: pending(생성 대기) → ready(파일 있음) → failed(재시도 대상). -- -- 회귀 0: 신규 테이블 — 기존 TTS/voice/playlist/care/music_themes 영향 없음. -- RLS: 소유자만 read/write (방어). 백엔드는 service_role + user_id 필터 병행. CREATE TABLE IF NOT EXISTS public.music_timelines ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), user_id uuid NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE, name text NOT NULL DEFAULT '내 카페 BGM', is_active boolean NOT NULL DEFAULT true, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE TABLE IF NOT EXISTS public.timeline_items ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), timeline_id uuid NOT NULL REFERENCES public.music_timelines(id) ON DELETE CASCADE, position integer NOT NULL, -- 재생 순서 (0-based) item_type text NOT NULL CHECK (item_type IN ('bgm', 'tts_ment')), -- bgm 슬롯 music_theme_id uuid REFERENCES public.music_themes(id) ON DELETE SET NULL, -- tts_ment 슬롯 (사전 생성 → 파일 재생) ment_text text, ment_voice text, -- 음색/스피커 키 ment_audio_path text, -- 생성된 멘트 오디오 ('music' 버킷 상대 경로) ment_status text NOT NULL DEFAULT 'pending' CHECK (ment_status IN ('pending', 'ready', 'failed')), settings jsonb NOT NULL DEFAULT '{}', -- loop/gap/volume 등 슬롯별 옵션 created_at timestamptz NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS timeline_items_timeline_pos_idx ON public.timeline_items (timeline_id, position); CREATE INDEX IF NOT EXISTS music_timelines_user_idx ON public.music_timelines (user_id, updated_at DESC); ALTER TABLE public.music_timelines ENABLE ROW LEVEL SECURITY; ALTER TABLE public.timeline_items ENABLE ROW LEVEL SECURITY; -- 소유자만 접근 (백엔드 service_role 은 RLS bypass — 추가 방어선). DROP POLICY IF EXISTS music_timelines_owner ON public.music_timelines; CREATE POLICY music_timelines_owner ON public.music_timelines FOR ALL USING (user_id = auth.uid()) WITH CHECK (user_id = auth.uid()); DROP POLICY IF EXISTS timeline_items_owner ON public.timeline_items; CREATE POLICY timeline_items_owner ON public.timeline_items FOR ALL USING ( EXISTS (SELECT 1 FROM public.music_timelines t WHERE t.id = timeline_items.timeline_id AND t.user_id = auth.uid()) ); COMMENT ON TABLE public.music_timelines IS '카페 BGM 연속재생 타임라인 (멘트 TTS + BGM). 재생=Storage 파일 서빙.';