Files
LlamaCasty/TASKS/task-50-publish-recording.md
T

6.4 KiB
Raw Blame History

TASK 50 — One-button "Publish this video" (resumable upload of the local recording)

Catalog: TASKS.md — status and requirements live here. Carved 2026-09-28 from a creator ruling: "For me, as a creator, I'd love a one-button publish this video feature. Who wouldn't?"

Status: ☐ Queued — creator-ruled, not yet scoped in detail

Goal: turn the local REC-side MP4 into a channel video with one button, and stop relying on YouTube's silent automatic archiving to get a recording onto the channel at all.

Size: S–M. Media already exists; the work is a resumable-transfer lifecycle. Not a quarter.


Why

Two reasons, and the second is the one that actually justifies it.

1. It fixes a defect the creator already reported as broken. On 2026-09-26 the creator could not get private test recordings saved to YouTube, and used the local recording as the proof of concept instead. The mechanism is now understood and CONFIRMED empirically (creator inspected the channel 2026-09-28: 20+ private videos, all content-less placeholders). A deliberate upload is the actual fix; the current behaviour is a side-effect nobody designed.

2. It is not the heavy feature it looks like. The instinct is to call upload a big risky addition because it moves bytes. It doesn't: ffmpeg already moves the media, and the recording already exists as a finished local MP4. The genuine new work is a discrete long-running job with a lifecycle — resumable, with progress, retry, cancel and quota. RTMP has none of that because the connection belongs to the encoder process and simply reconnects. Different protocol, different failure model. That is the whole cost.

Creator ruling, verbatim: one button. Not a media manager, not a playlist tool.


Mechanism — CORRECTED 2026-09-28 (creator's channel inspection disproved the earlier model)

Verified against the code AND against the creator's channel:

  • liveBroadcasts.insert creates a placeholder video on the channel for every broadcast the app makes — that is the source of the 20+ private videos. The creator confirmed 2026-09-28: a couple dozen+ private videos, all scheduled placeholders with NO content.
  • Content arrives only if the stream is actually pushed and archived: broadcast reaches LIVE (liveBroadcasts/transition), ffmpeg pushes RTMP to the bound stream key, and the broadcast ends long enough to be transcoded. Content-less placeholders mean the stream never lands — one of those three steps fails in practice.
  • enableAutomaticArchiving is never set by the app, so YouTube's true default applies.
  • Broadcasts are inserted with privacyStatus = "private" (Services/YouTubeStreamService.cs:49), so those orphans are not public. That is correct and must stay.
  • The app has no delete path — nothing in Services/ deletes a broadcast or a video. The creator clears each orphan by hand in Studio.

Consequence for the original 2026-09-26 complaint: it was correct. The private recordings never saved to YouTube because no video content was ever produced on the channel — not because the app couldn't reach a VOD that existed. The upload pipeline (broadcast → LIVE → RTMP push → archive) fails; only broadcast creation succeeds.

The one diagnostic question to answer before this task is scoped

During a real test stream, does ffmpeg actually reach a.rtmp.youtube.com, and does the broadcast reach the LIVE state? If the encoder never starts or the transition never fires, that is the observed bug — and it is worth a fix BEFORE any publish feature, because this task's premise ("the recording can get to YouTube") depends on it.

Sequencing constraint — do not flip the flag early

enableAutomaticArchiving: false is the correct end state: the app uploads the local file deliberately, on demand, instead of YouTube archiving silently. But automatic archiving is currently the only route a recording takes to YouTube. Setting it to false before publish ships would leave test streams with nothing on the channel at all and re-create the 2026-09-26 complaint in a worse form.

Therefore: ship the upload first, flip the flag as part of the same task, never before.


Design notes

  • Source is the local MP4, not the YouTube archive. The app already has it (REC side, EncoderOptions.RecordPath); the archived VOD is a duplicate and an orphan.
  • Resumable upload is mandatory, not optional. Stream-length recordings are large (hours of 4–8 Mbps video); a plain single POST is not viable. YouTube's videos.insert supports resumable sessions, and the failure mode that matters is a drop at 80%.
  • Default visibility must be private or unlisted, never public. A bad take going public is unrecoverable, and this app is used for test streams by definition. The creator picks, and the default is the safe one.
  • A title still has to come from somewhere. One button, not zero decisions: default to the recording's filename, allow an edit, do not block on it.
  • Quota: videos.insert costs 1600 units against a 10,000/day project allowance — roughly six uploads per day. Fine for a creator, but it is a real ceiling and the app should surface a quota error rather than retrying into it.
  • Scope already permits it: the single auth/youtube scope covers upload. No scope change needed.

Open question to settle before coding

Microsoft Store 11.12 (User-Generated Content). The standing answer is that the app hosts no user content and does not interact with third-party UGC — chat is read-only and never persisted, which is load-bearing for that answer. A publish feature makes the app push creator content to a third-party platform, which touches the same area. It does not obviously break the answer (the destination is YouTube, which has its own mature moderation, and the app stores nothing), but it must be re-checked against research-store-certification.md §11.12 and the IARC answers in task-48 before submission — do not let the IARC answers go to certification describing an app that cannot publish.


Precedence

Belongs to TASK 48 (MSIX/Store), but does not block the Store submission: the app is fully shippable without it. Recommend MSIX submission first, publish second — unless the creator reverses that, in which case it moves ahead of the remaining TASK 48 items.