Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -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`).