87509bcf99
TASKS.md is now the index (status table, open items, research pointer). 33 files: 32 task files + 1 research facts file. The full take-saga narrative and all design decisions are preserved verbatim; the catalog makes the queue readable without opening every task body. Schema and AGENTS.md updated to reflect the new layout.
5.8 KiB
5.8 KiB
TASK 9 — YouTube Live Stream Management
Catalog:
TASKS.md— status and requirements live here.
Goal: Create/bind broadcasts, monitor YouTube-side stream health — the v3 way.
Status: ⏳ In progress — items 1–3 SHIPPED (reusable stream 2026-08-16; report-by-exception health 2026-08-16); item 4 SHIPPED (status reconciled 2026-09-01); item 5 open; item 6 = deliberate lock (TASK 36); item 7 scoped to core fields — advanced tab is out-of-product
- ☑ Broadcast creation — title/description/privacy/scheduledStartTime via API, with the v3 flags above (SHIPPED:
CreateBroadcastsendsenableAutoStart/Stop,enableMonitorStream=false,latencyPreference=low,selfDeclaredMadeForKids=false) - ☑ Reusable stream — create once, cache + reuse; bind to broadcast (SHIPPED:
GetOrCreateReusableStreamAsynclists-then-inserts thevariable/isReusablestream, cached viaLayoutStoreSettings, bound at broadcast insert viaboundStreamId;_rtmpUrlProvideryields the ingest URL so go-live actually encodes + pushes) - ☑ Health monitoring — poll
liveStreams.listhealthStatus+configurationIssues[], surface banner only on warning/error (SHIPPED:GetStreamHealthAsync(streamId)30s while live; pureStreamHealthReporter.BannerFor= report-by-exception; banner strip under the top bar, amber warning / dark-red error, viaHealthIssueBanner/HealthIssueBackground; poll failures log-only; ONE integration testGetStreamHealthAsync_Report_By_Exception_Banner_Only_On_Warning_Or_Error) - ☑ Live chat — poll
liveChat/messages, render in right panel, support Super Chat + membership badges — SHIPPED (status reconciled 2026-09-01:YouTubeChatServicepolls + parsessuperChatEvent/newSponsorEventwith badge/level onChatMessage; the panel MOVED to the left-panel live state by Control Surface UX, "right panel" superseded; the remaining reward types land with the monetization chain, TASK 10 → related work) - ☐ Error handling — the YouTube error codes:
errorStreamInactive,invalidTransition,redundantTransition,liveStreamDeletionNotAllowed,liveStreamModificationNotAllowed,liveBroadcastBindingNotAllowed - ❌ Visibility picker — DELIBERATE TEST-PHASE LOCK (creator decision 2026-09-01), not open work: "always Private" stays during multi-month real-world testing so breakage VODs never clutter the channel.
recordFromStart/DVR stay on — Private VODs are invisible review tapes; bulk-delete pre-GA. Unlock = TASK 36 gold-pass item (remove the override inYouTubeStreamService.CreateBroadcast, wire the dialog selection). Seeai.md→ YouTube Live API constraints. - 🔶 Full broadcast form — RESCOPED 2026-09-01, not the old two-tab plan. Core fields (SHIPPED as the Text drawer, 2026-08-24): title, description, tags, visibility, made-for-kids — live-editable. Scheduling: ships as TASK 34 (Scheduled checkbox + datetime in the same drawer). Advanced tab is PERMANENTLY OUT (the 10% margin): latency (locked
low), DVR/record-from-start (locked on), embed, projection, CC, region restrictions stay fixed at sane defaults, invisible — every exposed field is a support ticket.categoryIdremoval: done (not aliveBroadcastfield). Monetization enablement (if ever needed) rides the reward-events chain vialiveBroadcasts.update, not a form field
Design decisions (v3)
- One-click go-live —
liveBroadcasts.insertwithenableAutoStart=true,enableAutoStop=true,enableMonitorStream=false,selfDeclaredMadeForKids=false,latencyPreference=low. Notransition(live)call, no testing stage, no liveStarting polling. Encoder starts → YouTube brings it live by itself. - Variable reusable stream —
cdn.resolution=variable,cdn.frameRate=variable,isReusable=true. Create once per channel, cache ingestion URL + stream name, reuse for every broadcast. Any quality tier works without recreation; auto step-down needs no API calls. - Report-by-exception — poll
liveStreams.list; banner only onhealthStatuswarning/error issues (configurationIssues[]). Bottom strip = YouTube logo + green/red connection dot (clickable → opens the dialog). - One dialog, three states —
not connected(sign-in) /connected-offline(all editable) /live(title + description + visibility editable; quality + account greyed out). Both entry points (Start Stream button + bottom strip) open it; prefilled from saved session profile. - Live edits —
liveBroadcasts.updatewith part=snippet,statusfor title/description/privacy. - End stream — stop encoder →
transition(complete), withenableAutoStopas the safety net. SHIPPED 2026-09-01 (EndBroadcastAsync, wired intoStopStreamafter RTMP EOF; the call had been specced since TASK 9 but never existed — found during recording verification) - Broadcast ID == Video ID — one ID to track status, health, and the auto-created VOD (
recordFromStart+enableDvr).
Requirements:
- Broadcast creation — title/description/privacy/scheduledStartTime via API, with the v3 flags above
- Reusable stream — create once, cache + reuse; bind to broadcast
- Health monitoring — poll
liveStreams.listhealthStatus+configurationIssues[], surface banner only on warning/error - Live chat — poll
liveChat/messages, render in right panel, support Super Chat + membership badges - Error handling — the YouTube error codes:
errorStreamInactive,invalidTransition,redundantTransition,liveStreamDeletionNotAllowed,liveStreamModificationNotAllowed,liveBroadcastBindingNotAllowed - Visibility picker — Private/Unlisted/Public from the go-live dialog
- Full broadcast form — Core + Advanced tabs with all API-supported fields