94f015044a
The open creator report ('I still cannot post a chat message in the TEST tab',
feedback 'Chat polling couldn't start — Mock Chat Input is disabled') was a single
cause: the liveChatId never resolved. Two YouTube API facts:
1. The id lives in snippet.liveChatId — contentDetails has no such property
(TASK 44 read part=contentDetails: could never resolve).
https://developers.google.com/youtube/v3/live/docs/liveBroadcasts
2. It only exists once the broadcast is LIVE — the official sample lists
broadcastStatus=active, and our fetch ran before the frame pump pushed RTMP
(enableAutoStart flips ready→live). A ready-state list legitimately returns
no id.
https://github.com/youtube/api-samples/blob/master/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/GetLiveChatId.java
Fix: GetBroadcastLiveChatIdAsync reads part=snippet and polls with a bounded
retry (10x/2s); PrepareAndStartLiveAsync starts the frame pump FIRST, then
resolves the id. Chat stays non-fatal. Docs ai.md/TASKS.md/HANDOFF.md +
MyMistakes recipe updated same commit. TASK 44.
Good Dog: ONE integration test (GetBroadcastLiveChatIdAsync_Polls_Snippet_...
) drives a broadcast that gains its id mid-retry and asserts every request used
part=snippet. Gate: clean build 0 warnings, vstest 318/318.
3.4 KiB
3.4 KiB
TASK 44 — TEST-tab chat fix: resolve the liveChatId (snippet + live-timing)
Catalog:
TASKS.md. Status: ✅ SHIPPED 2026-09-25 — the open creator report from HANDOFF ("I still cannot post a chat message in the TEST tab") diagnosed and fixed as its own scoped unit.
Provenance
- 2026-09-24, HANDOFF filed the creator report as open: "I still cannot post a chat
message in the TEST tab." The TEST drawer's Mock Chat Input posts a real
liveChat/messages.insert; the drawer only enables it when a liveChatId is resolved. - 2026-09-25 diagnosis: the reported feedback line "Chat polling couldn't start —
Mock Chat Input is disabled" is
TestSessionViewModel.BeginTestrunning with a null liveChatId. That id comes fromYouTubeStreamService.GetBroadcastLiveChatIdAsync, and two API facts (from the official liveBroadcasts reference + theGetLiveChatId.javasample) pin why it never resolved:- It lives under
snippet.liveChatId—contentDetailshas no such property at all. The code requestedpart=contentDetailsand readcontentDetails.liveChatId, a path that can NEVER resolve. - YouTube only populates it once the broadcast is
live(the official sample listsbroadcastStatus=active). The fetch ran right after broadcast insert (lifecycleStatusready) AND before_framePump.StartAsync()pushed the RTMP stream thatenableAutoStartneeds to flip the broadcast to live — so even the correct property would have been empty at fetch time.
- It lives under
What shipped
Services/YouTubeStreamService.cs:GetBroadcastLiveChatIdAsync(broadcastId, maxAttempts = 10, delayMs = 2000)now requestspart=snippetand readssnippet.liveChatId, and polls with a bounded retry until the id appears or the attempts exhaust (never throws). The default retry (~20s) gives the encoder time to connect and the broadcast to go live.- New private
FetchLiveChatIdAsyncholds the single read; the public method owns the retry loop.
ViewModels/MainViewModel.Streaming.Operations.cs:PrepareAndStartLiveAsyncstarts the frame pump FIRST, then resolves the liveChatId — the reorder is required for the id to ever exist. Chat remains non-fatal: failure logs and the stream continues.- TEST drawer wiring preserved:
TestSession.BeginTest(broadcastId, liveChatId)still opens the dock once the id resolves → Mock Chat Input becomes sendable.
- Docs:
ai.md(Test Stream section),TASKS.md(row 44),HANDOFF.mdrewritten.
Validation (Good Dog: ONE integration test)
ytLive.Tests/YouTubeStreamServiceTests.cs:
GetBroadcastLiveChatIdAsync_Polls_Snippet_Until_Id_Appears — a fake broadcast that
starts WITHOUT a liveChatId (not yet live) and gains it on a later poll; asserts the
retry eventually resolves Cg0LIVECHAT42, that it polled ≥3 times, and that every
request asked for snippet (never contentDetails) — the exact seam that was broken.
Gate: clean build 0 warnings; full vstest 318/318 passed.
Reference
- https://developers.google.com/youtube/v3/live/docs/liveBroadcasts (snippet.liveChatId; contentDetails has no liveChatId)
- https://github.com/youtube/api-samples/blob/master/java/src/main/java/com/google/api/services/samples/youtube/cmdline/live/GetLiveChatId.java (sample lists broadcastStatus=active — id only present on live broadcasts)