6.1 KiB
OpenSpec Change: enterprise-react-audio-stream
- Change ID: enterprise-react-audio-stream
- Package:
@suaveplan/react-audio-stream - Category: react
- Target path:
packages/ui/react/react-audio-stream - Status: PROPOSED
- Date: 2026-05-15
- Design:
./design.md - Spec delta:
./specs/react-audio-stream/spec.md
Replaces the prior 2026-04-24 draft flagged
NEEDS-REWRITE. See../REACT_AUDIO_WAVE_REWRITE_COMPLETE.md.
Summary
Deliver @suaveplan/react-audio-stream on genesis from scratch at enterprise quality. The package provides WebRTC-based real-time audio streaming for the React audio surface. It is transport-agnostic at its core (a StreamSession abstraction with peer fan-out) and ships two transport implementations: WebRTC (default) and WebSocket (server-relay fallback). Sessions are integrated with the unified architecture: a remote peer's incoming audio is materialised as an AudioPlayerPlugin-shaped source on a dedicated chain (so it benefits from FX, sidechain ducking, analyser readouts), and the local outgoing audio is captured via the engine's tap-to-bus surface from any track's post-FX point.
The package exposes:
<AudioStreamProvider>— owns oneStreamSessioninstance per provider, nested under<AudioPlayerProvider>(or any<AudioProvider>); accepts an injectable signalling adapter (default: WebSocket signalling).- Hooks:
useAudioStream(participantId),usePeerStreams(),useStreamControls(),useStreamReconnect(),useStreamMixer(),useStreamInterruption(). - Components:
<RemotePeerStrip>,<StreamMixer>(per-peer level/mute/solo + transport-share toggle),<StreamHealthIndicator>(latency, packet loss, codec),<StreamReconnectToast>. - Auto-reconnect with exponential back-off + interruption classification (network vs media-permission vs server-disconnect).
- Transport-share mode: a designated peer's transport play/pause/seek events drive every connected peer's local transport so collaborative listening stays in sync.
- OTel instrumentation (active sessions gauge, peer-connect / disconnect counters, ICE-failure counter, RTT histogram).
The package owns no DSP, no audio context, no codec implementation — every audio surface goes through @suaveplan/react-audio hooks; WebRTC peer streams become first-class source plugins on dedicated chains.
Current-state audit (genesis)
The package does not exist on genesis yet — fresh build replacing the obsolete pre-tier 2026-04-24 draft. The upstream react/media/react-audio-stream/ is layered on the monolithic @suaveplan/react-audio plugin surface; this rewrite re-derives every behaviour against the unified architecture.
Parity Checklist (vs upstream)
| Capability | Upstream | Migrated | Notes |
|---|---|---|---|
ReactAudioStream plugin class |
✅ | ⬆️ | Replaced by the StreamSession abstraction + per-peer AudioPlayerPlugin-shaped sources. |
| Session management | ✅ | ✅ | Now formal lifecycle: connect/join/leave/disconnect with FSM. |
| Peer stream fan-out | ✅ | ✅ | Per-peer MediaStream → MediaStreamTrack → engine source plugin. |
| Per-stream mixing controls | ✅ | ⬆️ | Each peer gets a track + chain in the engine; user controls = <StreamMixer> over useStreamMixer. |
| Effect routing | ✅ | ⬆️ | Per-peer chains support any FX from audio-fx-plugin-base. |
| Transport-control sharing | ✅ | ⬆️ | Single designated peer drives transport; explicit transfer-of-control. |
| Auto-reconnect | ✅ | ✅ | Exponential back-off with cap; user-overridable. |
| Interruption classification | ✅ | ✅ | Network / permission / signalling / peer / unknown buckets. |
| WebSocket transport | partial | ✅ | First-class equal-peer transport. |
| Storybook coverage | ⚠ | ✅ | Every component default + interactive + edge. |
| Coverage | ~82 % | ✅ | 100/100/100/100. |
No 🚫 rows.
Available workspace deps on genesis
| Package | Role |
|---|---|
@suaveplan/react-audio (workspace:^) |
Provider + hooks |
@suaveplan/audio-fx-plugin-base (workspace:^) |
PluginChain, source plugin shape |
@suaveplan/audio-transport (workspace:^) |
Transport for share mode |
@suaveplan/network-transport-websockets (workspace:^) |
Default WebSocket transport |
@suaveplan/network-discovery-trystero (workspace:^) |
Optional Trystero (BitTorrent-tracker WebRTC signalling) transport |
@suaveplan/fsm (workspace:^) |
Session lifecycle state machine |
@suaveplan/retry (workspace:^) |
Exponential back-off for reconnect |
@suaveplan/error, @suaveplan/types, @suaveplan/opentelemetry, @suaveplan/events |
foundations |
react (peer), zustand, zod |
File layout
packages/ui/react/react-audio-stream/
src/
index.ts
error-codes.ts
provider/
audio-stream-provider/
provider-options/
session/
stream-session/
session-fsm/
peer-channel/
stream-source-plugin/
interruption-classifier/
transports/
webrtc/
websocket/
trystero/ ← optional subpath
hooks/
use-audio-stream/
use-peer-streams/
use-stream-controls/
use-stream-reconnect/
use-stream-mixer/
use-stream-interruption/
use-transport-share/
components/
remote-peer-strip/
stream-mixer/
stream-health-indicator/
stream-reconnect-toast/
__benchmarks__/
session-fanout.bench.ts
tests/
integration.test.tsx
purity.test.ts
exports.test.ts
e2e/
two-peer-sync.spec.ts
Impact
Breaking changes: none — fresh build.
Prerequisites: react-audio, audio-fx-plugin-base, audio-transport, network-transport-websockets, fsm, retry, foundations.
Affected dependents
@suaveplan/react-audio-player— [ ] tests run / [ ] docs reviewed / [x] no action needed (reason:<PremiumPlayer>'smultiPeeroption consumes this package'suse-multi-peer-synchook through an optional subpath; created against this spec)
No other dependents (verified by bunx turbo ls --filter=...@suaveplan/react-audio-stream).