Files
skills/docs/ui/react/react-audio-stream
2026-05-29 08:20:56 +01:00
..
2026-05-29 08:20:56 +01:00
2026-05-29 08:20:56 +01:00

@suaveplan/react-audio-stream - Stream-tier React surface for the Suaveplan audio family — session-core foundation (chunk A). Provides StreamSession (FSM lifecycle), InterruptionClassifier, StreamSourcePlugin, error codes, and OTel instruments. Transports, hooks, components, and transport-share land in chunks B/C/D.

React 19 surface for live audio streaming sessions: a Provider, six hooks, and four accessible components. Chunk C of the four-chunk enterprise-react-audio-stream split.

Chunks A (session-core) and B (transports) deliver the headless engine. Chunk D delivers useTransportShare and its banner. This chunk delivers the React surface consumers actually touch.

Documentation tree

  • shared-transport-indicator — SharedTransportIndicator renders the spec-mandated "Shared transport active" badge whenever the local peer is in `'re…
    • shared-transport-indicator — SharedTransportIndicator renders the spec-mandated "Shared transport active" badge whenever the local peer is in `'re…
  • stream-mixer — <StreamMixer> renders one strip per remote peer, each with a volume range slider, a mute toggle, a solo toggle, and a…
    • stream-mixer — <StreamMixer> renders one strip per remote peer, each with a volume range slider, a mute toggle, a solo toggle, and a…
  • stream-permissions-banner — <StreamPermissionsBanner> is the visible counterpart to useStreamPermissions(). It renders a role="status" ARIA-l…
    • stream-permissions-banner — <StreamPermissionsBanner> is the visible counterpart to useStreamPermissions(). It renders a role="status" ARIA-l…
  • stream-recorder — <StreamRecorder> is a record/stop control with a live duration display. It delegates recording lifecycle to `useStrea…
    • stream-recorder — <StreamRecorder> is a record/stop control with a live duration display. It delegates recording lifecycle to `useStrea…
  • stream-room — <StreamRoom> is the headless layout primitive for the room scope. It renders no markup of its own — instead it expose…
    • stream-room — <StreamRoom> is the headless layout primitive for the room scope. It renders no markup of its own — instead it expose…
  • error-codes — The error-codes module is the canonical source of truth for every failure mode published by `@suaveplan/react-audio-str…
    • error-codes — The error-codes module is the canonical source of truth for every failure mode published by `@suaveplan/react-audio-str…
  • internal — Internal helper consumed by every public chunk-C hook. It reads the StreamReactContext, returns the non-null `{ sessi…
    • use-stream-context — Internal helper consumed by every public chunk-C hook. It reads the StreamReactContext, returns the non-null `{ sessi…
  • use-stream-levels — useStreamLevels projects realtime peak/RMS samples out of the session. Called without an argument it returns the loca…
    • use-stream-levels — useStreamLevels projects realtime peak/RMS samples out of the session. Called without an argument it returns the loca…
  • use-stream-mixer — useStreamMixer exposes per-peer mixer controls — level, mute, solo, and the per-peer FX slot count — and implements D…
    • use-stream-mixer — useStreamMixer exposes per-peer mixer controls — level, mute, solo, and the per-peer FX slot count — and implements D…
  • use-stream-peers — useStreamPeers returns the live remote-peer roster as a stable readonly Peer[]. Each peer entry carries the partici…
    • use-stream-peers — useStreamPeers returns the live remote-peer roster as a stable readonly Peer[]. Each peer entry carries the partici…
  • use-stream-permissions — useStreamPermissions exposes the microphone permission state with the typed MediaPermissionState enum (`"granted" |…
    • use-stream-permissions — useStreamPermissions exposes the microphone permission state with the typed MediaPermissionState enum (`"granted" |…
  • use-stream-recording — useStreamRecording exposes the start/stop controls for capturing a session as a single audio file. The hook delegates…
    • use-stream-recording — useStreamRecording exposes the start/stop controls for capturing a session as a single audio file. The hook delegates…
  • use-stream-room — useStreamRoom projects the current room scope out of the session: the room id (or null when the session is not conn…
    • use-stream-room — useStreamRoom projects the current room scope out of the session: the room id (or null when the session is not conn…
  • use-stream-session — useStreamSession is the entry-point hook for chunk-C consumers. It returns the live StreamSession instance, its cur…
    • use-stream-session — useStreamSession is the entry-point hook for chunk-C consumers. It returns the live StreamSession instance, its cur…
  • use-transport-share — useTransportShare is the React entry point to the transport-share subsystem. It composes a `TransportShareCoordinator…
    • use-transport-share — useTransportShare is the React entry point to the transport-share subsystem. It composes a `TransportShareCoordinator…
  • stream-context — StreamReactContext is the single React context that publishes the live StreamSession to every chunk-C hook and comp…
  • stream-provider — <StreamProvider> is the singleton React surface that owns the live StreamSession for a tree. It calls the caller-su…
  • session — The reconnect module owns the auto-reconnect lifecycle that StreamSession runs after a disconnect interruption. It wr…
    • interruption-classifier — InterruptionClassifier maps a structural disconnect cause to exactly one of `network | media-permission | signalling…
      • interruption-classifier — InterruptionClassifier maps a structural disconnect cause to exactly one of `network | media-permission | signalling…
    • session-fsm — The session-fsm module declares the canonical seven-state finite state machine that drives every StreamSession. Bui…
      • session-fsm — The session-fsm module declares the canonical seven-state finite state machine that drives every StreamSession. Bui…
    • stream-session — StreamSession is the public face of the stream-tier session core. It wraps the FSM, the transport adapter, the interr…
      • stream-session — StreamSession is the public face of the stream-tier session core. It wraps the FSM, the transport adapter, the interr…
    • stream-source-plugin — StreamSourcePlugin is the bridge that lets a remote peer's MediaStream participate in the audio engine's plugin-cha…
      • stream-source-plugin — StreamSourcePlugin is the bridge that lets a remote peer's MediaStream participate in the audio engine's plugin-cha…
    • reconnect — The reconnect module owns the auto-reconnect lifecycle that StreamSession runs after a disconnect interruption. It wr…
  • telemetry — The telemetry module owns every OpenTelemetry instrument published by @suaveplan/react-audio-stream. Concentrating th…
    • telemetry — The telemetry module owns every OpenTelemetry instrument published by @suaveplan/react-audio-stream. Concentrating th…
  • control-channel — The control-channel module is the wire-protocol heart of transport sharing. It defines the envelope shapes that flow be…
  • share-state — The share-state module owns the role-machine that decides whether a peer is in 'local', 'driving', or 'receiving'…
  • transports — The transport.types.ts module declares the structural contract that StreamSession (authored in chunk A of the `@sua…
    • trystero — TrysteroTransport is the serverless StreamTransportAdapter powered by @suaveplan/network-discovery-trystero. It p…
      • trystero-transport — TrysteroTransport is the serverless StreamTransportAdapter powered by @suaveplan/network-discovery-trystero. It p…
    • webrtc — WebRtcTransport is the low-latency default StreamTransportAdapter for @suaveplan/react-audio-stream. It wires a c…
      • webrtc-transport — WebRtcTransport is the low-latency default StreamTransportAdapter for @suaveplan/react-audio-stream. It wires a c…
    • websocket — WebSocketTransport is the fallback StreamTransportAdapter consumers choose when a corporate or carrier NAT blocks W…
      • websocket-transport — WebSocketTransport is the fallback StreamTransportAdapter consumers choose when a corporate or carrier NAT blocks W…
    • transport — The transport.types.ts module declares the structural contract that StreamSession (authored in chunk A of the `@sua…
  • test-setup — test-setup.ts is the per-worker bootstrap file referenced by vitest.config.ts's setupFiles. It registers `@testin…
  • test-utils — test-utils.tsx provides the in-memory FakeSession and the withProvider wrapper used by every chunk-C hook + compo…

Provider

  • <StreamProvider sessionFactory={…}> — StrictMode-safe singleton; injects a StreamSession lazily; fans seven session event channels into a single render-bump counter; disconnects on unmount.
  • StreamReactContext — exposed for advanced consumers that need raw context access.
  • Type-only mirrors (SessionState, Peer, PeerMixerState, MediaPermissionState, LevelSample, RecordingResult, StreamSessionFactory, StreamSessionLike, SessionEventMap, ReactAudioStreamErrorLike) for downstream typing.

Hooks

  • useStreamSession() — session, FSM state, and connect / join / leave / disconnect.
  • useStreamRoom() — roomId, isJoined, joinedAt, participants.
  • useStreamPeers() — live readonly Peer[].
  • useStreamMixer() — per-peer setVolume / setMute / setSolo with DAW solo semantics (when any peer is soloed, every non-soloed peer's track-volume → 0). Every mutation routes through the session's setTrackVolume / setTrackMute / setTrackSolo.
  • useStreamLevels(peerId?) — { peak, rms } for the local mic or named peer.
  • useStreamRecording() — start(peerIds?) and stop() returning a RecordingResult blob.
  • useStreamPermissions() — typed MediaPermissionState with request() callback.

Components

  • <StreamRoom> — headless render-prop wrapper exposing the room snapshot plus join / leave callbacks.
  • <StreamMixer> — per-peer mixer strip with range slider, aria-pressed mute/solo toggles, FX-slot read-out; supports renderStrip render-prop.
  • <StreamRecorder> — record/stop toggle with mm:ss duration display and ARIA-live read-out.
  • <StreamPermissionsBanner> — role="status" aria-live="polite" banner; renders nothing when permission is granted.

Quick start

import { StreamProvider, useStreamSession } from "@suaveplan/react-audio-stream";

function Room() {
    const { state, connect, join } = useStreamSession();
    if (state === "idle") return <button onClick={() => connect("lobby").then(join)}>Join</button>;
    return <p>Joined!</p>;
}

export function App() {
    return (
        <StreamProvider sessionFactory={() => createMyStreamSession()}>
            <Room />
        </StreamProvider>
    );
}

Constraints (from the canonical spec)

  • Zero browser audio APIs: no AudioContext / AudioNode / AudioWorklet imports.
  • DAW solo semantics live in the mixer hook, not in each component.
  • Every hook throws REACT_AUDIO_STREAM.NO_PROVIDER outside a <StreamProvider>.