Skip to content

feat(ws): drop embedded audio from CAL messages#26

Merged
revtex merged 1 commit intodevfrom
feat/ws-drop-embedded-audio
Apr 25, 2026
Merged

feat(ws): drop embedded audio from CAL messages#26
revtex merged 1 commit intodevfrom
feat/ws-drop-embedded-audio

Conversation

@revtex
Copy link
Copy Markdown
Owner

@revtex revtex commented Apr 25, 2026

⚠️ DO NOT MERGE ALONE ⚠️

This PR breaks live audio playback for the current frontend. The frontend rewrite PR (Phase 3) must merge immediately after this one. They form a paired hard cut. Do not deploy dev to production between the two merges.

Summary

WebSocket CAL messages no longer carry embedded base64 audio. The listener WS becomes a pure metadata/notification channel; clients fetch audio on demand via the existing GET /api/calls/:id/audio HTTP endpoint, authenticated via the os_session cookie shipped in the previous PR.

Changes

File Change
backend/internal/ws/messages.go NewCALMessage(payload) — second []byte parameter removed; no audio key in the payload
backend/internal/ws/hub.go Docstring updated; no signature change (already received pre-built bytes)
backend/internal/handler/calls/upload.go Removed the os.Root + io.LimitReader audio read whose sole consumer was the WS payload. Unused imports cleaned.
backend/internal/dirmonitor/watcher.go Same — dropped the WS-only audio read
backend/internal/ws/messages_test.go Dropped the embedded-audio test; new guard asserts marshalled CAL contains no "audio": substring
CHANGELOG.md Bullet under [Unreleased] ### Changed

Wire-size impact

A typical CAL was 30–80 KB depending on the codec and call duration (base64 inflates by ~33 %). Going forward each CAL is a small JSON object — under 2 KB in practice. The audio file is downloaded once via HTTP with full Range support and benefits from the browser HTTP cache on replay.

Verification

  • go vet ./... — clean
  • go build ./... — clean
  • go test ./... — all pass
  • rg '"audio":' backend/internal/ — only test assertions confirming absence
  • rg 'audioData' backend/internal/ws/ — zero hits

Self-review

  • No protocol versioning. The single-binary deployment model means server and SPA always ship together; a soft transition would be pure cost.
  • No security surface change. The audio GET endpoint already enforces grants and publicAccess semantics; this PR removes a duplicate delivery channel, not an authorization layer.
  • Hub no longer reads disk during fan-out — measurable memory and IO win at higher listener counts.

Pairing

The frontend rewrite (Phase 3) is on branch feat/audio-element-playback (will be opened next). Merge sequence:

  1. Merge this PR.
  2. Merge the Phase 3 PR immediately.
  3. Tag a release (Mobile Edge AAC fix is user-visible).

- NewCALMessage signature changed to (payload) — second []byte parameter
  removed; payload is metadata only, no "audio" field.
- ws.Hub.BroadcastCAL no longer touches the disk: docstring updated to
  reflect that audio is fetched on demand by clients via
  GET /api/calls/:id/audio. The hub already received pre-built bytes,
  so no signature change there.
- handler/calls/upload.go and dirmonitor/watcher.go: removed the
  os.Root + io.LimitReader audio read whose sole consumer was the WS
  payload. Unused 'io' / 'os' imports cleaned up.
- ws/messages_test.go: dropped TestNewCALMessage_WithAudio; updated
  TestNewCALMessage to call the new single-arg signature and added a
  bytes.Contains guard asserting the marshalled frame contains no
  "audio": substring.
- CHANGELOG: bullet under [Unreleased] ### Changed.

Frontend client will be updated in the next PR — current SPA build will
lose live audio playback once this merges; ship the frontend rewrite PR
immediately after.
@revtex revtex merged commit 0ef1aff into dev Apr 25, 2026
7 checks passed
@revtex revtex deleted the feat/ws-drop-embedded-audio branch April 25, 2026 20:20
revtex added a commit that referenced this pull request Apr 25, 2026
#27)

- Replace base64-over-WS + Web Audio decode pipeline with a single
  persistent hidden HTMLAudioElement, wired through
  MediaElementAudioSourceNode → GainNode → AudioContext.destination so
  the existing volume slider and gain graph keep working.
- WS client no longer parses or holds an audio callback; on CAL it
  dispatches callReceived(call) to Redux. A new listener middleware
  drives the player off the calls slice.
- Per-call playback flow: audio.src = /api/calls/:id/audio, preload
  auto, play() on canplay, advance queue on ended/error.
- Download buttons in BookmarksPanel and SearchPanel are now plain
  <a download> anchors pointing at the same authenticated endpoint.
- Shared-call page uses <audio src=/api/shared/:token/audio> directly.
- Autoplay-unlock now also primes the persistent <audio> element
  inside the user-gesture handler (play().then(pause)) so subsequent
  programmatic play() calls succeed on Mobile Edge / Mobile Safari.
- Tests updated to drive the new flow; 188 frontend tests pass.

Pairs with backend PR #26 dropping audioData from CAL frames; merge
that one first, then this.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant