feat(recording): auto-record on go-live + server-driven finalize (#169)#180
Merged
Conversation
…ace write failures Make show recording automatic and resilient to the browser lifecycle, and stop silently swallowing recording write failures. Closes #169 (Phase 1 of #164). - Auto-start recording when a live stream goes live: the show id is passed via `/ws/stream?show_id=N` and the backend starts the tee on connect (no separate frontend call). Reconnects are a no-op that resume the existing archive. - Grace-period finalize: a WS drop no longer ends the recording. A 30s timer (FINALIZE_GRACE) lets a reconnect resume the same archive instead of fragmenting it; explicit stop ('stop' msg / POST /api/stream/stop) finalizes immediately. Decouples the archive from a dropped tab. - Extract finalize_and_upload(state) + ensure_recording_started(state, show_id) as the single source of truth, reused by the HTTP stop endpoint, the WS lifecycle, and the grace task (idempotent: one upload per session). - Surface recording write failures: write_chunk now logs at error, sets recording_failed on StreamStatus, drops the corrupt file handle, and marks the DB recording version 'failed' — instead of warn!+Ok. Live stream is unaffected. - Frontend: useStreamSocket.connect(force, showId) carries show_id across reconnects; FlowWaiting/FlowOnAir drop their recordingApi.start() calls.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #169 — Phase 1 of the stream rework (#164).
What
Makes show recording automatic and resilient to the browser lifecycle, and stops silently swallowing recording write failures.
Auto-record on go-live (server-driven)
/ws/stream?show_id=N. The backend starts the recording tee on connect — no separatePOST /api/recording/startfrom the frontend.Grace-period finalize (decoupled from the tab)
FINALIZE_GRACE) lets a reconnect resume the same archive.'stop'message orPOST /api/stream/stop) finalizes immediately.finalize_and_upload(state)+ensure_recording_started(state, show_id)are the single source of truth, reused by the HTTP stop endpoint, the WS lifecycle, and the grace task. Idempotent — exactly one upload per session (manager.stop()takes the session).Surface write failures
stream_bridge::write_chunknow logs aterror!, setsrecording_failedonStreamStatus, drops the corrupt file handle, and the finalized DB version is markedfailedwith the error — instead ofwarn!+Ok. The live broadcast is unaffected.Files
backend/:stream_bridge.rs,handlers/recording.rs,handlers/stream_ws.rs,main.rs(newrecording_finalizerabort handle onAppState).frontend/:useStreamSocket.ts(carriesshow_idacross reconnects),FlowOnAir.vue/FlowWaiting.vue(drop redundantrecordingApi.start()).Verification
cargo build/fmtclean;clippyshows only pre-existing warnings in touched files.npm run lintclean;npm run typecheckfails identically on the clean base (.vueresolution — environmental), no new errors.cargo testnot run: pre-existing broken test target (recording.rs:440,u64 >= 0). These paths are integration-level (WS/S3/ffmpeg).Follow-ups (not in this PR)
flow.recordStream) is now vestigial — recording is always automatic. Worth removing/repurposing.recordingApi.stop()calls remain in FlowOnAir/FlowStreaming; harmless (same idempotent finalize path) but cleanable.