Initial Commit
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
# 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:
|
||||
|
||||
1. `<AudioStreamProvider>` — owns one `StreamSession` instance per provider, nested under `<AudioPlayerProvider>` (or any `<AudioProvider>`); accepts an injectable signalling adapter (default: WebSocket signalling).
|
||||
2. Hooks: `useAudioStream(participantId)`, `usePeerStreams()`, `useStreamControls()`, `useStreamReconnect()`, `useStreamMixer()`, `useStreamInterruption()`.
|
||||
3. Components: `<RemotePeerStrip>`, `<StreamMixer>` (per-peer level/mute/solo + transport-share toggle), `<StreamHealthIndicator>` (latency, packet loss, codec), `<StreamReconnectToast>`.
|
||||
4. Auto-reconnect with exponential back-off + interruption classification (network vs media-permission vs server-disconnect).
|
||||
5. 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.
|
||||
6. 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
|
||||
|
||||
```text
|
||||
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>`'s `multiPeer` option consumes this package's `use-multi-peer-sync` hook through an optional subpath; created against this spec)
|
||||
|
||||
No other dependents (verified by `bunx turbo ls --filter=...@suaveplan/react-audio-stream`).
|
||||
Reference in New Issue
Block a user