Files
LlamaCasty/TASKS/task-65-replay-clips.md
T
gramps ec6a5ca466 docs(queue): six veggies, then the new work; scheduling and publishing retired
Creator ruling 2026-11-09: finish the queue before the new features, gold pass always last.

**Retired (platform's surface, not ours):**
- 34 scheduled streams — YouTube owns scheduling *and* the reminder that makes it worth anything.
- 50 publish recording — Studio owns upload (resumable, quota-aware, explains rejections), and an
  in-app uploader would widen the OAuth consent to whole-channel video management for one convenience.
  The app adds "Show in folder" instead.

**New tasks:** 65 replay clips (the creator-side buffer YouTube does not give you), 66 timed ticker
messages, 67 per-event alert videos, 68 edit-while-live + first-run On-Air.

**TASK 65 spec** is the interesting one: 15 s is a clip (10/15/20, default 15); the ring holds encrypted
*encoded* fragments in RAM — raw 1080p frames would be ~7.4 GB for 15 s — so there is no steady disk
write and no crash debris; F10 saves; the replay layer plays once then hides in Live and loops the last
1–3 elsewhere; silent by default; three kept; the layer is excluded from its own clip (hall of mirrors).

**TASK 14 gains Branch 3:** mic input gain ahead of the gate (table boom mics fall under it), webcam
blank hotkey, opacity/geometry parity with a collapsed Geometry disclosure, Show-in-folder.

**Decisions recorded:** the replay-buffer reversal (it was retired in 2022-era reasoning as "different
product"; the case for it won), the platform-surface rule, and voice triggering deferred — always-
listening in a streaming app hears the game, so the content is its own false-positive source.

Queue refactored to 56 lines by archiving completed rows and the superseded surge plan; HANDOFF at 40.
2026-11-09 14:27:07 -08:00

66 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# TASK 65 — Replay clips: buffer the last 15 seconds, show it, save it
> Catalog: [`TASKS.md`](../TASKS.md) — status and requirements live here.
> Spec settled with the creator 2026-11-09. **Not a Twitch-clip clone:** the platform owns viewer
> clips; this is the creator-side replay buffer YouTube does not give you.
## The rule
**15 seconds is a clip.** Options 10 / 15 / 20, default **15**, no slider, no 30. A clip is a moment,
not a segment — 3-minute Shorts are the platform's problem, not ours.
## Why the ring holds encoded bytes, not frames
A 1080p BGRA composite frame is 8.3 MB; fifteen seconds at 60 fps is **~7.4 GB** of raw frames. The
15 MB figure is *after* compression. So the ring keeps **fragmented MP4** (`frag_keyframe+empty_moov`)
that ffmpeg writes to a pipe, in a **byte ring in RAM** — never on disk, never raw.
- Fragments are **1 s** (not 2): the ring can only hand back whole fragments, so a longer fragment
means the save can miss the punchline.
- The buffer is capped **by bytes**, not seconds — bitrate moves. When 15 s would exceed the cap, the
clip is simply shorter.
- The ring is a member of the process: it dies with the app, so a crash leaves no debris and needs no
sweep. **Nothing touches the disk until F10.**
## Trigger
**F10** saves the clip (F1–F9 are taken; F11 is the fallback if a game steals F10). No focus switch, no
mouse. Deferred deliberately: **voice triggering** (always-listening in a streaming app is a privacy
liability, and the game's own audio produces false positives) and **`!clip`** (only for viewers/mods,
never the creator, who cannot reach a keyboard mid-moment).
## The replay layer
One layer type, added by the creator to the scenes they want; behaviour comes from the scene:
| Scene | Behaviour |
|---|---|
| **Live** | plays the new clip **once**, then **hides** — you're there to see it or you're not |
| Every other scene | loops the last **1–3** saved clips **in order** (highlight reel), configurable |
- **Audio off by default**, toggleable per layer. The show's sound design is the creator's; a replay
should not re-mix it uninvited.
- **The replay layer is excluded from the clip's own composition.** Otherwise saving while a clip plays
records a video of a video (hall of mirrors). Viewers still see it live; the clip simply doesn't.
## Storage and retention
- Saved to `clips\` beside recordings, as a normal `.mp4`.
- **The three most recent are kept**; the fourth deletes the oldest.
- **Auto-clip on monetization events** (off by default): a Super Chat / membership / raid saves the
preceding 15 s hands-free. Same retention, so it cannot accumulate.
- **Disk discipline:** no steady writes while live (the ring is RAM); the free-space guard that already
protects REC also disables the ring when space is low — **the recording always wins**.
## Privacy
Named in `PRIVACY.md`: clips are local only, the three most recent are kept, older ones are deleted
automatically, and nothing is uploaded. The first save says the same in one line, so the policy is not
only a document.
## Tests
- Ring: fragment boundaries respected, byte cap enforced, save emits a playable MP4, oldest pruned.
- Layer: once-then-hide in Live, in-order loop elsewhere, silent by default, layer excluded from the clip.
- Failure: save with an empty ring (just started) says so instead of writing a 0-byte file.