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.
3.6 KiB
3.6 KiB
ytLlive — YouTube Live API research facts (authoritative)
YouTube Live API — research facts (authoritative, v3 build)
Lifecycle: created → ready → [testing] → live → complete (transitional liveStarting / testStarting).
- liveBroadcasts.insert requires:
snippet.title,snippet.scheduledStartTime,status.privacyStatus,status.selfDeclaredMadeForKids(COPPA). - liveStreams.insert requires:
snippet.title,cdn.frameRate,cdn.ingestionType,cdn.resolution. None of the four (except title) can ever change after creation — changing them means delete + recreate the stream. This is the hard constraint behind the quality grey-out. - Title / description / privacy: editable at any time, including while live (
liveBroadcasts.update, part=snippet,status). - contentDetails (DVR, recordFromStart, monitorStream, embed, latency): editable only in
created/ready. - Transition to live only allowed when the bound stream's
status.streamStatus == active.
Two features that reshape the design
- enableAutoStart / enableAutoStop — instant one-click go-live, no transition call. With
enableAutoStart=truewe never calltransition(live): the broadcast auto-goes-live the moment the encoder starts. Combined withenableMonitorStream=false(our preview pane replaces YouTube's monitor stream — the thing that forces a testing stage), the flow is create → bind → Start Stream → encoder starts → YouTube brings it live. No testing, no transition polling, no liveStarting stuck-state handling. cdn.resolution=variable/cdn.frameRate=variable— free auto step-down. YouTube auto-detects what we send; since we ARE the encoder we can drop bitrate/resolution on the fly with zero API calls. Declaring an explicit resolution instead (e.g. 1080p) requires a new stream, which can't happen mid-broadcast. Variable is the enabler for the whole auto step-down feature. (Claim-check 2026-09-01: the enabler is real, the governor is not built — the drop-side policy ships as TASK 33, v1 per the complete-v1 ruling.)
Compliance gotchas (maps perfectly to report-by-exception)
liveStreams.status.healthStatus:good | ok | bad | noDataplusconfigurationIssues[]withtype+severity(info|warning|error). Literally built for report-by-exception — poll it, render nothing on good/ok, surface a banner only on warning/error. No need to invent our own health logic.- Encoder must comply or YouTube flags it: keyframes ≤ 4s (
gopSizeLong), closed GOP, H.264, audio AAC/MP3 @ 44.1/48kHz, mono/stereo only. - Error codes to handle:
errorStreamInactive,invalidTransition,redundantTransition,liveStreamDeletionNotAllowed,liveStreamModificationNotAllowed,liveBroadcastBindingNotAllowed.
Tips we should take advantage of
- Reusable streams (
isReusable=true): one stream per channel, cache its ingestion URL + stream name, reuse for every broadcast. No rebinding dance each go-live. This is exactly the manual-stream-key baseline. - Backup ingestion address: YouTube provides a simultaneous-push backup — future hardening, not v1.
recordFromStart+enableDvrdefault true → every live is auto-recorded and immediately replayable. Free VOD archive, matches the v0.2 recording goal.latencyPreference:normal | low | ultraLow— for homelab streamers talking to chat,low(orultraLow, capped at 1080p) is a real feature.- Broadcast ID == Video ID — one ID to track everything.