@ravenkash/rtc 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +70 -0
- package/dist/index.cjs +2333 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +622 -0
- package/dist/index.d.ts +622 -0
- package/dist/index.js +2319 -0
- package/dist/index.js.map +1 -0
- package/dist/metafile-cjs.json +1 -0
- package/dist/metafile-esm.json +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/config.ts","../src/logger.ts","../src/internal/devices/enumerate.ts","../src/internal/telemetry/track-stats.ts","../src/track.ts","../src/internal/media/errors.ts","../src/internal/telemetry/rtc-stats.ts","../src/internal/media/native-track.ts","../src/internal/media/capture.ts","../src/events.ts","../src/participant.ts","../src/internal/signaling/protocol.ts","../src/internal/signaling/signaling-client.ts","../src/internal/sfu/raven-adapter.ts","../src/internal/telemetry/connection-id.ts","../src/internal/telemetry/platform.ts","../src/internal/telemetry/telemetry-client.ts","../src/version.ts","../src/room.ts","../src/client.ts","../src/browser-support.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/** Stable typed error codes the SDK raises. Never a raw browser DOMException. */\nexport type RTCErrorCode =\n | 'INVALID_TOKEN'\n | 'TOKEN_EXPIRED'\n | 'ROOM_NOT_FOUND'\n | 'CONNECTION_FAILED'\n | 'PERMISSION_DENIED'\n | 'CAMERA_PERMISSION_DENIED'\n | 'MICROPHONE_PERMISSION_DENIED'\n | 'DEVICE_NOT_FOUND'\n | 'NETWORK_ERROR'\n | 'SIGNALING_ERROR'\n | 'MEDIA_ERROR'\n /**\n * The platform simply can't do this. Screen sharing on a mobile browser\n * with no `getDisplayMedia`, say.\n *\n * Added in the native-RTC release, and kept separate from `MEDIA_ERROR`\n * on purpose. \"This device has no such capability\" is a permanent fact a\n * UI should act on by hiding the button; `MEDIA_ERROR` is a failure worth\n * retrying. Spec §16 requires telling the two apart. Purely additive, so\n * no existing code changed meaning.\n */\n | 'NOT_SUPPORTED'\n | 'TIMEOUT';\n\n/** The only error type this SDK throws, or emits on the `error` event. */\nexport class RTCError extends Error {\n readonly code: RTCErrorCode;\n readonly cause?: unknown;\n\n constructor(code: RTCErrorCode, message: string, cause?: unknown) {\n super(message);\n this.name = 'RTCError';\n this.code = code;\n this.cause = cause;\n }\n}\n\nexport function isRTCError(value: unknown): value is RTCError {\n return value instanceof RTCError;\n}\n","import { RTCError } from './errors';\nimport type { LogLevel } from './logger';\n\nexport interface RTCClientConfig {\n /** The RTC token your backend minted through Raven's Control API. Never mint one in the browser. */\n token: string;\n /**\n * RTC infrastructure URL to connect to. It's the `endpoint` field out of\n * the same mint response as `token`. Forward both through untouched;\n * don't build this by hand.\n */\n endpoint: string;\n /**\n * The `iceServers` array from the same mint response. Optional so tests\n * and advanced setups can skip it, but ordinarily you just forward it.\n * Don't go configuring STUN/TURN by hand.\n */\n iceServers?: RTCIceServer[];\n logLevel?: LogLevel;\n /** Defaults to true. Set false to disable automatic reconnect on network loss. */\n autoReconnect?: boolean;\n /**\n * Base URL for best-effort connection telemetry. Comes from the\n * `telemetryUrl` field of the same token-mint response as `token` and\n * `endpoint`; never build it yourself. Leave it out, or set\n * `telemetry: false`, to turn telemetry off completely. RTC never\n * depends on it either way. See docs/telemetry.md.\n */\n telemetryUrl?: string;\n /** Defaults to true. Set false to switch telemetry off; RTC never needs it (Phase 9 spec §31). */\n telemetry?: boolean;\n}\n\nexport interface ResolvedRTCClientConfig {\n token: string;\n endpoint: string;\n iceServers?: RTCIceServer[];\n logLevel: LogLevel;\n autoReconnect: boolean;\n telemetryUrl?: string;\n telemetry: boolean;\n}\n\ninterface DecodedTokenPayload {\n /** The `rid` claim: the room's `rooms.id` primary key. */\n roomId?: string;\n /** The `rnm` claim: the room's display name, carried next to `rid` so this check accepts either. */\n roomName?: string;\n exp?: number;\n sub?: string;\n}\n\n/**\n * Decodes the JWT payload. Doesn't verify it; the server is the source of truth.\n *\n * Reads Raven's own claim names (`rid`/`rnm`/`sub`/`exp`, see\n * `RtcTokenClaims` in the control plane). It used to read `video.room`,\n * which was LiveKit's claim shape and stopped existing when Raven's own\n * token signer replaced it — so every field here came back `undefined` and\n * `assertTokenMatchesRoom` below silently passed everything.\n */\nexport function decodeTokenPayload(token: string): DecodedTokenPayload {\n const parts = token.split('.');\n if (parts.length !== 3) {\n throw new RTCError('INVALID_TOKEN', 'RTC token is malformed (expected a JWT with 3 parts)');\n }\n try {\n const base64 = parts[1].replace(/-/g, '+').replace(/_/g, '/');\n const json = JSON.parse(atob(base64));\n return {\n roomId: typeof json?.rid === 'string' ? json.rid : undefined,\n roomName: typeof json?.rnm === 'string' ? json.rnm : undefined,\n exp: typeof json?.exp === 'number' ? json.exp : undefined,\n sub: typeof json?.sub === 'string' ? json.sub : undefined,\n };\n } catch (error) {\n throw new RTCError('INVALID_TOKEN', 'RTC token payload could not be decoded', error);\n }\n}\n\nexport function validateConfig(config: RTCClientConfig): ResolvedRTCClientConfig {\n if (!config || typeof config !== 'object') {\n throw new RTCError('INVALID_TOKEN', 'createRTCClient(config) requires a configuration object');\n }\n if (!config.token || typeof config.token !== 'string') {\n throw new RTCError('INVALID_TOKEN', 'config.token is required; the RTC token from your backend');\n }\n if (!config.endpoint || typeof config.endpoint !== 'string') {\n throw new RTCError(\n 'INVALID_TOKEN',\n 'config.endpoint is required; the \"endpoint\" field from the same token-mint response as config.token',\n );\n }\n\n const { exp } = decodeTokenPayload(config.token);\n if (exp !== undefined && exp * 1000 <= Date.now()) {\n throw new RTCError('TOKEN_EXPIRED', 'RTC token has already expired');\n }\n\n return {\n token: config.token,\n endpoint: config.endpoint,\n iceServers: config.iceServers,\n logLevel: config.logLevel ?? 'silent',\n autoReconnect: config.autoReconnect ?? true,\n telemetryUrl: config.telemetryUrl,\n telemetry: config.telemetry ?? true,\n };\n}\n\n/**\n * Bails out client-side, before any connection is attempted, if the token\n * was minted for a different room than the one being joined. Much clearer\n * than letting the connection fail and working backwards from that.\n *\n * Either the room id or the room name is accepted, because a token carries\n * both (`rid` and `rnm`) and application code legitimately holds whichever\n * one it happened to pass to its own backend.\n *\n * A token carrying neither claim passes. That's deliberate: this is a\n * courtesy check, not authorization. The signaling gateway re-verifies the\n * signed room on every join, so the only thing a missing claim costs is a\n * later, less obvious error message.\n */\nexport function assertTokenMatchesRoom(token: string, room: string): void {\n const { roomId, roomName } = decodeTokenPayload(token);\n if (!roomId && !roomName) {\n return;\n }\n if (room === roomId || room === roomName) {\n return;\n }\n // Named by name where we have one: logs and error reports get read by\n // humans, who know rooms by name rather than by primary key.\n const minted = roomName ?? roomId;\n throw new RTCError('ROOM_NOT_FOUND', `This token was minted for room \"${minted}\", not \"${room}\"`);\n}\n","export type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug';\n\nconst LEVELS: LogLevel[] = ['silent', 'error', 'warn', 'info', 'debug'];\n\nexport interface Logger {\n error(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n info(...args: unknown[]): void;\n debug(...args: unknown[]): void;\n}\n\n/**\n * Console-backed logger, prefixed and level-gated. Nothing here redacts\n * anything for you, so don't hand it a raw RTC token or an API key.\n */\nexport function createLogger(level: LogLevel = 'silent'): Logger {\n const rank = LEVELS.indexOf(level);\n const enabled = (l: LogLevel) => LEVELS.indexOf(l) <= rank;\n\n return {\n error: (...args) => {\n if (enabled('error')) console.error('[raven-rtc]', ...args);\n },\n warn: (...args) => {\n if (enabled('warn')) console.warn('[raven-rtc]', ...args);\n },\n info: (...args) => {\n if (enabled('info')) console.info('[raven-rtc]', ...args);\n },\n debug: (...args) => {\n if (enabled('debug')) console.debug('[raven-rtc]', ...args);\n },\n };\n}\n","import { RTCError } from '../../errors';\nimport type { DeviceInfo, DeviceKind } from '../sfu/types';\n\n/**\n * Lists available media devices.\n *\n * Labels come back empty until permission has been granted at least once.\n * That's a privacy measure in every browser and not something the SDK can\n * route around. A label-less device still has a usable `deviceId`, so you\n * can select it. There's just nothing worth showing a user until they've\n * allowed access once.\n */\nexport async function listDevices(kind?: DeviceKind): Promise<DeviceInfo[]> {\n if (typeof navigator === 'undefined' || !navigator.mediaDevices?.enumerateDevices) {\n throw new RTCError(\n 'NOT_SUPPORTED',\n 'Device enumeration is not available in this environment (no navigator.mediaDevices)',\n );\n }\n\n const devices = await navigator.mediaDevices.enumerateDevices();\n return devices\n .filter((device) => !kind || device.kind === kind)\n .map((device) => ({\n deviceId: device.deviceId,\n label: device.label,\n kind: device.kind as DeviceKind,\n }));\n}\n","import type { TrackKind } from '../../track';\n\n/**\n * One flattened WebRTC stats sample.\n *\n * Duck-typed instead of bound to any particular source, which is how this\n * file survived the move off LiveKit's stats objects to reading an\n * `RTCStatsReport` directly (see `internal/telemetry/rtc-stats.ts`). Every\n * field is a raw WebRTC stat in the units the spec uses, so seconds, not\n * milliseconds. `normalizeTrackStats` below translates into Raven's own\n * vocabulary.\n */\nexport interface RawTrackStats {\n type?: 'audio' | 'video';\n /** Epoch ms: when this sample was taken. Bitrate is a delta against a previous one. */\n timestamp: number;\n /** Seconds, per the WebRTC spec. */\n jitter?: number;\n packetsLost?: number;\n packetsSent?: number;\n packetsReceived?: number;\n /** Seconds. Only ever set on an outbound audio stream; WebRTC reports no RTT for video or for the receive direction. */\n roundTripTime?: number;\n bytesSent?: number;\n bytesReceived?: number;\n /** Receive-direction video only. WebRTC doesn't surface it for audio or for sending. */\n mimeType?: string;\n frameWidth?: number;\n frameHeight?: number;\n framesPerSecond?: number;\n}\n\n/**\n * Raven's own normalized shape. A raw WebRTC stats object never appears on\n * a public class.\n *\n * Every field is optional, and gets omitted, not set to `0` or\n * `null` when the browser or SFU didn't report it. \"0% packet loss\" and\n * \"we don't know\" are different facts, and this will not fabricate the\n * first to cover for the second.\n */\nexport interface TrackStats {\n kind: TrackKind;\n /** 'send' for a track we published, 'receive' for one we subscribed to. */\n direction: 'send' | 'receive';\n /** Bytes/sec, from two consecutive samples. Undefined on a track's first sample, since there's nothing to take a delta against yet. */\n bitrateBps?: number;\n packetsLost?: number;\n /** 0-100. The module doc explains why it's an approximation and not a WebRTC-spec figure. */\n packetLossPercent?: number;\n jitterMs?: number;\n roundTripTimeMs?: number;\n /** Only set for a received video track. See `RawTrackStats.mimeType`. */\n codec?: string;\n frameWidth?: number;\n frameHeight?: number;\n framesPerSecond?: number;\n}\n\nconst MS_PER_SECOND = 1000;\n\n/**\n * Turns one raw WebRTC sample into Raven's `TrackStats`, using the previous\n * sample where there is one to work bitrate out as a delta over time.\n *\n * Packet loss comes back as a percentage via the usual loss-rate\n * approximation, `lost / (lost + sent-or-received)`, which is what most\n * WebRTC quality tooling uses. It isn't the RFC 3550 formula and it isn't\n * exact: `packetsLost` is a cumulative, remote-reported count with its own\n * delivery lag. But it's close enough to be a useful signal and costs\n * nothing on top of stats we're already collecting.\n */\nexport function normalizeTrackStats(\n raw: RawTrackStats,\n previous: RawTrackStats | undefined,\n kind: TrackKind,\n direction: 'send' | 'receive',\n): TrackStats {\n const stats: TrackStats = { kind, direction };\n\n if (typeof raw.jitter === 'number') {\n stats.jitterMs = raw.jitter * MS_PER_SECOND;\n }\n if (typeof raw.roundTripTime === 'number') {\n stats.roundTripTimeMs = raw.roundTripTime * MS_PER_SECOND;\n }\n if (typeof raw.mimeType === 'string') {\n stats.codec = raw.mimeType;\n }\n if (typeof raw.frameWidth === 'number') stats.frameWidth = raw.frameWidth;\n if (typeof raw.frameHeight === 'number') stats.frameHeight = raw.frameHeight;\n if (typeof raw.framesPerSecond === 'number') stats.framesPerSecond = raw.framesPerSecond;\n\n if (typeof raw.packetsLost === 'number') {\n stats.packetsLost = raw.packetsLost;\n\n const attempted = direction === 'send' ? raw.packetsSent : raw.packetsReceived;\n if (typeof attempted === 'number' && attempted + raw.packetsLost > 0) {\n stats.packetLossPercent = (raw.packetsLost / (attempted + raw.packetsLost)) * 100;\n }\n }\n\n const bytesField = direction === 'send' ? 'bytesSent' : 'bytesReceived';\n const currentBytes = raw[bytesField];\n const previousBytes = previous?.[bytesField];\n\n if (typeof currentBytes === 'number' && typeof previousBytes === 'number') {\n const elapsedSeconds = (raw.timestamp - previous!.timestamp) / MS_PER_SECOND;\n // Non-positive elapsed time means the samples are out of order or\n // identical, which happens when a caller polls faster than the\n // underlying stats actually refresh. Computing a rate from that either\n // divides by zero or flips the sign, so skip it instead of reporting\n // junk.\n if (elapsedSeconds > 0 && currentBytes >= previousBytes) {\n stats.bitrateBps = ((currentBytes - previousBytes) * 8) / elapsedSeconds;\n }\n }\n\n return stats;\n}\n\n/**\n * `LocalVideoTrack.getSenderStats()` hands back one entry per simulcast\n * encoding layer, not a single stream. The highest-resolution layer is the\n * one worth calling \"this track's\" quality. The lower layers exist for\n * viewers on poor connections; they don't describe what this participant\n * is sending at its best.\n */\nexport function pickBestLayer(layers: RawTrackStats[]): RawTrackStats | undefined {\n return layers.reduce<RawTrackStats | undefined>((best, layer) => {\n const bestWidth = best?.frameWidth ?? -1;\n const layerWidth = layer.frameWidth ?? -1;\n return layerWidth > bestWidth ? layer : best;\n }, undefined);\n}\n","import type { EffectsPipeline } from '@ravenkash/effects';\nimport { normalizeTrackStats, pickBestLayer, type RawTrackStats, type TrackStats } from './internal/telemetry/track-stats';\nimport { RTCError } from './errors';\n\nexport type { TrackStats } from './internal/telemetry/track-stats';\nexport type TrackKind = 'camera' | 'microphone' | 'screenShare' | 'unknown';\n\n/**\n * A structural interface, not a concrete class, so a track can be backed by\n * a raw `MediaStreamTrack` (what the native adapter does) or by a test\n * double, with neither having to inherit anything.\n */\nexport interface TrackDelegate {\n readonly mediaStreamTrack: MediaStreamTrack;\n readonly mediaStream?: MediaStream;\n readonly isMuted: boolean;\n attach(element?: HTMLMediaElement): HTMLMediaElement;\n // Typed loosely so a delegate can return one element or an array.\n // Track.detach() below always normalizes to an array, so the public API\n // looks the same either way.\n detach(element?: HTMLMediaElement): HTMLMediaElement | HTMLMediaElement[];\n}\n\n/** Base class for local and remote tracks alike. Never leaks RTCRtpSender/Receiver. */\nexport abstract class Track {\n readonly kind: TrackKind;\n protected readonly delegate: TrackDelegate;\n\n constructor(delegate: TrackDelegate, kind: TrackKind) {\n this.delegate = delegate;\n this.kind = kind;\n }\n\n /** The underlying native track, for the rare occasion you need to go deeper. */\n get mediaStreamTrack(): MediaStreamTrack {\n return this.delegate.mediaStreamTrack;\n }\n\n get mediaStream(): MediaStream | undefined {\n return this.delegate.mediaStream;\n }\n\n get isMuted(): boolean {\n return this.delegate.isMuted;\n }\n\n /** Attaches this track to a `<video>`/`<audio>` element, creating one if omitted. */\n attach(element?: HTMLMediaElement): HTMLMediaElement {\n return this.delegate.attach(element);\n }\n\n /** Detaches this track from one element, or from all elements if omitted. */\n detach(element?: HTMLMediaElement): HTMLMediaElement[] {\n const result = this.delegate.detach(element);\n return Array.isArray(result) ? result : [result];\n }\n}\n\nexport interface LocalTrackDelegate extends TrackDelegate {\n // Typed `unknown` so a delegate resolving to anything, or to nothing at\n // all, still satisfies the interface. Nobody here uses the value.\n mute(): Promise<unknown>;\n unmute(): Promise<unknown>;\n /**\n * Optional, so a delegate that predates stats support (or a test double\n * that doesn't care) still satisfies this interface untouched. Purely\n * additive, never required. The array form covers video, where a\n * simulcast sender reports one `outbound-rtp` entry per encoding layer\n * instead of a single stream.\n */\n getSenderStats?(): Promise<RawTrackStats | RawTrackStats[] | undefined>;\n /**\n * Swaps the underlying MediaStreamTrack on an already-published sender.\n * `RTCRtpSender.replaceTrack()` manages this without renegotiating, so\n * nobody else in the room sees a thing. Optional for the same reason as\n * getSenderStats: a delegate predating Raven Effects still satisfies\n * this interface, and LocalTrack.attachEffects() checks for it rather\n * than assuming every delegate has it.\n */\n replaceTrack?(track: MediaStreamTrack, userProvidedTrack?: boolean): Promise<unknown>;\n}\n\nexport interface RemoteTrackDelegate extends TrackDelegate {\n /** Optional for the same reason as `LocalTrackDelegate.getSenderStats`. */\n getReceiverStats?(): Promise<RawTrackStats | undefined>;\n}\n\n/** A locally captured track (camera, microphone or screen share), published or not. */\nexport class LocalTrack extends Track {\n private readonly localDelegate: LocalTrackDelegate;\n private lastSample?: RawTrackStats;\n private attachedEffectsPipeline?: EffectsPipeline;\n private preEffectsMediaStreamTrack?: MediaStreamTrack;\n\n constructor(delegate: LocalTrackDelegate, kind: TrackKind) {\n super(delegate, kind);\n this.localDelegate = delegate;\n }\n\n async mute(): Promise<void> {\n await this.localDelegate.mute();\n }\n\n async unmute(): Promise<void> {\n await this.localDelegate.unmute();\n }\n\n /** Stops the underlying device capture. Publish state belongs to Room.unpublish(). */\n stop(): void {\n this.mediaStreamTrack.stop();\n }\n\n /**\n * Where Raven Effects (`@ravenkash/effects`) plugs in. The chain is\n * Camera → Raven Video Track → Effects Pipeline → Processed Video Track →\n * Raven RTC.\n *\n * Runs `pipeline` against this track's live camera feed and, if the track\n * is already published, swaps the sender's `MediaStreamTrack` in place\n * through the adapter's `replaceTrack()`. No renegotiation, no reconnect,\n * audio and the rest of the room untouched. Camera only for now; screen\n * share and microphone aren't supported.\n *\n * Can't run the pipeline on this device (no WebGL2, Canvas2D or\n * captureStream)? It falls back to the original track on its own. The\n * call keeps working either way.\n */\n async attachEffects(pipeline: EffectsPipeline): Promise<void> {\n if (this.kind !== 'camera') {\n throw new RTCError('MEDIA_ERROR', `attachEffects() is only supported on camera tracks, not \"${this.kind}\".`);\n }\n if (!this.localDelegate.replaceTrack) {\n throw new RTCError('MEDIA_ERROR', 'This track cannot be swapped in place; the current adapter does not support replaceTrack().');\n }\n if (this.attachedEffectsPipeline) {\n await this.detachEffects();\n }\n\n const original = this.mediaStreamTrack;\n const processed = await pipeline.attachToTrack(original);\n if (processed !== original) {\n await this.localDelegate.replaceTrack(processed, true);\n }\n this.attachedEffectsPipeline = pipeline;\n this.preEffectsMediaStreamTrack = original;\n }\n\n /** Goes back to the unmodified camera track and frees the pipeline's engine resources. */\n async detachEffects(): Promise<void> {\n if (!this.attachedEffectsPipeline) return;\n this.attachedEffectsPipeline.detach();\n if (this.preEffectsMediaStreamTrack && this.localDelegate.replaceTrack) {\n await this.localDelegate.replaceTrack(this.preEffectsMediaStreamTrack, true);\n }\n this.attachedEffectsPipeline = undefined;\n this.preEffectsMediaStreamTrack = undefined;\n }\n\n /**\n * Live send-side stats for this track: bitrate, packet loss, jitter, RTT\n * (audio only), resolution and fps (video only).\n *\n * You get `undefined`, not a zeroed-out object, when the adapter can't\n * supply them, either because the delegate has no `getSenderStats` or\n * because the underlying call resolved to nothing. The module doc covers\n * why that distinction matters.\n *\n * Call it periodically instead of once. `Room.getConnectionStats()` does,\n * every few seconds. Bitrate needs two samples to compute, so the first\n * call after a track starts always omits it.\n */\n async getStats(): Promise<TrackStats | undefined> {\n const raw = await this.localDelegate.getSenderStats?.();\n if (!raw) {\n return undefined;\n }\n\n const sample = Array.isArray(raw) ? pickBestLayer(raw) : raw;\n if (!sample) {\n return undefined;\n }\n\n const stats = normalizeTrackStats(sample, this.lastSample, this.kind, 'send');\n this.lastSample = sample;\n return stats;\n }\n}\n\n/** A track received from a remote participant, via the SFU. */\nexport class RemoteTrack extends Track {\n private readonly remoteDelegate: RemoteTrackDelegate;\n private lastSample?: RawTrackStats;\n\n constructor(delegate: RemoteTrackDelegate, kind: TrackKind) {\n super(delegate, kind);\n this.remoteDelegate = delegate;\n }\n\n /** Live receive-side stats. `LocalTrack.getStats()` covers the shape and the caveats. */\n async getStats(): Promise<TrackStats | undefined> {\n const raw = await this.remoteDelegate.getReceiverStats?.();\n if (!raw) {\n return undefined;\n }\n\n const stats = normalizeTrackStats(raw, this.lastSample, this.kind, 'receive');\n this.lastSample = raw;\n return stats;\n }\n}\n","import { RTCError } from '../../errors';\nimport type { TrackKind } from '../../track';\n\n/**\n * Maps a raw getUserMedia/getDisplayMedia failure onto one of our typed\n * error codes.\n *\n * The whole classification is a short read of the `DOMException` names the\n * Media Capture spec defines, so Raven owns it instead of pulling in a\n * library.\n *\n * Those names come from the spec's own error list (getUserMedia §9.2), not\n * from any one browser's quirks. Every engine reports them. A name we\n * don't recognise falls through to a generic `MEDIA_ERROR` instead of\n * getting guessed at.\n */\nexport function toMediaError(error: unknown, kind: TrackKind): RTCError {\n const name = errorName(error);\n\n switch (name) {\n case 'NotAllowedError':\n case 'SecurityError':\n // SecurityError is what a browser raises when the page isn't a\n // secure context. From the developer's side that's a permission\n // problem, and the message spells out which kind.\n return new RTCError(\n permissionDeniedCode(kind),\n `Permission to use the ${label(kind)} was denied`,\n error,\n );\n\n case 'NotFoundError':\n case 'OverconstrainedError':\n // OverconstrainedError means nothing satisfies the constraints. In\n // practice that's a deviceId that no longer exists, which a\n // developer handles exactly the same way as \"not found\".\n return new RTCError('DEVICE_NOT_FOUND', `No ${label(kind)} device matched`, error);\n\n case 'NotReadableError':\n return new RTCError(\n 'MEDIA_ERROR',\n `The ${label(kind)} is already in use by another application`,\n error,\n );\n\n case 'AbortError':\n return new RTCError('MEDIA_ERROR', `Capturing the ${label(kind)} was aborted`, error);\n\n case 'TypeError':\n // Empty or malformed constraints. That's a programming error, not a\n // device one, so say so.\n return new RTCError('MEDIA_ERROR', `Invalid ${label(kind)} capture constraints`, error);\n\n default:\n return new RTCError('MEDIA_ERROR', `Could not access the ${label(kind)}`, error);\n }\n}\n\nfunction errorName(error: unknown): string | undefined {\n if (typeof DOMException !== 'undefined' && error instanceof DOMException) {\n return error.name;\n }\n // Not every environment has DOMException (some test runners, older\n // React Native), and `error.name` is there regardless.\n if (error && typeof error === 'object' && typeof (error as { name?: unknown }).name === 'string') {\n return (error as { name: string }).name;\n }\n return undefined;\n}\n\n/** What a developer calls it, rather than what the SDK calls it internally. */\nfunction label(kind: TrackKind): string {\n return kind === 'screenShare' ? 'screen' : kind;\n}\n\nfunction permissionDeniedCode(\n kind: TrackKind,\n): 'CAMERA_PERMISSION_DENIED' | 'MICROPHONE_PERMISSION_DENIED' | 'PERMISSION_DENIED' {\n if (kind === 'camera') return 'CAMERA_PERMISSION_DENIED';\n if (kind === 'microphone') return 'MICROPHONE_PERMISSION_DENIED';\n return 'PERMISSION_DENIED';\n}\n","import type { RawTrackStats } from './track-stats';\n\nexport type { RawTrackStats } from './track-stats';\n\n/**\n * Reads an `RTCStatsReport` into the flat samples `normalizeTrackStats`\n * already knows how to handle.\n *\n * # Why this walks the whole report instead of grabbing one entry\n *\n * The numbers you want for a single track are scattered across several\n * stats objects, and which object holds what depends on direction:\n *\n * - `outbound-rtp` / `inbound-rtp`: bytes, packets, and video\n * resolution/framerate.\n * - `remote-inbound-rtp`: the *remote* end's view of a stream we're\n * sending. It's the only place round-trip time and the loss the far side\n * actually saw get reported. Send-side loss can't be measured locally at\n * all; a sender only knows what it handed to the network.\n * - `codec`: the mime type, referenced by id rather than inlined.\n *\n * So a faithful sample is a join across all of those. Doing that here,\n * once, is what keeps `TrackStats` a flat honest shape instead of\n * exposing the report's structure to every caller.\n *\n * Anything the report doesn't contain stays `undefined`. Nothing here\n * swaps a zero in for a missing measurement. Spec §19 forbids inventing\n * quality figures, and \"0% loss\" versus \"no report yet\" is exactly the\n * distinction that matters.\n */\nexport function rawStatsFromReport(\n report: RTCStatsReport,\n wanted: 'outbound-rtp' | 'inbound-rtp',\n): RawTrackStats[] {\n const codecs = new Map<string, string>();\n const remoteInbound: RemoteInboundStats[] = [];\n const rtpEntries: RtpStats[] = [];\n\n report.forEach((entry) => {\n const stats = entry as { type?: string } & Record<string, unknown>;\n switch (stats.type) {\n case 'codec':\n if (typeof stats.id === 'string' && typeof stats.mimeType === 'string') {\n codecs.set(stats.id, stats.mimeType);\n }\n break;\n case 'remote-inbound-rtp':\n remoteInbound.push(stats as unknown as RemoteInboundStats);\n break;\n case wanted:\n rtpEntries.push(stats as unknown as RtpStats);\n break;\n default:\n break;\n }\n });\n\n return rtpEntries.map((rtp) => toRawStats(rtp, wanted, codecs, remoteInbound));\n}\n\ninterface RtpStats {\n id?: string;\n ssrc?: number;\n kind?: string;\n mediaType?: string;\n timestamp?: number;\n codecId?: string;\n bytesSent?: number;\n bytesReceived?: number;\n packetsSent?: number;\n packetsReceived?: number;\n packetsLost?: number;\n jitter?: number;\n frameWidth?: number;\n frameHeight?: number;\n framesPerSecond?: number;\n mimeType?: string;\n}\n\ninterface RemoteInboundStats {\n ssrc?: number;\n localId?: string;\n roundTripTime?: number;\n packetsLost?: number;\n jitter?: number;\n}\n\nfunction toRawStats(\n rtp: RtpStats,\n direction: 'outbound-rtp' | 'inbound-rtp',\n codecs: Map<string, string>,\n remoteInbound: RemoteInboundStats[],\n): RawTrackStats {\n const kind = rtp.kind ?? rtp.mediaType;\n const sample: RawTrackStats = {\n type: kind === 'audio' ? 'audio' : kind === 'video' ? 'video' : undefined,\n // `RTCStats.timestamp` is a DOMHighResTimeStamp relative to the time\n // origin, and `normalizeTrackStats` only ever uses it as a delta\n // against a previous sample, so the epoch is irrelevant. Falling back\n // to Date.now() keeps the delta usable on the rare browser that omits\n // it.\n timestamp: typeof rtp.timestamp === 'number' ? rtp.timestamp : Date.now(),\n };\n\n if (typeof rtp.jitter === 'number') sample.jitter = rtp.jitter;\n if (typeof rtp.frameWidth === 'number') sample.frameWidth = rtp.frameWidth;\n if (typeof rtp.frameHeight === 'number') sample.frameHeight = rtp.frameHeight;\n if (typeof rtp.framesPerSecond === 'number') sample.framesPerSecond = rtp.framesPerSecond;\n\n const mimeType = rtp.mimeType ?? (rtp.codecId ? codecs.get(rtp.codecId) : undefined);\n if (mimeType) sample.mimeType = mimeType;\n\n if (direction === 'outbound-rtp') {\n if (typeof rtp.bytesSent === 'number') sample.bytesSent = rtp.bytesSent;\n if (typeof rtp.packetsSent === 'number') sample.packetsSent = rtp.packetsSent;\n\n // Loss and RTT for a stream we're sending are only knowable from the\n // receiver's report. Match on `localId` where the browser gives us\n // one, fall back to SSRC otherwise. Safari has a long history of being\n // inconsistent about `localId`, and a slightly looser match beats no\n // match at all.\n const feedback =\n remoteInbound.find((remote) => rtp.id && remote.localId === rtp.id) ??\n remoteInbound.find((remote) => rtp.ssrc !== undefined && remote.ssrc === rtp.ssrc);\n if (feedback) {\n if (typeof feedback.roundTripTime === 'number') sample.roundTripTime = feedback.roundTripTime;\n if (typeof feedback.packetsLost === 'number') sample.packetsLost = feedback.packetsLost;\n if (sample.jitter === undefined && typeof feedback.jitter === 'number') {\n sample.jitter = feedback.jitter;\n }\n }\n return sample;\n }\n\n if (typeof rtp.bytesReceived === 'number') sample.bytesReceived = rtp.bytesReceived;\n if (typeof rtp.packetsReceived === 'number') sample.packetsReceived = rtp.packetsReceived;\n if (typeof rtp.packetsLost === 'number') sample.packetsLost = rtp.packetsLost;\n return sample;\n}\n\n/**\n * Round-trip time on the negotiated ICE candidate pair, if there is one.\n *\n * Worth having alongside per-track RTT because it still exists on a\n * video-only or receive-only connection, where there's no audio\n * `remote-inbound-rtp` report to carry one.\n */\nexport async function connectionRoundTripTimeMs(\n connection: RTCPeerConnection,\n): Promise<number | undefined> {\n const report = await connection.getStats();\n let rttSeconds: number | undefined;\n\n report.forEach((entry) => {\n const stats = entry as { type?: string } & Record<string, unknown>;\n if (stats.type !== 'candidate-pair') {\n return;\n }\n // Only the pair actually in use. A connection gathers several and\n // reports the lot; the others' timings describe paths nobody is\n // taking.\n if (stats.state !== 'succeeded' || stats.nominated !== true) {\n return;\n }\n if (typeof stats.currentRoundTripTime === 'number') {\n rttSeconds = stats.currentRoundTripTime;\n }\n });\n\n return rttSeconds === undefined ? undefined : rttSeconds * 1000;\n}\n","import type { LocalTrackDelegate, RemoteTrackDelegate } from '../../track';\nimport { rawStatsFromReport, type RawTrackStats } from '../telemetry/rtc-stats';\n\n/**\n * Attach/detach over a plain `MediaStreamTrack`.\n *\n * `Track.attach()` is how the SDK gets media onto a page without anyone\n * touching `srcObject`. The job itself is small: wrap the track in a\n * `MediaStream`, point an element at it, and remember which elements you\n * attached so `detach()` can find them later.\n *\n * That last bit is the part worth getting right. Skip the bookkeeping and\n * `detach()` with no argument has nothing to detach *from*, at which point\n * the standard React cleanup path quietly leaks a playing video.\n */\nabstract class NativeTrackDelegate {\n readonly mediaStreamTrack: MediaStreamTrack;\n private stream?: MediaStream;\n private readonly attachedElements = new Set<HTMLMediaElement>();\n\n constructor(mediaStreamTrack: MediaStreamTrack) {\n this.mediaStreamTrack = mediaStreamTrack;\n }\n\n get mediaStream(): MediaStream | undefined {\n if (!this.stream && typeof MediaStream !== 'undefined') {\n this.stream = new MediaStream([this.mediaStreamTrack]);\n }\n return this.stream;\n }\n\n attach(element?: HTMLMediaElement): HTMLMediaElement {\n const target = element ?? this.createElement();\n const stream = this.mediaStream;\n if (stream) {\n target.srcObject = stream;\n }\n // Autoplay policies block an unmuted video element until the user has\n // interacted with the page. A remote track needs to be audible, so we\n // don't mute it. `autoplay` plus `playsInline` covers the cases that\n // are allowed, and anyone needing finer control passes their own\n // element.\n target.autoplay = true;\n if (target instanceof HTMLVideoElement) {\n target.playsInline = true;\n }\n this.attachedElements.add(target);\n return target;\n }\n\n detach(element?: HTMLMediaElement): HTMLMediaElement | HTMLMediaElement[] {\n if (element) {\n element.srcObject = null;\n this.attachedElements.delete(element);\n return element;\n }\n\n const detached = Array.from(this.attachedElements);\n for (const attached of detached) {\n attached.srcObject = null;\n }\n this.attachedElements.clear();\n return detached;\n }\n\n /**\n * Swaps out the track this delegate wraps.\n *\n * Called once `replaceTrack` on the sender has succeeded, so attached\n * elements and `mediaStreamTrack` describe what's actually going out\n * rather than the track we just replaced.\n */\n protected swapMediaStreamTrack(next: MediaStreamTrack): void {\n (this as { mediaStreamTrack: MediaStreamTrack }).mediaStreamTrack = next;\n this.stream = typeof MediaStream !== 'undefined' ? new MediaStream([next]) : undefined;\n const stream = this.stream;\n if (!stream) {\n return;\n }\n for (const element of this.attachedElements) {\n element.srcObject = stream;\n }\n }\n\n private createElement(): HTMLMediaElement {\n if (typeof document === 'undefined') {\n throw new Error('attach() without an element requires a DOM');\n }\n return document.createElement(this.mediaStreamTrack.kind === 'video' ? 'video' : 'audio');\n }\n}\n\n/**\n * A locally captured track, which may or may not have an `RTCRtpSender`.\n *\n * The sender arrives after publishing, not at construction. You can capture\n * a track for a preview and publish it later (`client.createCameraTrack()`\n * then `room.publish(track)`), and mute has to work in both states.\n */\nexport class NativeLocalTrackDelegate extends NativeTrackDelegate implements LocalTrackDelegate {\n private sender?: RTCRtpSender;\n private muted = false;\n\n get isMuted(): boolean {\n return this.muted;\n }\n\n /** @internal Called by the adapter once the track has a sender. */\n setSender(sender: RTCRtpSender | undefined): void {\n this.sender = sender;\n }\n\n /**\n * Mutes by disabling the underlying track, not by removing it.\n *\n * `track.enabled = false` has the browser send silence or black frames.\n * The RTP stream keeps going, the transceiver stays put, and unmuting is\n * instant. Stopping the track instead releases the device, which does\n * turn the camera light off (users read that as \"off\"), but undoing it\n * then costs a fresh `getUserMedia` and a renegotiation.\n *\n * We tell the SFU separately over signaling, so it can stop forwarding\n * the silence to every subscriber instead of paying to relay nothing.\n */\n async mute(): Promise<unknown> {\n this.mediaStreamTrack.enabled = false;\n this.muted = true;\n return undefined;\n }\n\n async unmute(): Promise<unknown> {\n this.mediaStreamTrack.enabled = true;\n this.muted = false;\n return undefined;\n }\n\n /**\n * Replaces the outgoing track without renegotiating.\n *\n * This is the trick that makes Raven Effects work mid-call.\n * `RTCRtpSender.replaceTrack` swaps the source of an established stream,\n * so a processed video track takes over from the raw camera with no\n * offer/answer and nobody else in the room noticing.\n */\n async replaceTrack(track: MediaStreamTrack, _userProvidedTrack?: boolean): Promise<unknown> {\n if (this.sender) {\n await this.sender.replaceTrack(track);\n }\n // Applied with or without a sender, so an unpublished track's preview\n // follows the swap too.\n this.swapMediaStreamTrack(track);\n if (this.muted) {\n track.enabled = false;\n }\n return undefined;\n }\n\n /**\n * Send-side stats for this track.\n *\n * Video gets an array, because a simulcast sender reports one\n * `outbound-rtp` per encoding layer, and `LocalTrack.getStats()` picks\n * the highest-resolution one. You get `undefined` when there's no sender\n * yet. An unpublished track has no send statistics, and reporting zeroes\n * would claim it was sending nothing when really it isn't sending.\n */\n async getSenderStats(): Promise<RawTrackStats | RawTrackStats[] | undefined> {\n if (!this.sender) {\n return undefined;\n }\n const report = await this.sender.getStats();\n const samples = rawStatsFromReport(report, 'outbound-rtp');\n if (samples.length === 0) {\n return undefined;\n }\n return samples.length === 1 ? samples[0] : samples;\n }\n}\n\n/**\n * A track received from a remote participant.\n *\n * `isMuted` is the *publisher's* mute, as reported by the SFU over\n * signaling. It is not `mediaStreamTrack.muted`, which in a browser means\n * \"nothing arriving right now\" and flickers true during perfectly ordinary\n * network jitter. Drive a UI off that and it flashes a muted badge on a\n * completely healthy connection.\n */\nexport class NativeRemoteTrackDelegate extends NativeTrackDelegate implements RemoteTrackDelegate {\n private readonly receiver: RTCRtpReceiver;\n private publisherMuted = false;\n\n constructor(mediaStreamTrack: MediaStreamTrack, receiver: RTCRtpReceiver) {\n super(mediaStreamTrack);\n this.receiver = receiver;\n }\n\n get isMuted(): boolean {\n return this.publisherMuted;\n }\n\n /** @internal Set from the SFU's `track.muted` / `track.unmuted` events. */\n setPublisherMuted(muted: boolean): void {\n this.publisherMuted = muted;\n }\n\n async getReceiverStats(): Promise<RawTrackStats | undefined> {\n const report = await this.receiver.getStats();\n const [sample] = rawStatsFromReport(report, 'inbound-rtp');\n return sample;\n }\n}\n","import { RTCError } from '../../errors';\nimport { LocalTrack, type TrackKind } from '../../track';\nimport { toMediaError } from './errors';\nimport { NativeLocalTrackDelegate } from './native-track';\n\n/**\n * Default audio constraints (spec §13).\n *\n * All three on by default, because without them a call sounds dreadful in\n * the circumstances calls actually happen in. A laptop speaker and mic in\n * one room is an echo generator. This is the browser's own processing, not\n * anything Raven implements, and anyone who wants raw audio for music or\n * transcription can pass their own constraints.\n */\nconst DEFAULT_AUDIO_CONSTRAINTS: MediaTrackConstraints = {\n echoCancellation: true,\n noiseSuppression: true,\n autoGainControl: true,\n};\n\n/**\n * Default camera constraints (spec §14).\n *\n * `ideal`, never `exact`. An exact resolution fails outright on a device\n * that can't manage it, and \"your call didn't start because your webcam is\n * 640×480\" is not an acceptable outcome. 720p because it's the resolution\n * most cameras genuinely deliver and most layouts genuinely display.\n */\nconst DEFAULT_VIDEO_CONSTRAINTS: MediaTrackConstraints = {\n width: { ideal: 1280 },\n height: { ideal: 720 },\n frameRate: { ideal: 30 },\n};\n\n/** Named video profiles, so you pick a size instead of composing constraints. */\nexport type VideoProfile = '360p' | '480p' | '720p' | '1080p';\n\nconst VIDEO_PROFILES: Record<VideoProfile, MediaTrackConstraints> = {\n '360p': { width: { ideal: 640 }, height: { ideal: 360 }, frameRate: { ideal: 30 } },\n '480p': { width: { ideal: 854 }, height: { ideal: 480 }, frameRate: { ideal: 30 } },\n '720p': { width: { ideal: 1280 }, height: { ideal: 720 }, frameRate: { ideal: 30 } },\n '1080p': { width: { ideal: 1920 }, height: { ideal: 1080 }, frameRate: { ideal: 30 } },\n};\n\nexport interface CameraOptions {\n deviceId?: string;\n profile?: VideoProfile;\n /** `'user'` is the selfie camera, `'environment'` the rear one. Mobile only. */\n facingMode?: 'user' | 'environment';\n constraints?: MediaTrackConstraints;\n}\n\nexport interface MicrophoneOptions {\n deviceId?: string;\n constraints?: MediaTrackConstraints;\n}\n\n/**\n * Captures the camera without publishing it, for anyone who wants a\n * preview before `room.publish(track)`.\n *\n * Doesn't go near the microphone. Spec §13 is explicit that an audio-only\n * call must not demand camera permission, and it cuts both ways: a camera\n * preview shouldn't have the browser asking for a microphone nobody\n * requested.\n */\nexport async function createCameraTrack(options: CameraOptions = {}): Promise<LocalTrack> {\n const constraints: MediaTrackConstraints = {\n ...DEFAULT_VIDEO_CONSTRAINTS,\n ...(options.profile ? VIDEO_PROFILES[options.profile] : {}),\n ...(options.facingMode ? { facingMode: options.facingMode } : {}),\n ...(options.deviceId ? { deviceId: { exact: options.deviceId } } : {}),\n ...options.constraints,\n };\n\n const stream = await getUserMedia({ video: constraints, audio: false }, 'camera');\n return trackFromStream(stream, 'camera');\n}\n\nexport async function createMicrophoneTrack(options: MicrophoneOptions = {}): Promise<LocalTrack> {\n const constraints: MediaTrackConstraints = {\n ...DEFAULT_AUDIO_CONSTRAINTS,\n ...(options.deviceId ? { deviceId: { exact: options.deviceId } } : {}),\n ...options.constraints,\n };\n\n const stream = await getUserMedia({ audio: constraints, video: false }, 'microphone');\n return trackFromStream(stream, 'microphone');\n}\n\n/**\n * Captures a screen share through `getDisplayMedia`.\n *\n * Video only, which matches `room.enableScreenShare()`'s single-track\n * contract. We do request screen *audio* where the platform offers it, but\n * only surface the video track. A second published track would change the\n * shape of the public API, so this is a documented scope limit, not a\n * silent omission (spec §16).\n */\nexport async function createScreenShareTrack(): Promise<LocalTrack> {\n if (typeof navigator === 'undefined' || !navigator.mediaDevices?.getDisplayMedia) {\n // Mobile browsers and older engines have no getDisplayMedia at all,\n // and spec §16 says don't assume screen share exists. So: a clear\n // typed refusal, rather than some obscure TypeError.\n throw new RTCError(\n 'NOT_SUPPORTED',\n 'Screen sharing is not available on this platform (no getDisplayMedia)',\n );\n }\n\n let stream: MediaStream;\n try {\n stream = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: false });\n } catch (error) {\n throw toMediaError(error, 'screenShare');\n }\n\n const [videoTrack] = stream.getVideoTracks();\n if (!videoTrack) {\n throw new RTCError('MEDIA_ERROR', 'Screen capture returned no video track');\n }\n\n // Someone who stops sharing from the browser's own \"Stop sharing\" bar\n // ends the track without telling us a thing. The adapter watches for\n // that and unpublishes. Nothing to do here but hand the track over.\n return new LocalTrack(new NativeLocalTrackDelegate(videoTrack), 'screenShare');\n}\n\nasync function getUserMedia(constraints: MediaStreamConstraints, kind: TrackKind): Promise<MediaStream> {\n if (typeof navigator === 'undefined' || !navigator.mediaDevices?.getUserMedia) {\n throw new RTCError(\n 'NOT_SUPPORTED',\n 'Media capture is not available in this environment (no navigator.mediaDevices)',\n );\n }\n\n try {\n return await navigator.mediaDevices.getUserMedia(constraints);\n } catch (error) {\n throw toMediaError(error, kind);\n }\n}\n\nfunction trackFromStream(stream: MediaStream, kind: TrackKind): LocalTrack {\n const [track] = kind === 'microphone' ? stream.getAudioTracks() : stream.getVideoTracks();\n if (!track) {\n throw new RTCError('MEDIA_ERROR', `Capture returned no ${kind} track`);\n }\n return new LocalTrack(new NativeLocalTrackDelegate(track), kind);\n}\n","/** Minimal typed pub/sub. No dependency, and it keeps the bundle small. */\nexport class TypedEventEmitter<EventMap extends { [K in keyof EventMap]: (...args: never[]) => void }> {\n private listeners = new Map<keyof EventMap, Set<(...args: never[]) => void>>();\n\n on<E extends keyof EventMap>(event: E, handler: EventMap[E]): this {\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n set.add(handler as (...args: never[]) => void);\n return this;\n }\n\n off<E extends keyof EventMap>(event: E, handler: EventMap[E]): this {\n this.listeners.get(event)?.delete(handler as (...args: never[]) => void);\n return this;\n }\n\n once<E extends keyof EventMap>(event: E, handler: EventMap[E]): this {\n const wrapped = ((...args: never[]) => {\n this.off(event, wrapped as EventMap[E]);\n (handler as (...args: never[]) => void)(...args);\n }) as EventMap[E];\n return this.on(event, wrapped);\n }\n\n removeAllListeners(event?: keyof EventMap): this {\n if (event) {\n this.listeners.delete(event);\n } else {\n this.listeners.clear();\n }\n return this;\n }\n\n protected emit<E extends keyof EventMap>(event: E, ...args: Parameters<EventMap[E]>): void {\n const set = this.listeners.get(event);\n if (!set) return;\n // Copy before iterating: a handler might call .off() on itself, or on\n // another handler for this event, mid-dispatch.\n for (const handler of Array.from(set)) {\n (handler as (...args: unknown[]) => void)(...args);\n }\n }\n}\n","import type { LocalTrack, RemoteTrack } from './track';\n\n/** Fields the local user and remote participants have in common. */\nexport abstract class Participant {\n private _identity: string;\n /** Opaque application metadata set when the RTC token was minted. */\n readonly metadata?: string;\n\n constructor(identity: string, metadata?: string) {\n this._identity = identity;\n this.metadata = metadata;\n }\n\n /** The RTC token's participant identity. Stable for the whole session. */\n get identity(): string {\n return this._identity;\n }\n\n /**\n * @internal Called once by the SFU adapter just after connect() resolves.\n * The constructor runs before the server has confirmed identity, so this\n * patches it in afterwards.\n */\n _setIdentity(identity: string): void {\n this._identity = identity;\n }\n}\n\nexport class LocalParticipant extends Participant {\n /** Tracks this participant has published, in publish order. Mutated by Room. */\n readonly tracks: LocalTrack[] = [];\n}\n\nexport class RemoteParticipant extends Participant {\n /** Tracks subscribed from this participant, in subscribe order. Mutated by Room. */\n readonly tracks: RemoteTrack[] = [];\n}\n","/**\n * Raven's signaling wire protocol, as the client sees it.\n *\n * Mirrors `apps/api/src/modules/signaling/signaling.constants.ts` and\n * `interfaces/signaling-message.interface.ts`. Written out by hand rather\n * than imported, so the SDK carries no dependency on the server package.\n * Three client implementations speak this (web, React Native, Flutter) and\n * the contract has to stand on its own.\n *\n * Warning if you're reading older code: most of the message *names*\n * survived the move off the old full-mesh protocol, but their meanings\n * didn't. `targetParticipantId` is gone. A client has exactly one peer\n * now: the SFU serving its room.\n */\n\nexport const ClientMessageType = {\n ROOM_JOIN: 'room.join',\n ROOM_LEAVE: 'room.leave',\n SDP_ANSWER: 'sdp.answer',\n SDP_OFFER: 'sdp.offer',\n ICE_CANDIDATE: 'ice.candidate',\n TRACK_MUTE: 'track.mute',\n /**\n * Declares what a track being published is *of*.\n *\n * Needed because WebRTC has no such concept, and a page can't choose the\n * `MediaStream` or `MediaStreamTrack` id the SDP will carry; both are\n * read-only. Without this the SFU can only guess the source from codec\n * kind, and that can't tell a screen share from a camera.\n */\n TRACK_PUBLISH: 'track.publish',\n SUBSCRIPTION_UPDATE: 'subscription.update',\n PING: 'ping',\n} as const;\n\nexport const ServerMessageType = {\n ROOM_JOINED: 'room.joined',\n ROOM_LEFT: 'room.left',\n PARTICIPANT_JOINED: 'participant.joined',\n PARTICIPANT_LEFT: 'participant.left',\n TRACK_PUBLISHED: 'track.published',\n TRACK_UNPUBLISHED: 'track.unpublished',\n TRACK_MUTED: 'track.muted',\n TRACK_UNMUTED: 'track.unmuted',\n SDP_OFFER: 'sdp.offer',\n SDP_ANSWER: 'sdp.answer',\n ICE_CANDIDATE: 'ice.candidate',\n CONNECTION_STATE: 'connection.state',\n ERROR: 'error',\n PONG: 'pong',\n} as const;\n\nexport type SignalingErrorCode =\n | 'INVALID_TOKEN'\n | 'TOKEN_EXPIRED'\n | 'UNAUTHORIZED'\n | 'ROOM_NOT_FOUND'\n | 'ROOM_FULL'\n | 'INVALID_MESSAGE'\n | 'INVALID_MESSAGE_TYPE'\n | 'PARTICIPANT_NOT_FOUND'\n | 'NOT_IN_ROOM'\n | 'PERMISSION_DENIED'\n | 'RATE_LIMITED'\n | 'NO_RTC_CAPACITY'\n | 'RTC_SERVER_UNREACHABLE'\n | 'NEGOTIATION_FAILED'\n | 'NEGOTIATION_GLARE';\n\nexport interface ServerTrack {\n trackId: string;\n kind: 'audio' | 'video';\n source: string;\n muted: boolean;\n simulcast: boolean;\n layers?: string[];\n}\n\nexport interface ServerParticipant {\n id: string;\n tracks?: ServerTrack[];\n}\n\nexport type ServerMessage =\n | { type: typeof ServerMessageType.ROOM_JOINED; roomId: string; participants: ServerParticipant[]; rtcServer?: string; region?: string }\n | { type: typeof ServerMessageType.ROOM_LEFT; roomId: string }\n | { type: typeof ServerMessageType.PARTICIPANT_JOINED; participant: ServerParticipant }\n | { type: typeof ServerMessageType.PARTICIPANT_LEFT; participant: ServerParticipant }\n | { type: typeof ServerMessageType.TRACK_PUBLISHED; participantId: string; track: ServerTrack }\n | { type: typeof ServerMessageType.TRACK_UNPUBLISHED; participantId: string; trackId: string }\n | { type: typeof ServerMessageType.TRACK_MUTED; participantId: string; trackId: string }\n | { type: typeof ServerMessageType.TRACK_UNMUTED; participantId: string; trackId: string }\n | { type: typeof ServerMessageType.SDP_OFFER; sdp: string }\n | { type: typeof ServerMessageType.SDP_ANSWER; sdp: string }\n | { type: typeof ServerMessageType.ICE_CANDIDATE; candidate: string; sdpMid?: string; sdpMLineIndex?: number; usernameFragment?: string }\n | { type: typeof ServerMessageType.CONNECTION_STATE; iceState: string; peerState: string }\n | { type: typeof ServerMessageType.ERROR; code: SignalingErrorCode; message: string }\n | { type: typeof ServerMessageType.PONG };\n\nexport type ClientMessage =\n | { type: typeof ClientMessageType.ROOM_JOIN; roomId?: string; region?: string }\n | { type: typeof ClientMessageType.ROOM_LEAVE }\n | { type: typeof ClientMessageType.SDP_ANSWER; sdp: string }\n | { type: typeof ClientMessageType.SDP_OFFER; sdp: string }\n | { type: typeof ClientMessageType.ICE_CANDIDATE; candidate: string; sdpMid?: string; sdpMLineIndex?: number; usernameFragment?: string }\n | { type: typeof ClientMessageType.TRACK_MUTE; trackId: string; muted: boolean }\n | { type: typeof ClientMessageType.TRACK_PUBLISH; trackId: string; source: 'camera' | 'microphone' | 'screenShare' }\n | { type: typeof ClientMessageType.SUBSCRIPTION_UPDATE; publisherId: string; trackId: string; layer: 'low' | 'medium' | 'high' | 'auto' }\n | { type: typeof ClientMessageType.PING };\n\n/**\n * Error codes meaning \"the credential is the problem\", where reconnecting\n * on the same token can't possibly help.\n *\n * The split drives reconnect behaviour. Everything else is worth retrying\n * with backoff; these want a fresh token from the application's backend\n * first.\n */\nexport const FATAL_ERROR_CODES: ReadonlySet<SignalingErrorCode> = new Set([\n 'INVALID_TOKEN',\n 'TOKEN_EXPIRED',\n 'UNAUTHORIZED',\n 'ROOM_NOT_FOUND',\n 'PERMISSION_DENIED',\n]);\n","import { RTCError } from '../../errors';\nimport type { Logger } from '../../logger';\nimport { TypedEventEmitter } from '../../events';\nimport {\n ClientMessageType,\n FATAL_ERROR_CODES,\n ServerMessageType,\n type ClientMessage,\n type ServerMessage,\n type ServerParticipant,\n type SignalingErrorCode,\n} from './protocol';\n\n/**\n * How long to wait for the socket to open, and then for `room.joined`.\n *\n * Two values, because they fail for completely different reasons. The\n * first means \"can't reach the API\"; the second means \"the API can't reach\n * an RTC server\". One combined timeout would report both as the same\n * thing, which helps nobody.\n */\nconst OPEN_TIMEOUT_MS = 10_000;\nconst JOIN_TIMEOUT_MS = 15_000;\n\n/** Reconnect backoff, jittered, so a fleet-wide blip doesn't turn into a thundering herd. */\nconst RECONNECT_BASE_MS = 300;\nconst RECONNECT_MAX_MS = 10_000;\nconst RECONNECT_MAX_ATTEMPTS = 12;\n\n/** What the server reports about the room at the moment of joining. */\nexport interface JoinedPayload {\n roomId: string;\n participants: ServerParticipant[];\n /** The RTC server's name, for diagnostics. Never its address. */\n rtcServer?: string;\n region?: string;\n}\n\nexport interface SignalingClientEvents {\n /** Socket opened, room joined. Fires again after every successful reconnect. */\n joined: (payload: JoinedPayload) => void;\n message: (message: ServerMessage) => void;\n /** Connection lost; a reconnect is being attempted. */\n reconnecting: () => void;\n /** Reconnect attempts exhausted, or the failure is not retryable. */\n failed: (error: RTCError) => void;\n /** Closed on purpose, via `close()`. */\n closed: () => void;\n}\n\nexport interface SignalingClientOptions {\n endpoint: string;\n token: string;\n roomId: string;\n region?: string;\n autoReconnect: boolean;\n logger: Logger;\n /**\n * Hands back a fresh token when the current one is nearly expired or has\n * been rejected outright (spec §21). Without it, a call outlives its\n * token and dies at the next reconnect.\n */\n refreshToken?: () => Promise<string>;\n}\n\n/**\n * The SDK's signaling connection.\n *\n * # What it owns, and what it doesn't\n *\n * It owns the socket, the join handshake and reconnection. It has no idea\n * what a `PeerConnection` is. Every message goes straight to the adapter,\n * which decides what to negotiate. Keeping that line clean is what makes\n * the reconnect logic testable with no WebRTC stack in sight, and what\n * lets the React Native and Flutter clients reuse the same protocol\n * reasoning over a different transport.\n *\n * # Reconnection\n *\n * A reconnect re-runs the entire join, because that's what the server is\n * expecting. The previous session's PeerConnection is gone or being\n * reaped, and `room.join` allocates a fresh one; the adapter rebuilds its\n * PeerConnection off the offer that follows. Yes, that's more work than\n * resuming a session, and it's the deliberate choice: an ICE restart on a\n * connection that already failed is flakier than starting clean, and the\n * client has to cope with a fresh session anyway when the network moved\n * under it (spec §20).\n */\nexport class SignalingClient extends TypedEventEmitter<SignalingClientEvents> {\n private socket?: WebSocket;\n private token: string;\n private readonly options: SignalingClientOptions;\n private readonly logger: Logger;\n\n private reconnectAttempts = 0;\n private reconnectTimer?: ReturnType<typeof setTimeout>;\n private closedByCaller = false;\n private joined = false;\n\n constructor(options: SignalingClientOptions) {\n super();\n this.options = options;\n this.token = options.token;\n this.logger = options.logger;\n }\n\n get isJoined(): boolean {\n return this.joined;\n }\n\n /**\n * Opens the socket and joins the room.\n *\n * Resolves when `room.joined` arrives, not when the socket opens. Resolve\n * on socket-open and the caller still has to sit waiting on an event to\n * find out whether they're actually in the room, which is the same wait\n * with an extra step bolted on.\n */\n async connect(): Promise<JoinedPayload> {\n this.closedByCaller = false;\n return this.openAndJoin();\n }\n\n private async openAndJoin(): Promise<JoinedPayload> {\n const socket = await this.openSocket();\n this.socket = socket;\n return this.join(socket);\n }\n\n private openSocket(): Promise<WebSocket> {\n const url = this.buildUrl();\n\n return new Promise<WebSocket>((resolve, reject) => {\n let socket: WebSocket;\n try {\n socket = new WebSocket(url);\n } catch (error) {\n reject(new RTCError('SIGNALING_ERROR', 'Could not open a signaling connection', error));\n return;\n }\n\n const timeout = setTimeout(() => {\n socket.close();\n reject(new RTCError('TIMEOUT', `Signaling connection to ${this.options.endpoint} timed out`));\n }, OPEN_TIMEOUT_MS);\n\n socket.onopen = () => {\n clearTimeout(timeout);\n this.logger.debug('signaling socket open');\n resolve(socket);\n };\n\n socket.onerror = () => {\n clearTimeout(timeout);\n // A browser WebSocket error event carries no detail whatsoever,\n // by design: saying why a connection failed would be a cross-origin\n // information leak. So this message lists what to check instead of\n // pretending to know.\n reject(\n new RTCError(\n 'NETWORK_ERROR',\n `Could not reach the signaling endpoint at ${this.options.endpoint}`,\n ),\n );\n };\n });\n }\n\n private join(socket: WebSocket): Promise<JoinedPayload> {\n return new Promise<JoinedPayload>((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new RTCError('TIMEOUT', 'The server did not confirm the room join'));\n }, JOIN_TIMEOUT_MS);\n\n let settled = false;\n const settle = (fn: () => void) => {\n if (settled) return;\n settled = true;\n clearTimeout(timeout);\n fn();\n };\n\n socket.onmessage = (event: MessageEvent) => {\n const message = this.parse(event.data);\n if (!message) {\n return;\n }\n\n // Join handshake resolves here. Everything after it goes to the\n // steady-state handler below.\n if (!settled) {\n if (message.type === ServerMessageType.ROOM_JOINED) {\n const payload: JoinedPayload = {\n roomId: message.roomId,\n participants: message.participants,\n rtcServer: message.rtcServer,\n region: message.region,\n };\n this.joined = true;\n this.reconnectAttempts = 0;\n this.logger.info(\n 'joined room',\n message.roomId,\n message.rtcServer ? `via ${message.rtcServer}` : '',\n );\n settle(() => resolve(payload));\n this.emit('joined', payload);\n return;\n }\n\n if (message.type === ServerMessageType.ERROR) {\n settle(() => reject(this.toError(message.code, message.message)));\n return;\n }\n }\n\n this.handleMessage(message);\n };\n\n socket.onclose = (event: CloseEvent) => {\n this.joined = false;\n settle(() =>\n reject(\n new RTCError(\n 'SIGNALING_ERROR',\n `The signaling connection closed before the room was joined (code ${event.code})`,\n ),\n ),\n );\n this.handleClose(event);\n };\n\n socket.onerror = () => {\n // A post-open error is always followed by a close event, and\n // that's where reconnection gets decided. Nothing to do here except\n // not leave the event unhandled.\n };\n\n this.send({\n type: ClientMessageType.ROOM_JOIN,\n roomId: this.options.roomId,\n region: this.options.region,\n });\n });\n }\n\n private handleMessage(message: ServerMessage): void {\n if (message.type === ServerMessageType.ERROR) {\n const error = this.toError(message.code, message.message);\n this.logger.warn('signaling error', message.code, message.message);\n // Fatal errors end the session. Retryable ones belong to the\n // adapter, glare being the usual suspect, which it sorts out by\n // retrying its offer.\n if (FATAL_ERROR_CODES.has(message.code)) {\n this.closedByCaller = true;\n this.socket?.close();\n this.emit('failed', error);\n return;\n }\n }\n\n this.emit('message', message);\n }\n\n private handleClose(event: CloseEvent): void {\n if (this.closedByCaller) {\n this.emit('closed');\n return;\n }\n if (!this.options.autoReconnect) {\n this.emit(\n 'failed',\n new RTCError('NETWORK_ERROR', `The signaling connection closed (code ${event.code})`),\n );\n return;\n }\n\n // 4001 is the server's authentication-failed close code. Reconnect\n // with the same rejected token and you'll get rejected again, so try a\n // refresh first and only then reconnect.\n const authFailed = event.code === 4001;\n void this.scheduleReconnect(authFailed);\n }\n\n private async scheduleReconnect(refreshFirst: boolean): Promise<void> {\n if (this.reconnectAttempts >= RECONNECT_MAX_ATTEMPTS) {\n this.emit(\n 'failed',\n new RTCError(\n 'CONNECTION_FAILED',\n `Could not re-establish signaling after ${RECONNECT_MAX_ATTEMPTS} attempts`,\n ),\n );\n return;\n }\n\n this.reconnectAttempts++;\n this.emit('reconnecting');\n\n if (refreshFirst || this.reconnectAttempts === 1) {\n // Refresh on the first attempt as well, not just after an auth\n // failure. A reconnect following a long outage very often carries an\n // expired token, and finding that out by getting rejected costs a\n // round trip and leaves a confusing line in the log.\n await this.tryRefreshToken();\n }\n\n const backoff = Math.min(RECONNECT_BASE_MS * 2 ** (this.reconnectAttempts - 1), RECONNECT_MAX_MS);\n // Full jitter. Every client picks somewhere in [0, backoff), so a\n // fleet that all dropped together doesn't all come back together.\n const delay = Math.random() * backoff;\n\n this.logger.info(\n `signaling reconnect attempt ${this.reconnectAttempts} in ${Math.round(delay)}ms`,\n );\n\n this.reconnectTimer = setTimeout(() => {\n void this.openAndJoin().catch((error) => {\n this.logger.warn('signaling reconnect failed', (error as Error).message);\n void this.scheduleReconnect(false);\n });\n }, delay);\n }\n\n private async tryRefreshToken(): Promise<void> {\n if (!this.options.refreshToken) {\n return;\n }\n try {\n this.token = await this.options.refreshToken();\n this.logger.debug('rtc token refreshed');\n } catch (error) {\n // Not fatal by itself. The existing token may well still be good,\n // and failing the reconnect here turns a recoverable blip into a\n // dropped call.\n this.logger.warn('rtc token refresh failed', (error as Error).message);\n }\n }\n\n /** Replaces the token used by future reconnects (spec §21). */\n setToken(token: string): void {\n this.token = token;\n }\n\n send(message: ClientMessage): void {\n if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {\n // Dropped, not queued. Every message here describes one moment in a\n // negotiation, and replaying a stale answer after a reconnect is\n // worse than never sending it. The reconnect re-joins and negotiates\n // from scratch anyway.\n this.logger.debug('dropping signaling message, socket not open', message.type);\n return;\n }\n this.socket.send(JSON.stringify(message));\n }\n\n /** Leaves the room and closes the socket. No reconnect afterwards. */\n close(): void {\n this.closedByCaller = true;\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = undefined;\n }\n if (this.socket?.readyState === WebSocket.OPEN) {\n this.send({ type: ClientMessageType.ROOM_LEAVE });\n this.socket.close(1000, 'client left');\n }\n this.joined = false;\n }\n\n private buildUrl(): string {\n const base = this.options.endpoint.replace(/\\/$/, '');\n // Token rides in a query parameter, because the browser's WebSocket\n // API can't set request headers. It's short-lived by design for exactly\n // this reason, and the connection has to be wss:// in production, which\n // the server's own config validation enforces.\n return `${base}?token=${encodeURIComponent(this.token)}`;\n }\n\n private parse(data: unknown): ServerMessage | undefined {\n if (typeof data !== 'string') {\n // Raven's signaling is text-only. A binary frame means something\n // else has got onto this socket, and guessing at it beats ignoring it\n // exactly never.\n this.logger.warn('ignoring non-text signaling frame');\n return undefined;\n }\n try {\n return JSON.parse(data) as ServerMessage;\n } catch {\n this.logger.warn('ignoring unparseable signaling frame');\n return undefined;\n }\n }\n\n private toError(code: SignalingErrorCode, message: string): RTCError {\n switch (code) {\n case 'INVALID_TOKEN':\n return new RTCError('INVALID_TOKEN', message);\n case 'TOKEN_EXPIRED':\n return new RTCError('TOKEN_EXPIRED', message);\n case 'ROOM_NOT_FOUND':\n return new RTCError('ROOM_NOT_FOUND', message);\n case 'UNAUTHORIZED':\n case 'PERMISSION_DENIED':\n return new RTCError('PERMISSION_DENIED', message);\n case 'ROOM_FULL':\n case 'NO_RTC_CAPACITY':\n case 'RTC_SERVER_UNREACHABLE':\n return new RTCError('CONNECTION_FAILED', message);\n case 'RATE_LIMITED':\n return new RTCError('NETWORK_ERROR', message);\n default:\n return new RTCError('SIGNALING_ERROR', message);\n }\n }\n}\n","import { RTCError } from '../../errors';\nimport { TypedEventEmitter } from '../../events';\nimport type { Logger } from '../../logger';\nimport { LocalParticipant, RemoteParticipant } from '../../participant';\nimport { LocalTrack, RemoteTrack, type TrackKind } from '../../track';\nimport {\n createCameraTrack,\n createMicrophoneTrack,\n createScreenShareTrack,\n} from '../media/capture';\nimport { NativeLocalTrackDelegate, NativeRemoteTrackDelegate } from '../media/native-track';\nimport { listDevices } from '../devices/enumerate';\nimport { connectionRoundTripTimeMs } from '../telemetry/rtc-stats';\nimport {\n ClientMessageType,\n ServerMessageType,\n type ServerMessage,\n type ServerTrack,\n} from '../signaling/protocol';\nimport { SignalingClient, type JoinedPayload } from '../signaling/signaling-client';\nimport type {\n ConnectionQuality,\n DeviceInfo,\n DeviceKind,\n SFUAdapter,\n SFUAdapterEventMap,\n SdkConnectionState,\n} from './types';\n\n/**\n * Data channel label. Has to match the SFU's `dataChannelLabel`. A channel\n * the node doesn't recognise gets closed, not quietly ignored.\n */\nconst DATA_CHANNEL_LABEL = 'raven-data';\n\n/**\n * Payload ceiling for `room.sendData()` (spec §18).\n *\n * SCTP happily fragments bigger messages, but a browser's send buffer is\n * finite, and anyone pushing megabytes down a data channel will stall\n * their own media. The channel shares the transport. 64 KiB is plenty for\n * what this is actually for (reactions, cursor positions, chat) and small\n * enough to fail loudly instead of quietly wrecking a call.\n */\nconst MAX_DATA_PAYLOAD_BYTES = 64 * 1024;\n\n/** How long to wait for the local description to be ready before answering. */\nconst ICE_GATHER_HINT_MS = 0;\n\n/** Server source string → the SDK's own track kinds. */\nfunction trackKindFromSource(source: string, kind: 'audio' | 'video'): TrackKind {\n switch (source) {\n case 'camera':\n return 'camera';\n case 'microphone':\n return 'microphone';\n case 'screenShare':\n return 'screenShare';\n default:\n return kind === 'audio' ? 'microphone' : 'camera';\n }\n}\n\ninterface SubscribedTrack {\n track: RemoteTrack;\n delegate: NativeRemoteTrackDelegate;\n participantId: string;\n trackId: string;\n}\n\n/**\n * Raven's native `SFUAdapter`: an `RTCPeerConnection` driven by Raven's own\n * signaling.\n *\n * This replaced the LiveKit adapter. `Room` and `RTCClient` were already\n * written against `SFUAdapter` and never imported livekit-client, so the\n * public API (`createRTCClient`, `room.enableCamera()`, the event names)\n * came through the swap untouched. Which is exactly why that boundary was\n * there in the first place.\n *\n * # Negotiation\n *\n * The SFU offers, we answer. That holds for publishing too: instead of\n * offering when a track is added, the adapter adds the track and lets the\n * SFU's next offer carry it. The one exception is the first publish of a\n * given kind, where no transceiver exists yet and a client-initiated offer\n * is unavoidable. The server settles the resulting glare by refusing our\n * offer with a retryable code, and `publishWithNegotiation` has another go\n * once the server's offer has been answered.\n *\n * # Track identity\n *\n * A subscribed track is identified by `(publisherId, trackId)`, pulled off\n * the SFU's `track.published` event and matched against the `MediaStream`\n * id and track id the SFU stamps on the forwarded track. `ontrack` on its\n * own won't do: it fires with a track whose id only means anything next to\n * what signaling already told us.\n */\nexport class RavenAdapter extends TypedEventEmitter<SFUAdapterEventMap> implements SFUAdapter {\n readonly localParticipant: LocalParticipant;\n readonly remoteParticipants = new Map<string, RemoteParticipant>();\n\n private readonly logger: Logger;\n private readonly autoReconnect: boolean;\n\n private pc?: RTCPeerConnection;\n private signaling?: SignalingClient;\n private dataChannel?: RTCDataChannel;\n private iceServers: RTCIceServer[] = [];\n\n private _connectionState: SdkConnectionState = 'disconnected';\n private intentionalDisconnect = false;\n\n /** Published tracks by kind, so `enableCamera(false)` knows what to kill. */\n private readonly published = new Map<TrackKind, { track: LocalTrack; delegate: NativeLocalTrackDelegate; sender: RTCRtpSender; trackId: string }>();\n\n /** Subscribed tracks by `publisherId/trackId`. */\n private readonly subscribed = new Map<string, SubscribedTrack>();\n\n /**\n * What the server says each participant publishes, ahead of the media\n * actually turning up. `ontrack` and `track.published` race and either\n * can win, so both paths check in here and whichever lands second\n * finishes the subscription.\n */\n private readonly announcedTracks = new Map<string, { participantId: string; track: ServerTrack }>();\n\n /** Tracks whose media arrived before the announcement. */\n private readonly pendingMedia = new Map<string, { stream: MediaStream; track: MediaStreamTrack; receiver: RTCRtpReceiver }>();\n\n /** Last ICE/peer state the SFU told us about. Diagnostics only. */\n private sfuIceState?: string;\n private sfuPeerState?: string;\n\n constructor(logger: Logger, autoReconnect: boolean) {\n super();\n this.logger = logger;\n this.autoReconnect = autoReconnect;\n this.localParticipant = new LocalParticipant('');\n }\n\n get connectionState(): SdkConnectionState {\n return this._connectionState;\n }\n\n /**\n * The SFU's read on this connection's health.\n *\n * Right now that's `'unknown'` unless the SFU has reported a failure.\n *\n * TODO: return a real verdict once the SFU computes one.\n *\n * Known gap, not an oversight. The old adapter passed through LiveKit's\n * server-computed verdict, which had a vantage point no client can get\n * near: the SFU sees loss and jitter on every leg of the room, not just\n * this one. Raven's SFU doesn't work out an equivalent yet. Dressing a\n * client-side guess up as a server verdict is precisely the fabricated\n * metric spec §19 rules out, so this says \"unknown\" until the SFU can\n * answer honestly. `room.getConnectionStats()` gives you real per-track\n * numbers in the meantime.\n */\n getConnectionQuality(): ConnectionQuality {\n if (this.sfuPeerState === 'failed' || this._connectionState === 'failed') {\n return 'lost';\n }\n return 'unknown';\n }\n\n /** Diagnostics the LiveKit adapter never could give us (see `Room.getDiagnostics()`). */\n getIceConnectionState(): string | undefined {\n return this.pc?.iceConnectionState;\n }\n\n getSignalingState(): string | undefined {\n return this.pc?.signalingState;\n }\n\n /** The SFU's own view. It can disagree with the local one, and that disagreement is usually the interesting bit. */\n getRemoteConnectionState(): { iceState?: string; peerState?: string } {\n return { iceState: this.sfuIceState, peerState: this.sfuPeerState };\n }\n\n async getConnectionRoundTripTimeMs(): Promise<number | undefined> {\n return this.pc ? connectionRoundTripTimeMs(this.pc) : undefined;\n }\n\n // --- Connection --------------------------------------------------------\n\n async connect(endpoint: string, token: string, iceServers?: RTCIceServer[]): Promise<void> {\n this.iceServers = iceServers ?? [];\n this.setConnectionState('connecting');\n\n const roomId = roomIdFromToken(token);\n\n const signaling = new SignalingClient({\n endpoint,\n token,\n roomId,\n autoReconnect: this.autoReconnect,\n logger: this.logger,\n });\n this.signaling = signaling;\n\n signaling.on('message', (message) => void this.handleSignalingMessage(message));\n signaling.on('reconnecting', () => {\n this.setConnectionState('reconnecting');\n // The old PeerConnection is no use to us; the server allocates a\n // fresh session on rejoin. Tear it down now instead of at rejoin\n // time, so anyone inspecting state mid-reconnect doesn't find a\n // connection that looks alive and forwards nothing.\n this.teardownPeerConnection();\n });\n signaling.on('joined', (payload) => void this.handleJoined(payload));\n signaling.on('failed', (error) => {\n this.logger.error('signaling failed', error.message);\n this.setConnectionState('failed');\n });\n signaling.on('closed', () => {\n this.setConnectionState(this.intentionalDisconnect ? 'disconnected' : 'failed');\n });\n\n try {\n const joined = await signaling.connect();\n this.localParticipant._setIdentity(participantIdFromToken(token));\n await this.handleJoined(joined);\n } catch (error) {\n this.setConnectionState('failed');\n throw error instanceof RTCError\n ? error\n : new RTCError('CONNECTION_FAILED', 'Could not join the room', error);\n }\n }\n\n /**\n * Applies whatever room state the server reported at join.\n *\n * Runs on first join and after every reconnect. On a reconnect the\n * server's participant list wins outright and the old one goes in the\n * bin: anyone who left during the outage must not linger, anyone who\n * joined during it must show up.\n */\n private async handleJoined(payload: JoinedPayload): Promise<void> {\n this.logger.debug(\n 'room state at join',\n `${payload.participants.length} participant(s)`,\n payload.rtcServer ? `on ${payload.rtcServer}` : '',\n );\n\n // Reconcile, don't append. Leaves for anyone gone, joins for anyone\n // new, everybody else untouched, so a reconnect doesn't make every\n // tile in the UI flash.\n const present = new Set(payload.participants.map((participant) => participant.id));\n for (const [id, participant] of this.remoteParticipants) {\n if (!present.has(id)) {\n this.remoteParticipants.delete(id);\n this.emit('participantLeft', participant);\n }\n }\n\n for (const entry of payload.participants) {\n let participant = this.remoteParticipants.get(entry.id);\n if (!participant) {\n participant = new RemoteParticipant(entry.id);\n this.remoteParticipants.set(entry.id, participant);\n this.emit('participantJoined', participant);\n }\n for (const track of entry.tracks ?? []) {\n this.announceTrack(entry.id, track);\n }\n }\n }\n\n private async handleSignalingMessage(message: ServerMessage): Promise<void> {\n switch (message.type) {\n case ServerMessageType.ROOM_JOINED:\n // Usually the join handshake eats this, but handle it here too.\n // The server can re-send room state on an established connection,\n // and `handleJoined` reconciles, not appends, so applying it\n // again is harmless and keeps the client's view honest.\n await this.handleJoined({\n roomId: message.roomId,\n participants: message.participants,\n rtcServer: message.rtcServer,\n region: message.region,\n });\n return;\n\n case ServerMessageType.SDP_OFFER:\n await this.handleOffer(message.sdp);\n return;\n\n case ServerMessageType.SDP_ANSWER:\n await this.handleAnswer(message.sdp);\n return;\n\n case ServerMessageType.ICE_CANDIDATE:\n await this.handleRemoteCandidate(message);\n return;\n\n case ServerMessageType.PARTICIPANT_JOINED: {\n const existing = this.remoteParticipants.get(message.participant.id);\n if (existing) {\n return;\n }\n const participant = new RemoteParticipant(message.participant.id);\n this.remoteParticipants.set(participant.identity, participant);\n this.emit('participantJoined', participant);\n return;\n }\n\n case ServerMessageType.PARTICIPANT_LEFT: {\n const participant = this.remoteParticipants.get(message.participant.id);\n if (!participant) {\n return;\n }\n this.remoteParticipants.delete(participant.identity);\n // Their tracks leave with them. The PeerConnection fires\n // `onremovetrack` as well, but lean on that alone and the UI keeps\n // showing a departed participant's frozen last frame until the\n // browser gets round to it.\n for (const [key, subscription] of this.subscribed) {\n if (subscription.participantId === participant.identity) {\n this.subscribed.delete(key);\n this.emit('trackUnsubscribed', subscription.track, participant);\n }\n }\n this.emit('participantLeft', participant);\n return;\n }\n\n case ServerMessageType.TRACK_PUBLISHED:\n this.announceTrack(message.participantId, message.track);\n return;\n\n case ServerMessageType.TRACK_UNPUBLISHED: {\n const key = subscriptionKey(message.participantId, message.trackId);\n this.announcedTracks.delete(key);\n this.pendingMedia.delete(key);\n const subscription = this.subscribed.get(key);\n const participant = this.remoteParticipants.get(message.participantId);\n if (subscription && participant) {\n this.subscribed.delete(key);\n this.emit('trackUnpublished', subscription.track.kind, participant);\n this.emit('trackUnsubscribed', subscription.track, participant);\n }\n return;\n }\n\n case ServerMessageType.TRACK_MUTED:\n case ServerMessageType.TRACK_UNMUTED: {\n const muted = message.type === ServerMessageType.TRACK_MUTED;\n const key = subscriptionKey(message.participantId, message.trackId);\n const subscription = this.subscribed.get(key);\n const participant = this.remoteParticipants.get(message.participantId);\n if (!subscription || !participant) {\n return;\n }\n // The publisher's mute, not the browser's \"nothing arriving\" flag.\n // See NativeRemoteTrackDelegate.\n subscription.delegate.setPublisherMuted(muted);\n this.emit(muted ? 'trackMuted' : 'trackUnmuted', subscription.track.kind, participant);\n return;\n }\n\n case ServerMessageType.CONNECTION_STATE:\n this.sfuIceState = message.iceState;\n this.sfuPeerState = message.peerState;\n this.logger.debug('sfu connection state', message.iceState, message.peerState);\n return;\n\n case ServerMessageType.ERROR:\n // The signaling client handles fatal codes by closing. Whatever\n // reaches here is retryable, glare most of all, which the publish\n // path deals with.\n if (message.code === 'NEGOTIATION_GLARE') {\n this.logger.debug('publish deferred by glare; will retry after the next offer');\n return;\n }\n this.emit('mediaError', new Error(message.message));\n return;\n\n default:\n return;\n }\n }\n\n // --- Negotiation -------------------------------------------------------\n\n private ensurePeerConnection(): RTCPeerConnection {\n if (this.pc) {\n return this.pc;\n }\n\n const pc = new RTCPeerConnection({ iceServers: this.iceServers });\n this.pc = pc;\n\n pc.onicecandidate = (event) => {\n if (!event.candidate) {\n // End of gathering. We don't forward it. The server reads \"no more\n // candidates\" the same way, and an explicit end-of-candidates\n // message is one more thing three client implementations would\n // have to agree on.\n return;\n }\n this.signaling?.send({\n type: ClientMessageType.ICE_CANDIDATE,\n candidate: event.candidate.candidate,\n sdpMid: event.candidate.sdpMid ?? undefined,\n sdpMLineIndex: event.candidate.sdpMLineIndex ?? undefined,\n usernameFragment: event.candidate.usernameFragment ?? undefined,\n });\n };\n\n pc.onconnectionstatechange = () => {\n this.logger.debug('peer connection state', pc.connectionState);\n switch (pc.connectionState) {\n case 'connected':\n this.setConnectionState('connected');\n break;\n case 'failed':\n // Whether to reconnect is the signaling client's call. Say\n // 'reconnecting' when it won't and we've lied; say 'failed' when\n // it will and we're merely early, which the next state change\n // sorts out.\n this.setConnectionState(this.autoReconnect ? 'reconnecting' : 'failed');\n break;\n case 'disconnected':\n // Transient by definition in WebRTC; ICE may well sort itself\n // out. Not surfaced as a state change, because a UI flashing\n // \"reconnecting\" at every little blip is worse than one that\n // holds its nerve.\n break;\n default:\n break;\n }\n };\n\n pc.ontrack = (event) => this.handleIncomingTrack(event);\n\n pc.ondatachannel = (event) => {\n if (event.channel.label !== DATA_CHANNEL_LABEL) {\n return;\n }\n this.attachDataChannel(event.channel);\n };\n\n return pc;\n }\n\n private async handleOffer(sdp: string): Promise<void> {\n const pc = this.ensurePeerConnection();\n try {\n await pc.setRemoteDescription({ type: 'offer', sdp });\n const answer = await pc.createAnswer();\n await pc.setLocalDescription(answer);\n\n // Send `pc.localDescription`, not `answer`. The browser may have\n // stuffed candidates into it since, and the pre-set copy would lose\n // them.\n this.signaling?.send({\n type: ClientMessageType.SDP_ANSWER,\n sdp: pc.localDescription?.sdp ?? answer.sdp ?? '',\n });\n\n // Anything publishing had to defer because of glare can go ahead\n // now the server's offer is answered.\n this.flushDeferredPublishes();\n } catch (error) {\n this.logger.error('failed to answer offer', (error as Error).message);\n this.emit('mediaError', new Error('Could not answer the server\\'s offer'));\n }\n }\n\n private async handleAnswer(sdp: string): Promise<void> {\n if (!this.pc) {\n return;\n }\n try {\n await this.pc.setRemoteDescription({ type: 'answer', sdp });\n } catch (error) {\n this.logger.error('failed to apply answer', (error as Error).message);\n }\n }\n\n private async handleRemoteCandidate(message: {\n candidate: string;\n sdpMid?: string;\n sdpMLineIndex?: number;\n usernameFragment?: string;\n }): Promise<void> {\n if (!this.pc) {\n return;\n }\n try {\n await this.pc.addIceCandidate({\n candidate: message.candidate,\n sdpMid: message.sdpMid,\n sdpMLineIndex: message.sdpMLineIndex,\n usernameFragment: message.usernameFragment,\n });\n } catch (error) {\n // Candidates turn up just before a remote description gets set, or\n // for a transceiver that's already gone, all the time. Neither is\n // worth surfacing; the connection comes up on the candidates that do\n // apply.\n this.logger.debug('ignoring ICE candidate', (error as Error).message);\n }\n }\n\n /** Publishes that glare pushed back, retried once we've answered the server. */\n private deferredPublishes: (() => void)[] = [];\n\n private flushDeferredPublishes(): void {\n const pending = this.deferredPublishes;\n this.deferredPublishes = [];\n for (const retry of pending) {\n retry();\n }\n }\n\n /**\n * Offers, so the server hears about a track we just added.\n *\n * Only needed when adding the track created a new transceiver, which is\n * the first publish of each kind. Later publishes of the same kind reuse\n * the transceiver and hitch a ride on the server's next offer.\n */\n private async negotiatePublish(): Promise<void> {\n const pc = this.pc;\n const signaling = this.signaling;\n if (!pc || !signaling) {\n return;\n }\n\n if (pc.signalingState !== 'stable') {\n // Server already has an offer in flight. Answer that first and\n // retry, instead of putting a competing offer on the wire.\n this.logger.debug('deferring publish negotiation until stable');\n this.deferredPublishes.push(() => void this.negotiatePublish());\n return;\n }\n\n try {\n const offer = await pc.createOffer();\n await pc.setLocalDescription(offer);\n await waitTick();\n signaling.send({\n type: ClientMessageType.SDP_OFFER,\n sdp: pc.localDescription?.sdp ?? offer.sdp ?? '',\n });\n } catch (error) {\n this.logger.error('publish negotiation failed', (error as Error).message);\n throw new RTCError('MEDIA_ERROR', 'Could not negotiate the published track', error);\n }\n }\n\n // --- Incoming media ----------------------------------------------------\n\n /**\n * Matches an arriving track up with whatever signaling said about it.\n *\n * The SFU forwards every subscription carrying the *publisher's* track id\n * as the SDP `msid` track id, and that's what makes attribution possible\n * without a side channel. `ontrack` and `track.published` race, so this\n * only completes a subscription when both halves are in, parking\n * whichever showed up first.\n *\n * # Why the id comes from the SDP, not the track\n *\n * `RTCTrackEvent.track.id` is **not** the remote track id. Chrome mints\n * a brand-new local id for a received track and pays no attention to the\n * `msid`; the id in `a=msid:<stream> <track>` is the remote one. So\n * matching on `event.track.id` never matched anything, ever. And because\n * the unmatched track got parked as \"media arrived early\", it failed in\n * total silence: a subscription that simply never completed, not an\n * error anybody could see. Reading the `msid` is the standards-defined\n * way to get the id the remote peer actually picked.\n */\n private handleIncomingTrack(event: RTCTrackEvent): void {\n const [stream] = event.streams;\n // In order of preference: the msid track id, which is what the SFU\n // actually labelled this with, then the local track id, for any stack\n // that does adopt the msid.\n const trackId = this.remoteTrackIdFor(event) ?? event.track.id;\n\n // Whichever announcement mentions this track id names the publisher.\n // The SFU guarantees track ids are unique inside a room, since they\n // come from separate publishers' own tracks.\n const announcement = this.findAnnouncementForTrack(trackId);\n\n if (!announcement) {\n // Log what *was* announced. Nine times out of ten a subscription\n // that never completes is an id mismatch, not a real ordering race,\n // and without this line the two look identical.\n this.logger.debug(\n 'media arrived before its announcement',\n `resolved=${trackId}`,\n `local=${event.track.id}`,\n `stream=${stream?.id ?? 'none'}`,\n `mid=${event.transceiver?.mid ?? 'none'}`,\n `announced=[${Array.from(this.announcedTracks.values())\n .map((entry) => `${entry.participantId}:${entry.track.trackId}`)\n .join(', ')}]`,\n );\n this.pendingMedia.set(pendingKey(trackId), {\n stream: stream ?? new MediaStream([event.track]),\n track: event.track,\n receiver: event.receiver,\n });\n return;\n }\n\n this.completeSubscription(\n announcement.participantId,\n announcement.track,\n event.track,\n event.receiver,\n );\n }\n\n /**\n * The remote track id for an arriving track, read out of the remote SDP.\n *\n * Found via the transceiver's `mid` rather than by scanning every\n * `a=msid:` line. Someone publishing both a camera and a screen share\n * has two video m-sections, and picking the wrong one labels a screen\n * share as somebody's face.\n *\n * Returns undefined when the SDP doesn't say, either an `msid`-less\n * offer or a transceiver with no mid yet, so the caller can fall back\n * instead of guessing.\n */\n private remoteTrackIdFor(event: RTCTrackEvent): string | undefined {\n const mid = event.transceiver?.mid;\n const sdp = this.pc?.remoteDescription?.sdp;\n if (!mid || !sdp) {\n return undefined;\n }\n\n // First chunk is the session section and has no m= line. Everything\n // after it is one media description.\n const sections = sdp.split(/\\r?\\nm=/).slice(1);\n for (const section of sections) {\n const lines = section.split(/\\r?\\n/);\n if (!lines.some((line) => line.trim() === `a=mid:${mid}`)) {\n continue;\n }\n const msid = lines.find((line) => line.startsWith('a=msid:'));\n // `a=msid:<stream-id> <track-id>`. The stream-only form is legal\n // and has no track id in it to hand back.\n const trackId = msid?.slice('a=msid:'.length).trim().split(/\\s+/)[1];\n return trackId && trackId.length > 0 ? trackId : undefined;\n }\n return undefined;\n }\n\n private findAnnouncementForTrack(\n trackId: string,\n ): { participantId: string; track: ServerTrack } | undefined {\n for (const announcement of this.announcedTracks.values()) {\n if (announcement.track.trackId === trackId) {\n return announcement;\n }\n }\n return undefined;\n }\n\n private announceTrack(participantId: string, track: ServerTrack): void {\n const key = subscriptionKey(participantId, track.trackId);\n this.announcedTracks.set(key, { participantId, track });\n this.logger.debug('track announced', `${participantId}:${track.trackId}`, track.kind, track.source);\n\n const participant = this.remoteParticipants.get(participantId);\n if (participant) {\n this.emit('trackPublished', trackKindFromSource(track.source, track.kind), participant);\n }\n\n // Media might already have beaten us here.\n const pending = this.pendingMedia.get(pendingKey(track.trackId));\n if (pending) {\n this.pendingMedia.delete(pendingKey(track.trackId));\n this.completeSubscription(participantId, track, pending.track, pending.receiver);\n }\n }\n\n private completeSubscription(\n participantId: string,\n serverTrack: ServerTrack,\n mediaStreamTrack: MediaStreamTrack,\n receiver: RTCRtpReceiver,\n ): void {\n const participant = this.remoteParticipants.get(participantId);\n if (!participant) {\n this.logger.debug('track for an unknown participant', participantId);\n return;\n }\n\n const key = subscriptionKey(participantId, serverTrack.trackId);\n if (this.subscribed.has(key)) {\n return;\n }\n\n const delegate = new NativeRemoteTrackDelegate(mediaStreamTrack, receiver);\n delegate.setPublisherMuted(serverTrack.muted);\n const kind = trackKindFromSource(serverTrack.source, serverTrack.kind);\n const track = new RemoteTrack(delegate, kind);\n\n this.subscribed.set(key, { track, delegate, participantId, trackId: serverTrack.trackId });\n participant.tracks.push(track);\n this.emit('trackSubscribed', track, participant);\n\n mediaStreamTrack.onended = () => {\n const subscription = this.subscribed.get(key);\n if (!subscription) {\n return;\n }\n this.subscribed.delete(key);\n const index = participant.tracks.indexOf(subscription.track);\n if (index !== -1) {\n participant.tracks.splice(index, 1);\n }\n this.emit('trackUnsubscribed', subscription.track, participant);\n };\n }\n\n // --- Publishing --------------------------------------------------------\n\n async enableCamera(enabled: boolean): Promise<LocalTrack | undefined> {\n return enabled\n ? this.publishKind('camera', () => createCameraTrack())\n : this.unpublishKind('camera');\n }\n\n async enableMicrophone(enabled: boolean): Promise<LocalTrack | undefined> {\n return enabled\n ? this.publishKind('microphone', () => createMicrophoneTrack())\n : this.unpublishKind('microphone');\n }\n\n async enableScreenShare(enabled: boolean): Promise<LocalTrack | undefined> {\n return enabled\n ? this.publishKind('screenShare', () => createScreenShareTrack())\n : this.unpublishKind('screenShare');\n }\n\n private async publishKind(\n kind: TrackKind,\n capture: () => Promise<LocalTrack>,\n ): Promise<LocalTrack | undefined> {\n const existing = this.published.get(kind);\n if (existing) {\n // Already publishing, so unmute instead of capturing again. A\n // second getUserMedia on the same device is slower and on some\n // platforms just fails.\n await existing.track.unmute();\n this.signaling?.send({\n type: ClientMessageType.TRACK_MUTE,\n trackId: existing.trackId,\n muted: false,\n });\n return existing.track;\n }\n\n const track = await capture();\n await this.publish(track);\n return track;\n }\n\n private async unpublishKind(kind: TrackKind): Promise<undefined> {\n const existing = this.published.get(kind);\n if (!existing) {\n return undefined;\n }\n await this.unpublish(existing.track);\n return undefined;\n }\n\n async publish(track: LocalTrack): Promise<void> {\n const pc = this.ensurePeerConnection();\n const delegate = track['delegate'] as unknown;\n if (!(delegate instanceof NativeLocalTrackDelegate)) {\n throw new RTCError(\n 'MEDIA_ERROR',\n 'This track was not created by the Raven SDK and cannot be published',\n );\n }\n\n const stream =\n typeof MediaStream !== 'undefined'\n ? new MediaStream([track.mediaStreamTrack])\n : undefined;\n\n let sender: RTCRtpSender;\n try {\n sender = stream\n ? pc.addTrack(track.mediaStreamTrack, stream)\n : pc.addTrack(track.mediaStreamTrack);\n } catch (error) {\n throw new RTCError('MEDIA_ERROR', 'Could not add the track to the connection', error);\n }\n\n // Declared over signaling, never inferred from the SDP. A page can't\n // pick the stream or track id the SDP carries, since both are\n // read-only, which leaves codec kind as all the SFU would have to go\n // on. And that can't tell a screen share from a camera (spec §16).\n // Sent before negotiating, so the source is known by the time the\n // track lands on the node.\n const source = declaredSourceFor(track.kind);\n if (source) {\n this.signaling?.send({\n type: ClientMessageType.TRACK_PUBLISH,\n trackId: track.mediaStreamTrack.id,\n source,\n });\n }\n\n delegate.setSender(sender);\n await this.applySimulcast(sender, track.kind);\n\n this.published.set(track.kind, {\n track,\n delegate,\n sender,\n trackId: track.mediaStreamTrack.id,\n });\n if (!this.localParticipant.tracks.includes(track)) {\n this.localParticipant.tracks.push(track);\n }\n\n // A screen share the user stops from the browser's own bar ends the\n // track without telling us. Unpublishing here keeps the room's view\n // correct without the application having to watch for it.\n track.mediaStreamTrack.onended = () => {\n void this.unpublish(track).catch(() => undefined);\n };\n\n await this.negotiatePublish();\n this.emit('localTrackPublished', track);\n }\n\n async unpublish(track: LocalTrack): Promise<void> {\n const entry = this.published.get(track.kind);\n if (!entry || entry.track !== track) {\n return;\n }\n\n this.published.delete(track.kind);\n const index = this.localParticipant.tracks.indexOf(track);\n if (index !== -1) {\n this.localParticipant.tracks.splice(index, 1);\n }\n\n entry.delegate.setSender(undefined);\n try {\n this.pc?.removeTrack(entry.sender);\n } catch (error) {\n this.logger.debug('removeTrack failed', (error as Error).message);\n }\n track.mediaStreamTrack.stop();\n\n await this.negotiatePublish();\n this.emit('localTrackUnpublished', track);\n }\n\n /**\n * Sets up simulcast on a video sender (spec §15).\n *\n * Three spatial layers, each a quarter of the previous one's pixel count.\n * That's the standard ladder and the one browsers actually implement\n * well. Applied with `setParameters` after `addTrack` instead of through\n * `addTransceiver`'s `sendEncodings`, because the transceiver may already\n * exist from the SFU's offer and re-adding it would renegotiate for\n * nothing at all.\n *\n * Audio gets left alone. There's no spatial layering to do, and Opus\n * already sorts its own bitrate out.\n */\n private async applySimulcast(sender: RTCRtpSender, kind: TrackKind): Promise<void> {\n if (kind === 'microphone' || sender.track?.kind !== 'video') {\n return;\n }\n // Screen shares don't simulcast, on purpose. The content is usually\n // text, and dropping resolution wrecks legibility in a way it never\n // does for a face. One high-quality layer is the better trade.\n if (kind === 'screenShare') {\n return;\n }\n\n try {\n const parameters = sender.getParameters();\n // Some browsers report no encodings at all until the first\n // negotiation completes, and setting them then just fails. The SFU\n // falls back to a single layer, which is fine, not broken.\n if (!parameters.encodings || parameters.encodings.length === 0) {\n return;\n }\n\n parameters.encodings = [\n { rid: 'low', scaleResolutionDownBy: 4, maxBitrate: 150_000 },\n { rid: 'medium', scaleResolutionDownBy: 2, maxBitrate: 500_000 },\n { rid: 'high', scaleResolutionDownBy: 1, maxBitrate: 1_500_000 },\n ];\n await sender.setParameters(parameters);\n } catch (error) {\n // Not fatal. A publisher without simulcast still publishes, and\n // every subscriber gets the one layer.\n this.logger.debug('simulcast not applied', (error as Error).message);\n }\n }\n\n // --- Data channel ------------------------------------------------------\n\n private attachDataChannel(channel: RTCDataChannel): void {\n this.dataChannel = channel;\n channel.binaryType = 'arraybuffer';\n channel.onmessage = (event: MessageEvent) => {\n const payload = toUint8Array(event.data);\n if (payload) {\n // No participant attribution here. The SFU fans data out over\n // each recipient's own channel, so the transport carries no sender\n // identity at all. Attributing it would mean trusting a field the\n // sender controls, and saying nothing beats that.\n this.emit('dataReceived', payload, undefined);\n }\n };\n channel.onclose = () => {\n if (this.dataChannel === channel) {\n this.dataChannel = undefined;\n }\n };\n }\n\n async sendData(payload: Uint8Array<ArrayBuffer>): Promise<void> {\n if (payload.byteLength > MAX_DATA_PAYLOAD_BYTES) {\n throw new RTCError(\n 'MEDIA_ERROR',\n `Data payload is ${payload.byteLength} bytes, over the ${MAX_DATA_PAYLOAD_BYTES}-byte limit`,\n );\n }\n\n const channel = this.dataChannel ?? this.openDataChannel();\n if (!channel) {\n throw new RTCError('CONNECTION_FAILED', 'sendData() requires an active connection');\n }\n if (channel.readyState !== 'open') {\n throw new RTCError('CONNECTION_FAILED', 'The data channel is not open yet');\n }\n\n try {\n channel.send(payload);\n } catch (error) {\n throw new RTCError('PERMISSION_DENIED', 'Could not send data; check the token grants publishData', error);\n }\n }\n\n /**\n * Opens the data channel when something actually wants it.\n *\n * Not at connect time. A channel costs an SCTP association and most\n * calls never send a byte of data. The client creates it, not the\n * server, because the client is the side that knows it needs one.\n */\n private openDataChannel(): RTCDataChannel | undefined {\n if (!this.pc) {\n return undefined;\n }\n // Ordered and reliable. That's the default, and what anyone sending\n // structured messages expects. Unreliable delivery would suit\n // high-frequency cursor updates, but as an opt-in later, not as a\n // default that surprises everybody else.\n const channel = this.pc.createDataChannel(DATA_CHANNEL_LABEL, { ordered: true });\n this.attachDataChannel(channel);\n return channel;\n }\n\n // --- Devices -----------------------------------------------------------\n\n async getDevices(kind?: DeviceKind): Promise<DeviceInfo[]> {\n return listDevices(kind);\n }\n\n async setDevice(kind: DeviceKind, deviceId: string): Promise<void> {\n switch (kind) {\n case 'videoinput':\n return this.replaceDevice('camera', () => createCameraTrack({ deviceId }));\n case 'audioinput':\n return this.replaceDevice('microphone', () => createMicrophoneTrack({ deviceId }));\n case 'audiooutput':\n return this.setAudioOutput(deviceId);\n default:\n throw new RTCError('DEVICE_NOT_FOUND', `Unknown device kind \"${String(kind)}\"`);\n }\n }\n\n /**\n * Swaps the device behind a published track without renegotiating.\n *\n * `replaceTrack` is what makes it seamless. Transceiver, SSRC, and every\n * subscriber's view of the track all stay put, so nobody else in the\n * room notices a thing.\n */\n private async replaceDevice(kind: TrackKind, capture: () => Promise<LocalTrack>): Promise<void> {\n const entry = this.published.get(kind);\n if (!entry) {\n // Nothing published, so nothing to switch. Capturing and publishing\n // here would turn a device preference into a publish nobody asked\n // for.\n return;\n }\n\n const replacement = await capture();\n const previous = entry.track.mediaStreamTrack;\n await entry.delegate.replaceTrack(replacement.mediaStreamTrack);\n previous.stop();\n }\n\n /**\n * Points this room's remote audio at a different output device.\n *\n * `setSinkId` works per element, so this walks whatever elements each\n * remote audio track is attached to. Safari doesn't have `setSinkId` at\n * all. `Room.setSpeakerDevice()` checks and throws before we get here,\n * so an unsupported browser gets a real error instead of a silent no-op.\n */\n private async setAudioOutput(deviceId: string): Promise<void> {\n const failures: unknown[] = [];\n\n for (const subscription of this.subscribed.values()) {\n if (subscription.track.kind === 'camera' || subscription.track.kind === 'screenShare') {\n continue;\n }\n for (const element of subscription.track.detach()) {\n const withSink = element as HTMLMediaElement & { setSinkId?: (id: string) => Promise<void> };\n try {\n await withSink.setSinkId?.(deviceId);\n } catch (error) {\n failures.push(error);\n }\n subscription.track.attach(element);\n }\n }\n\n if (failures.length > 0) {\n throw new RTCError('DEVICE_NOT_FOUND', 'Could not switch the audio output device', failures[0]);\n }\n }\n\n // --- Teardown ----------------------------------------------------------\n\n async disconnect(): Promise<void> {\n this.intentionalDisconnect = true;\n\n for (const entry of this.published.values()) {\n entry.track.mediaStreamTrack.stop();\n }\n this.published.clear();\n this.localParticipant.tracks.length = 0;\n\n this.signaling?.close();\n this.teardownPeerConnection();\n\n this.remoteParticipants.clear();\n this.subscribed.clear();\n this.announcedTracks.clear();\n this.pendingMedia.clear();\n\n this.setConnectionState('disconnected');\n }\n\n private teardownPeerConnection(): void {\n if (this.dataChannel) {\n try {\n this.dataChannel.close();\n } catch {\n // Went with the connection already.\n }\n this.dataChannel = undefined;\n }\n if (!this.pc) {\n return;\n }\n // Clear the handlers before closing, so a state change fired during\n // teardown doesn't get mistaken for a connection failure.\n this.pc.onicecandidate = null;\n this.pc.onconnectionstatechange = null;\n this.pc.ontrack = null;\n this.pc.ondatachannel = null;\n try {\n this.pc.close();\n } catch {\n // Already closed.\n }\n this.pc = undefined;\n }\n\n private setConnectionState(state: SdkConnectionState): void {\n if (this._connectionState === state) {\n return;\n }\n this._connectionState = state;\n this.emit('connectionStateChanged', state);\n }\n}\n\nfunction subscriptionKey(participantId: string, trackId: string): string {\n return `${participantId}/${trackId}`;\n}\n\nfunction pendingKey(trackId: string): string {\n return `media:${trackId}`;\n}\n\n/** SDK track kinds → the source names the wire protocol uses. */\nfunction declaredSourceFor(kind: TrackKind): 'camera' | 'microphone' | 'screenShare' | undefined {\n switch (kind) {\n case 'camera':\n case 'microphone':\n case 'screenShare':\n return kind;\n default:\n return undefined;\n }\n}\n\n/**\n * Turns whatever a data channel handed us into bytes.\n *\n * Uses `Object.prototype.toString` instead of `instanceof`, because\n * `instanceof ArrayBuffer` comes back false for a buffer that crossed a\n * realm boundary. That's not a test-environment curiosity either: Web\n * Workers, iframes and a few bundler shims each bring their own\n * `ArrayBuffer`. An `instanceof` check in that situation silently drops\n * every single message.\n */\nfunction toUint8Array(data: unknown): Uint8Array | undefined {\n if (typeof data === 'string') {\n return new TextEncoder().encode(data);\n }\n if (ArrayBuffer.isView(data)) {\n // Respect the view's offset and length. A Uint8Array covering part of\n // a bigger buffer must not be read as the whole thing.\n return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n }\n if (isArrayBufferLike(data)) {\n return new Uint8Array(data);\n }\n return undefined;\n}\n\nfunction isArrayBufferLike(value: unknown): value is ArrayBuffer {\n const tag = Object.prototype.toString.call(value);\n return tag === '[object ArrayBuffer]' || tag === '[object SharedArrayBuffer]';\n}\n\n/** Yields once, giving a just-set local description a beat to settle before we read it. */\nfunction waitTick(): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ICE_GATHER_HINT_MS));\n}\n\n/**\n * Reads which room this token was minted for.\n *\n * The token is a Raven JWT and its payload is readable, not secret. Same\n * information the server is going to act on. We decode it; we never trust\n * it. The server re-verifies the signature, and anything a client fiddles\n * with here only changes which room it *asks* for.\n */\nfunction roomIdFromToken(token: string): string {\n const claims = decodeClaims(token);\n const roomId = claims?.rid;\n if (typeof roomId !== 'string' || roomId.length === 0) {\n throw new RTCError('INVALID_TOKEN', 'RTC token does not name a room');\n }\n return roomId;\n}\n\nfunction participantIdFromToken(token: string): string {\n const claims = decodeClaims(token);\n return typeof claims?.sub === 'string' ? claims.sub : '';\n}\n\nfunction decodeClaims(token: string): Record<string, unknown> | undefined {\n const parts = token.split('.');\n if (parts.length !== 3) {\n return undefined;\n }\n try {\n const base64 = parts[1].replace(/-/g, '+').replace(/_/g, '/');\n return JSON.parse(atob(base64)) as Record<string, unknown>;\n } catch {\n return undefined;\n }\n}\n","/**\n * Generated client-side, once per `join()`, and never changed for the life\n * of that connection. This is the id a developer sees in the dashboard, in\n * `raven connections inspect`, and in every error report (Phase 9 spec §8).\n *\n * Prefers `crypto.randomUUID()`, which every SDK-supported browser has.\n * The manual fallback only ever matters in odd test or embedding\n * environments.\n */\nexport function generateConnectionId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return `conn_${crypto.randomUUID().replace(/-/g, '')}`;\n }\n let id = '';\n for (let i = 0; i < 32; i++) {\n id += Math.floor(Math.random() * 16).toString(16);\n }\n return `conn_${id}`;\n}\n","export interface PlatformInfo {\n platform: string;\n browser: string;\n networkType?: string;\n}\n\n/**\n * Best-effort, browser-only detection. Never throws, never assumes\n * `navigator` exists, since unit tests run under Node. Coarse on purpose:\n * a browser/device category (Phase 9 spec §4), not a fingerprinting\n * library.\n */\nexport function detectPlatform(): PlatformInfo {\n if (typeof navigator === 'undefined') {\n return { platform: 'unknown', browser: 'unknown' };\n }\n\n const ua = navigator.userAgent ?? '';\n let browser = 'unknown';\n if (/edg\\//i.test(ua)) browser = 'edge';\n else if (/firefox|fxios/i.test(ua)) browser = 'firefox';\n else if (/chrome|crios/i.test(ua)) browser = 'chrome';\n else if (/safari/i.test(ua)) browser = 'safari';\n\n let platform = 'web';\n if (/android/i.test(ua)) platform = 'android';\n else if (/iphone|ipad|ipod/i.test(ua)) platform = 'ios';\n\n const connection = (navigator as unknown as { connection?: { effectiveType?: string } }).connection;\n const networkType = typeof connection?.effectiveType === 'string' ? connection.effectiveType : undefined;\n\n return { platform, browser, networkType };\n}\n","import type { Logger } from '../../logger';\nimport { generateConnectionId } from './connection-id';\nimport { detectPlatform } from './platform';\n\nexport interface TelemetryClient {\n readonly connectionId: string;\n /**\n * Fire and forget. Never hands back a promise anyone is meant to await,\n * never throws. See docs/telemetry.md#reliability and Phase 9 spec §11:\n * \"RTC must continue working even if telemetry fails.\"\n */\n send(type: string, data?: Record<string, unknown>): void;\n}\n\nexport interface TelemetryClientOptions {\n enabled: boolean;\n telemetryUrl?: string;\n token: string;\n sdkVersion: string;\n logger: Logger;\n}\n\n/**\n * Builds a real HTTP telemetry client when telemetry is on and a\n * `telemetryUrl` was supplied, and a no-op one otherwise. Callers never\n * have to branch on whether telemetry is active; they just call `send()`\n * and get on with it.\n *\n * `connectionId` is real and stable either way, since it doubles as the\n * SDK's public `room.connectionId` whether telemetry is enabled or not.\n */\nexport function createTelemetryClient(options: TelemetryClientOptions): TelemetryClient {\n const connectionId = generateConnectionId();\n\n if (!options.enabled || !options.telemetryUrl) {\n return { connectionId, send: () => {} };\n }\n\n return new HttpTelemetryClient(connectionId, options);\n}\n\nclass HttpTelemetryClient implements TelemetryClient {\n constructor(\n readonly connectionId: string,\n private readonly options: TelemetryClientOptions,\n ) {}\n\n send(type: string, data: Record<string, unknown> = {}): void {\n const body = {\n connectionId: this.connectionId,\n type,\n data: { sdkVersion: this.options.sdkVersion, ...detectPlatform(), ...data },\n };\n\n try {\n // Nobody awaits this, on purpose, and every failure mode gets\n // swallowed right here: network error, non-2xx, telemetryUrl\n // unreachable, the lot. A telemetry outage must never show up as an\n // RTC error.\n //\n // `keepalive: true` gives it a fighting chance of completing through\n // a page unload or tab close, which is where that final\n // \"disconnected\" event lands. Same problem `navigator.sendBeacon`\n // solves, except beacon is no use to us: it can't carry the\n // Authorization header this endpoint wants.\n fetch(`${this.options.telemetryUrl}/v1/telemetry/events`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${this.options.token}` },\n body: JSON.stringify(body),\n keepalive: true,\n })\n .then((res) => {\n if (!res.ok) {\n this.options.logger.debug('telemetry event rejected', type, res.status);\n }\n })\n .catch((error) => {\n this.options.logger.debug('telemetry event failed', type, (error as Error).message);\n });\n } catch (error) {\n this.options.logger.debug('telemetry send threw synchronously', type, (error as Error).message);\n }\n }\n}\n","/** Kept in sync with package.json by hand (no bundler JSON import, same approach as @ravenkash/cli). */\nexport const SDK_VERSION = '0.1.0';\n","import { RTCError } from './errors';\nimport { TypedEventEmitter } from './events';\nimport { createTelemetryClient, type TelemetryClient } from './internal/telemetry/telemetry-client';\nimport { detectPlatform } from './internal/telemetry/platform';\nimport type { Logger } from './logger';\nimport { LocalParticipant, RemoteParticipant } from './participant';\nimport type { ConnectionQuality, SFUAdapter, SdkConnectionState } from './internal/sfu/types';\nimport { LocalTrack, RemoteTrack, type TrackKind, type TrackStats } from './track';\nimport { SDK_VERSION } from './version';\n\nexport type ConnectionState = SdkConnectionState;\n\n/**\n * A diagnostic snapshot that's safe to paste straight into a bug report.\n * No tokens, no secrets, nothing sensitive.\n *\n * Anything we don't know comes back `undefined`; nothing here is guessed.\n * `iceConnectionState` and `signalingState` were always `undefined` under\n * the LiveKit adapter, which never exposed them. The native adapter does,\n * so they now carry the states that actually explain a failed connection.\n */\nexport interface ConnectionDiagnostics {\n connectionState: ConnectionState;\n iceConnectionState?: string;\n signalingState?: string;\n /**\n * What the SFU makes of this connection. Worth sitting next to the local\n * states, because the two can disagree, and \"server says failed, browser\n * says connected\" is a diagnosis, not a contradiction.\n */\n remoteIceConnectionState?: string;\n remotePeerConnectionState?: string;\n reconnectCount: number;\n sdkVersion: string;\n platform: string;\n browser: string;\n}\n\n/**\n * Live media-quality stats. A separate `async` method rather than another\n * field on `getDiagnostics()`, and that's on purpose. `getDiagnostics()`\n * is synchronous and cheap so you can call it from anywhere at any time.\n * Collecting real WebRTC stats is neither: it costs at least one round\n * trip through the browser's stats API per track, and squashing per-track\n * numbers into one flat object throws away the very thing that made them\n * useful in a room full of people.\n */\nexport interface ConnectionStats {\n connectionState: ConnectionState;\n /** The SFU's own read on connection health. See `ConnectionQuality`. */\n connectionQuality: ConnectionQuality;\n /** One entry per track this side has published. */\n local: TrackStats[];\n /** One entry per subscribed track, across all remote participants. */\n remote: TrackStats[];\n}\n\nexport interface RoomEventMap {\n connectionStateChanged: (state: ConnectionState) => void;\n connected: () => void;\n disconnected: () => void;\n reconnecting: () => void;\n reconnected: () => void;\n participantJoined: (participant: RemoteParticipant) => void;\n participantLeft: (participant: RemoteParticipant) => void;\n trackPublished: (kind: TrackKind, participant: RemoteParticipant) => void;\n trackUnpublished: (kind: TrackKind, participant: RemoteParticipant) => void;\n trackSubscribed: (track: RemoteTrack, participant: RemoteParticipant) => void;\n trackUnsubscribed: (track: RemoteTrack, participant: RemoteParticipant) => void;\n /** Phase 11 addition. A remote participant muted or unmuted a track they'd already published. */\n trackMuted: (kind: TrackKind, participant: RemoteParticipant) => void;\n trackUnmuted: (kind: TrackKind, participant: RemoteParticipant) => void;\n localTrackPublished: (track: LocalTrack) => void;\n localTrackUnpublished: (track: LocalTrack) => void;\n dataReceived: (payload: Uint8Array, participant?: RemoteParticipant) => void;\n error: (error: RTCError) => void;\n}\n\n/**\n * A joined room. You get one from `client.join(roomId)`; don't build it\n * yourself. It owns participant and track state plus every room-scoped\n * action. No SDP, ICE candidates or RTCPeerConnection leak out here.\n */\nexport class Room extends TypedEventEmitter<RoomEventMap> {\n readonly roomId: string;\n /** Stable for the whole life of this connection. This is the id to quote in a bug report (Phase 9 spec §8). */\n readonly connectionId: string;\n readonly localParticipant: LocalParticipant;\n private readonly adapter: SFUAdapter;\n private readonly logger: Logger;\n private readonly telemetry: TelemetryClient;\n private reconnectCount = 0;\n private statsTimer?: ReturnType<typeof setInterval>;\n\n /**\n * How often the stats monitor samples and reports. Often enough that a\n * dashboard showing \"now\" isn't showing you five minutes ago, rarely\n * enough that it doesn't hammer the telemetry endpoint on a call where\n * dozens of participants are all doing exactly this.\n */\n private static readonly STATS_INTERVAL_MS = 5_000;\n\n /** @internal Use `client.join(roomId)`. The telemetry client defaults to a no-op, so tests and advanced setups can build a Room directly without wiring one up. */\n constructor(\n adapter: SFUAdapter,\n roomId: string,\n logger: Logger,\n telemetry: TelemetryClient = createTelemetryClient({ enabled: false, token: '', sdkVersion: SDK_VERSION, logger }),\n ) {\n super();\n this.adapter = adapter;\n this.roomId = roomId;\n this.logger = logger;\n this.telemetry = telemetry;\n this.connectionId = telemetry.connectionId;\n this.localParticipant = adapter.localParticipant;\n this.wireAdapterEvents();\n }\n\n get remoteParticipants(): RemoteParticipant[] {\n return Array.from(this.adapter.remoteParticipants.values());\n }\n\n get connectionState(): ConnectionState {\n return this.adapter.connectionState;\n }\n\n private wireAdapterEvents(): void {\n let prevState: ConnectionState = this.adapter.connectionState;\n\n this.adapter.on('connectionStateChanged', (state) => {\n this.emit('connectionStateChanged', state);\n\n if (state === 'connected') {\n if (prevState === 'reconnecting') {\n this.reconnectCount++;\n this.telemetry.send('reconnected');\n this.emit('reconnected');\n } else {\n this.telemetry.send('connected');\n this.emit('connected');\n }\n this.startStatsMonitor();\n } else if (state === 'reconnecting' && prevState !== 'reconnecting') {\n this.telemetry.send('reconnecting');\n this.emit('reconnecting');\n } else if (state === 'disconnected' || state === 'failed') {\n this.stopStatsMonitor();\n this.telemetry.send(state === 'failed' ? 'connection_failed' : 'disconnected');\n this.emit('disconnected');\n if (state === 'failed') {\n const error = new RTCError('CONNECTION_FAILED', 'Connection failed after exhausting reconnect attempts');\n this.telemetry.send('error', { code: error.code, message: error.message });\n this.emit('error', error);\n }\n }\n\n prevState = state;\n });\n\n this.adapter.on('participantJoined', (participant) => {\n this.telemetry.send('participant_joined', { participantIdentity: participant.identity });\n this.emit('participantJoined', participant);\n });\n this.adapter.on('participantLeft', (participant) => {\n this.telemetry.send('participant_left', { participantIdentity: participant.identity });\n this.emit('participantLeft', participant);\n });\n this.adapter.on('trackPublished', (kind, participant) => this.emit('trackPublished', kind, participant));\n this.adapter.on('trackUnpublished', (kind, participant) => this.emit('trackUnpublished', kind, participant));\n this.adapter.on('trackSubscribed', (track, participant) => this.emit('trackSubscribed', track, participant));\n this.adapter.on('trackUnsubscribed', (track, participant) => this.emit('trackUnsubscribed', track, participant));\n this.adapter.on('trackMuted', (kind, participant) => this.emit('trackMuted', kind, participant));\n this.adapter.on('trackUnmuted', (kind, participant) => this.emit('trackUnmuted', kind, participant));\n this.adapter.on('localTrackPublished', (track) => {\n this.telemetry.send('track_published', { kind: track.kind });\n this.emit('localTrackPublished', track);\n });\n this.adapter.on('localTrackUnpublished', (track) => {\n this.telemetry.send('track_unpublished', { kind: track.kind });\n this.emit('localTrackUnpublished', track);\n });\n this.adapter.on('dataReceived', (payload, participant) => this.emit('dataReceived', payload, participant));\n this.adapter.on('mediaError', (error) => {\n this.logger.warn('media device error', error.message);\n const rtcError = new RTCError('MEDIA_ERROR', error.message, error);\n this.telemetry.send('error', { code: rtcError.code, message: rtcError.message });\n this.emit('error', rtcError);\n });\n }\n\n /**\n * A non-secret diagnostic snapshot for support and debugging.\n *\n * Synchronous and cheap by design, so you can call it from anywhere at\n * any time, error handlers included. Live media stats are a separate\n * `async` call; see `getConnectionStats()`.\n */\n getDiagnostics(): ConnectionDiagnostics {\n const { platform, browser } = detectPlatform();\n const remote = this.adapter.getRemoteConnectionState?.() ?? {};\n return {\n connectionState: this.connectionState,\n iceConnectionState: this.adapter.getIceConnectionState?.(),\n signalingState: this.adapter.getSignalingState?.(),\n remoteIceConnectionState: remote.iceState,\n remotePeerConnectionState: remote.peerState,\n reconnectCount: this.reconnectCount,\n sdkVersion: SDK_VERSION,\n platform,\n browser,\n };\n }\n\n /**\n * Live media-quality stats for every published and subscribed track.\n * RTT, jitter, packet loss, bitrate, codec, resolution/fps, and the\n * SFU's own connection-quality read. `ConnectionStats` explains why this\n * is kept apart from `getDiagnostics()`.\n *\n * Call it whenever you like, including before anything is published or\n * subscribed. You just get empty `local`/`remote` arrays then, not an\n * error.\n */\n async getConnectionStats(): Promise<ConnectionStats> {\n const localTracks = this.localParticipant.tracks;\n const remoteTracks = this.remoteParticipants.flatMap((participant) => participant.tracks);\n\n const [local, remote] = await Promise.all([\n Promise.all(localTracks.map((track) => track.getStats())),\n Promise.all(remoteTracks.map((track) => track.getStats())),\n ]);\n\n return {\n connectionState: this.connectionState,\n connectionQuality: this.adapter.getConnectionQuality(),\n local: local.filter((stats): stats is TrackStats => stats !== undefined),\n remote: remote.filter((stats): stats is TrackStats => stats !== undefined),\n };\n }\n\n /**\n * Polls `getConnectionStats()` on a timer and ships the result as\n * telemetry, so the dashboard's RTC view (spec §23) has numbers to show\n * without every developer wiring it up by hand. Best-effort, same as\n * every other telemetry event here: failures get swallowed. A hiccup\n * collecting stats is no reason to disturb the call it's describing.\n */\n private startStatsMonitor(): void {\n if (this.statsTimer) {\n return;\n }\n this.statsTimer = setInterval(() => {\n this.getConnectionStats()\n .then((stats) => this.telemetry.send('stats', stats as unknown as Record<string, unknown>))\n .catch(() => {\n // Silent on purpose. See the method doc.\n });\n }, Room.STATS_INTERVAL_MS);\n }\n\n private stopStatsMonitor(): void {\n if (this.statsTimer) {\n clearInterval(this.statsTimer);\n this.statsTimer = undefined;\n }\n }\n\n /** Captures and publishes the camera in one go. Resolves to the published track. */\n async enableCamera(): Promise<LocalTrack | undefined> {\n return this.adapter.enableCamera(true);\n }\n\n /** Stops publishing and releases the camera. */\n async disableCamera(): Promise<void> {\n await this.adapter.enableCamera(false);\n }\n\n /** Captures and publishes the microphone in one call. Resolves to the published track. */\n async enableMicrophone(): Promise<LocalTrack | undefined> {\n return this.adapter.enableMicrophone(true);\n }\n\n /** Stops publishing and releases the microphone. */\n async disableMicrophone(): Promise<void> {\n await this.adapter.enableMicrophone(false);\n }\n\n /** Captures and publishes a screen share in one call. */\n async enableScreenShare(): Promise<LocalTrack | undefined> {\n return this.adapter.enableScreenShare(true);\n }\n\n async disableScreenShare(): Promise<void> {\n await this.adapter.enableScreenShare(false);\n }\n\n /** Publishes a track you made with `client.createCameraTrack()` and friends. */\n async publish(track: LocalTrack): Promise<void> {\n await this.adapter.publish(track);\n }\n\n async unpublish(track: LocalTrack): Promise<void> {\n await this.adapter.unpublish(track);\n }\n\n /** Switches the active camera without republishing. */\n async setCameraDevice(deviceId: string): Promise<void> {\n await this.adapter.setDevice('videoinput', deviceId);\n }\n\n /** Switches the active microphone without republishing. */\n async setMicrophoneDevice(deviceId: string): Promise<void> {\n await this.adapter.setDevice('audioinput', deviceId);\n }\n\n /**\n * Switches the audio output (\"speaker\") device for this room's remote\n * audio elements. Phase 11 addition. Not supported everywhere: Safari\n * has no `HTMLMediaElement.setSinkId`. Browsers that don't implement it\n * get a `DEVICE_NOT_FOUND` throw instead of a silent no-op.\n */\n async setSpeakerDevice(deviceId: string): Promise<void> {\n if (typeof document !== 'undefined') {\n const probe = document.createElement('audio') as HTMLAudioElement & { setSinkId?: unknown };\n if (typeof probe.setSinkId !== 'function') {\n throw new RTCError('DEVICE_NOT_FOUND', \"This browser doesn't support selecting an audio output device (no setSinkId)\");\n }\n }\n await this.adapter.setDevice('audiooutput', deviceId);\n }\n\n /**\n * Sends a small payload to everyone, or to specific people if the\n * underlying SFU adapter supports targeting. Requires the token's\n * `publishData` grant; throws PERMISSION_DENIED without it.\n */\n async sendData(payload: string | Uint8Array): Promise<void> {\n // Rewrap as a plain ArrayBuffer-backed Uint8Array, so callers never\n // have to think about ArrayBuffer vs SharedArrayBuffer generics.\n const bytes = typeof payload === 'string' ? new TextEncoder().encode(payload) : new Uint8Array(payload);\n await this.adapter.sendData(bytes);\n }\n\n /**\n * Resolves once the media connection is genuinely up.\n *\n * # Why this exists\n *\n * `client.join()` resolves when the **control plane** lets you in: room\n * joined, you know who else is here, you can publish. The media\n * connection finishes a moment later, once ICE and DTLS are done, which\n * means `connectionState` sits at `'connecting'` for a short window\n * after `join()` returns. That's the honest shape of an SFU connection,\n * and it's why `'connected'` is an event, not something joining\n * guarantees you.\n *\n * Most callers need none of this. `enableCamera()` and\n * `enableMicrophone()` work fine inside that window, and the `connected`\n * event is what you want driving a UI. This is for code that genuinely\n * has to block: a test, or a flow that mustn't move on until media is\n * live.\n *\n * Resolves straight away if already connected. Rejects on `'failed'` and\n * on timeout, rather than handing back a connection that isn't there.\n *\n * Careful: a subscriber joining a room where nobody is publishing can\n * quite legitimately stay `'connecting'`. With no tracks on either side\n * there's nothing to negotiate, so waiting here times out on a\n * connection that isn't broken at all. Where you can, drive the UI off\n * the `connected` event instead of blocking on this.\n */\n waitUntilConnected(timeoutMs = 15_000): Promise<void> {\n if (this.connectionState === 'connected') {\n return Promise.resolve();\n }\n\n return new Promise<void>((resolve, reject) => {\n const settle = (fn: () => void) => {\n clearTimeout(timer);\n this.off('connectionStateChanged', onState);\n fn();\n };\n\n const onState = (state: ConnectionState) => {\n if (state === 'connected') {\n settle(resolve);\n } else if (state === 'failed') {\n settle(() => reject(new RTCError('CONNECTION_FAILED', 'The connection failed while waiting for it')));\n }\n };\n\n const timer = setTimeout(() => {\n settle(() =>\n reject(\n new RTCError(\n 'CONNECTION_FAILED',\n `Still ${this.connectionState} after ${timeoutMs}ms; the media connection did not establish`,\n ),\n ),\n );\n }, timeoutMs);\n\n this.on('connectionStateChanged', onState);\n });\n }\n\n /** Leaves the room, stops local tracks and closes the underlying connection. */\n async leave(): Promise<void> {\n this.stopStatsMonitor();\n await this.adapter.disconnect();\n }\n}\n","import { assertTokenMatchesRoom, validateConfig, type ResolvedRTCClientConfig, type RTCClientConfig } from './config';\nimport { RTCError } from './errors';\nimport { createLogger, type Logger } from './logger';\nimport { listDevices } from './internal/devices/enumerate';\nimport {\n createCameraTrack,\n createMicrophoneTrack,\n createScreenShareTrack,\n} from './internal/media/capture';\nimport { RavenAdapter } from './internal/sfu/raven-adapter';\nimport type { DeviceInfo, DeviceKind, SFUAdapter } from './internal/sfu/types';\nimport { createTelemetryClient } from './internal/telemetry/telemetry-client';\nimport { Room, type ConnectionDiagnostics } from './room';\nimport { LocalTrack } from './track';\nimport { SDK_VERSION } from './version';\n\ntype AdapterFactory = (logger: Logger, autoReconnect: boolean) => SFUAdapter;\n\nconst defaultAdapterFactory: AdapterFactory = (logger, autoReconnect) => new RavenAdapter(logger, autoReconnect);\n\n/**\n * The SDK's entry point. Holds your RTC token and endpoint and gets you\n * into a room. Everything per-room lives on the `Room` it hands back.\n */\nexport class RTCClient {\n private readonly config: ResolvedRTCClientConfig;\n private readonly logger: Logger;\n private readonly adapterFactory: AdapterFactory;\n private currentRoom?: Room;\n\n /**\n * @internal Use `createRTCClient(config)`. The second param exists purely\n * so tests can inject a fake SFUAdapter without a real browser and WebRTC\n * stack. Not part of the public config.\n */\n constructor(config: ResolvedRTCClientConfig, adapterFactory: AdapterFactory = defaultAdapterFactory) {\n this.config = config;\n this.logger = createLogger(config.logLevel);\n this.adapterFactory = adapterFactory;\n }\n\n /**\n * Joins the room this client's token was minted for. `roomId` has to\n * match that room; pass a different one and you get `ROOM_NOT_FOUND`\n * straight away, before any connection is attempted.\n */\n async join(roomId: string): Promise<Room> {\n assertTokenMatchesRoom(this.config.token, roomId);\n this.logger.info('joining room', roomId);\n\n const telemetry = createTelemetryClient({\n enabled: this.config.telemetry,\n telemetryUrl: this.config.telemetryUrl,\n token: this.config.token,\n sdkVersion: SDK_VERSION,\n logger: this.logger,\n });\n telemetry.send('connection_started');\n\n const adapter = this.adapterFactory(this.logger, this.config.autoReconnect);\n const room = new Room(adapter, roomId, this.logger, telemetry);\n\n try {\n await adapter.connect(this.config.endpoint, this.config.token, this.config.iceServers);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const code = error instanceof RTCError ? error.code : 'CONNECTION_FAILED';\n telemetry.send('error', { code, message });\n telemetry.send('connection_failed');\n throw error;\n }\n\n this.currentRoom = room;\n return room;\n }\n\n /** Leaves the most recently joined room, if there is one. Same as `.leave()` on that `Room`. */\n async leave(): Promise<void> {\n await this.currentRoom?.leave();\n this.currentRoom = undefined;\n }\n\n /** Captures a camera track without joining or publishing. Pair it with `room.publish(track)`. */\n async createCameraTrack(deviceId?: string): Promise<LocalTrack> {\n return createCameraTrack(deviceId ? { deviceId } : {});\n }\n\n /** Captures a microphone track without joining or publishing. Pair it with `room.publish(track)`. */\n async createMicrophoneTrack(deviceId?: string): Promise<LocalTrack> {\n return createMicrophoneTrack(deviceId ? { deviceId } : {});\n }\n\n /** Captures a screen-share track without joining or publishing. Pair it with `room.publish(track)`. */\n async createScreenShareTrack(): Promise<LocalTrack> {\n return createScreenShareTrack();\n }\n\n /** Lists available devices. Labels only fill in once permission has been granted at least once. */\n async getDevices(kind?: DeviceKind): Promise<DeviceInfo[]> {\n return listDevices(kind);\n }\n\n /**\n * Subscribes to devices coming and going (Phase 11 addition), like a USB\n * webcam being plugged in or yanked out. Returns an unsubscribe function.\n *\n * In an environment with no `navigator.mediaDevices` this is a no-op with\n * an immediately-callable unsubscribe, rather than a throw. It's an\n * optional convenience, not a capability anything depends on.\n */\n onDeviceChange(callback: () => void): () => void {\n if (typeof navigator === 'undefined' || !navigator.mediaDevices) {\n return () => {};\n }\n navigator.mediaDevices.addEventListener('devicechange', callback);\n return () => navigator.mediaDevices.removeEventListener('devicechange', callback);\n }\n\n /** Switches the active camera on the currently joined room. */\n async setCamera(deviceId: string): Promise<void> {\n if (!this.currentRoom) {\n throw new RTCError('CONNECTION_FAILED', 'setCamera() requires an active room; call join() first');\n }\n await this.currentRoom.setCameraDevice(deviceId);\n }\n\n /** Switches the active microphone on the currently joined room. */\n async setMicrophone(deviceId: string): Promise<void> {\n if (!this.currentRoom) {\n throw new RTCError('CONNECTION_FAILED', 'setMicrophone() requires an active room; call join() first');\n }\n await this.currentRoom.setMicrophoneDevice(deviceId);\n }\n\n /** Diagnostic snapshot of the currently joined room. See `Room.getDiagnostics()`. */\n getDiagnostics(): ConnectionDiagnostics {\n if (!this.currentRoom) {\n throw new RTCError('CONNECTION_FAILED', 'getDiagnostics() requires an active room; call join() first');\n }\n return this.currentRoom.getDiagnostics();\n }\n}\n\n/**\n * Creates an RTC client from a token your backend minted. `token` and\n * `endpoint` come straight out of that same mint response. Don't build\n * them by hand, and never mint a token in the browser.\n */\nexport function createRTCClient(config: RTCClientConfig): RTCClient {\n const resolved = validateConfig(config);\n return new RTCClient(resolved);\n}\n","/**\n * Phase 11 addition. Feature-detects what the SDK actually needs, instead\n * of keeping a user-agent allowlist that goes stale the moment you write\n * it. See docs/sdk/web.md#browser-support for the documented matrix.\n */\nexport interface BrowserSupportDetails {\n supported: boolean;\n missing: string[];\n}\n\nexport function getBrowserSupportDetails(): BrowserSupportDetails {\n const missing: string[] = [];\n\n if (typeof RTCPeerConnection === 'undefined') missing.push('RTCPeerConnection');\n if (typeof navigator === 'undefined' || !navigator.mediaDevices?.getUserMedia) missing.push('navigator.mediaDevices.getUserMedia');\n if (typeof WebSocket === 'undefined') missing.push('WebSocket');\n\n return { supported: missing.length === 0, missing };\n}\n\n/** A simple yes/no wrapper over `getBrowserSupportDetails()`. */\nexport function isBrowserSupported(): boolean {\n return getBrowserSupportDetails().supported;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"inputs":{"src/errors.ts":{"bytes":1322,"imports":[],"format":"esm"},"src/config.ts":{"bytes":5301,"imports":[{"path":"src/errors.ts","kind":"import-statement","original":"./errors"}],"format":"esm"},"src/logger.ts":{"bytes":1043,"imports":[],"format":"esm"},"src/internal/devices/enumerate.ts":{"bytes":1060,"imports":[{"path":"src/errors.ts","kind":"import-statement","original":"../../errors"}],"format":"esm"},"src/internal/telemetry/track-stats.ts":{"bytes":5356,"imports":[],"format":"esm"},"src/track.ts":{"bytes":8014,"imports":[{"path":"src/internal/telemetry/track-stats.ts","kind":"import-statement","original":"./internal/telemetry/track-stats"},{"path":"src/errors.ts","kind":"import-statement","original":"./errors"}],"format":"esm"},"src/internal/media/errors.ts":{"bytes":3035,"imports":[{"path":"src/errors.ts","kind":"import-statement","original":"../../errors"}],"format":"esm"},"src/internal/telemetry/rtc-stats.ts":{"bytes":6313,"imports":[],"format":"esm"},"src/internal/media/native-track.ts":{"bytes":7387,"imports":[{"path":"src/internal/telemetry/rtc-stats.ts","kind":"import-statement","original":"../telemetry/rtc-stats"}],"format":"esm"},"src/internal/media/capture.ts":{"bytes":5838,"imports":[{"path":"src/errors.ts","kind":"import-statement","original":"../../errors"},{"path":"src/track.ts","kind":"import-statement","original":"../../track"},{"path":"src/internal/media/errors.ts","kind":"import-statement","original":"./errors"},{"path":"src/internal/media/native-track.ts","kind":"import-statement","original":"./native-track"}],"format":"esm"},"src/events.ts":{"bytes":1570,"imports":[],"format":"esm"},"src/participant.ts":{"bytes":1181,"imports":[],"format":"esm"},"src/internal/signaling/protocol.ts":{"bytes":4987,"imports":[],"format":"esm"},"src/internal/signaling/signaling-client.ts":{"bytes":13927,"imports":[{"path":"src/errors.ts","kind":"import-statement","original":"../../errors"},{"path":"src/events.ts","kind":"import-statement","original":"../../events"},{"path":"src/internal/signaling/protocol.ts","kind":"import-statement","original":"./protocol"}],"format":"esm"},"src/internal/sfu/raven-adapter.ts":{"bytes":42732,"imports":[{"path":"src/errors.ts","kind":"import-statement","original":"../../errors"},{"path":"src/events.ts","kind":"import-statement","original":"../../events"},{"path":"src/participant.ts","kind":"import-statement","original":"../../participant"},{"path":"src/track.ts","kind":"import-statement","original":"../../track"},{"path":"src/internal/media/capture.ts","kind":"import-statement","original":"../media/capture"},{"path":"src/internal/media/native-track.ts","kind":"import-statement","original":"../media/native-track"},{"path":"src/internal/devices/enumerate.ts","kind":"import-statement","original":"../devices/enumerate"},{"path":"src/internal/telemetry/rtc-stats.ts","kind":"import-statement","original":"../telemetry/rtc-stats"},{"path":"src/internal/signaling/protocol.ts","kind":"import-statement","original":"../signaling/protocol"},{"path":"src/internal/signaling/signaling-client.ts","kind":"import-statement","original":"../signaling/signaling-client"}],"format":"esm"},"src/internal/telemetry/connection-id.ts":{"bytes":724,"imports":[],"format":"esm"},"src/internal/telemetry/platform.ts":{"bytes":1153,"imports":[],"format":"esm"},"src/internal/telemetry/telemetry-client.ts":{"bytes":3005,"imports":[{"path":"src/internal/telemetry/connection-id.ts","kind":"import-statement","original":"./connection-id"},{"path":"src/internal/telemetry/platform.ts","kind":"import-statement","original":"./platform"}],"format":"esm"},"src/version.ts":{"bytes":141,"imports":[],"format":"esm"},"src/room.ts":{"bytes":16952,"imports":[{"path":"src/errors.ts","kind":"import-statement","original":"./errors"},{"path":"src/events.ts","kind":"import-statement","original":"./events"},{"path":"src/internal/telemetry/telemetry-client.ts","kind":"import-statement","original":"./internal/telemetry/telemetry-client"},{"path":"src/internal/telemetry/platform.ts","kind":"import-statement","original":"./internal/telemetry/platform"},{"path":"./participant","kind":"import-statement","external":true},{"path":"./track","kind":"import-statement","external":true},{"path":"src/version.ts","kind":"import-statement","original":"./version"}],"format":"esm"},"src/client.ts":{"bytes":6084,"imports":[{"path":"src/config.ts","kind":"import-statement","original":"./config"},{"path":"src/errors.ts","kind":"import-statement","original":"./errors"},{"path":"src/logger.ts","kind":"import-statement","original":"./logger"},{"path":"src/internal/devices/enumerate.ts","kind":"import-statement","original":"./internal/devices/enumerate"},{"path":"src/internal/media/capture.ts","kind":"import-statement","original":"./internal/media/capture"},{"path":"src/internal/sfu/raven-adapter.ts","kind":"import-statement","original":"./internal/sfu/raven-adapter"},{"path":"src/internal/telemetry/telemetry-client.ts","kind":"import-statement","original":"./internal/telemetry/telemetry-client"},{"path":"src/room.ts","kind":"import-statement","original":"./room"},{"path":"./track","kind":"import-statement","external":true},{"path":"src/version.ts","kind":"import-statement","original":"./version"}],"format":"esm"},"src/browser-support.ts":{"bytes":921,"imports":[],"format":"esm"},"src/index.ts":{"bytes":1275,"imports":[{"path":"src/client.ts","kind":"import-statement","original":"./client"},{"path":"src/room.ts","kind":"import-statement","original":"./room"},{"path":"src/participant.ts","kind":"import-statement","original":"./participant"},{"path":"src/track.ts","kind":"import-statement","original":"./track"},{"path":"src/errors.ts","kind":"import-statement","original":"./errors"},{"path":"src/browser-support.ts","kind":"import-statement","original":"./browser-support"}],"format":"esm"}},"outputs":{"dist/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":188921},"dist/index.cjs":{"imports":[],"exports":["LocalParticipant","LocalTrack","Participant","RTCClient","RTCError","RemoteParticipant","RemoteTrack","Room","Track","createRTCClient","getBrowserSupportDetails","isBrowserSupported","isRTCError"],"entryPoint":"src/index.ts","inputs":{"src/errors.ts":{"bytesInOutput":243},"src/config.ts":{"bytesInOutput":2104},"src/logger.ts":{"bytesInOutput":602},"src/internal/devices/enumerate.ts":{"bytesInOutput":512},"src/internal/telemetry/track-stats.ts":{"bytesInOutput":1728},"src/track.ts":{"bytesInOutput":4570},"src/internal/media/errors.ts":{"bytesInOutput":1480},"src/internal/telemetry/rtc-stats.ts":{"bytesInOutput":3232},"src/internal/media/native-track.ts":{"bytesInOutput":4842},"src/internal/media/capture.ts":{"bytesInOutput":2837},"src/events.ts":{"bytesInOutput":891},"src/participant.ts":{"bytesInOutput":936},"src/internal/signaling/protocol.ts":{"bytesInOutput":1273},"src/internal/signaling/signaling-client.ts":{"bytesInOutput":7903},"src/internal/sfu/raven-adapter.ts":{"bytesInOutput":29731},"src/internal/telemetry/connection-id.ts":{"bytesInOutput":312},"src/internal/telemetry/platform.ts":{"bytesInOutput":734},"src/internal/telemetry/telemetry-client.ts":{"bytesInOutput":1233},"src/version.ts":{"bytesInOutput":27},"src/room.ts":{"bytesInOutput":11788},"src/client.ts":{"bytesInOutput":4377},"src/index.ts":{"bytesInOutput":0},"src/browser-support.ts":{"bytesInOutput":482}},"bytes":82729}}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"inputs":{"src/errors.ts":{"bytes":1322,"imports":[],"format":"esm"},"src/config.ts":{"bytes":5301,"imports":[{"path":"src/errors.ts","kind":"import-statement","original":"./errors"}],"format":"esm"},"src/logger.ts":{"bytes":1043,"imports":[],"format":"esm"},"src/internal/devices/enumerate.ts":{"bytes":1060,"imports":[{"path":"src/errors.ts","kind":"import-statement","original":"../../errors"}],"format":"esm"},"src/internal/telemetry/track-stats.ts":{"bytes":5356,"imports":[],"format":"esm"},"src/track.ts":{"bytes":8014,"imports":[{"path":"src/internal/telemetry/track-stats.ts","kind":"import-statement","original":"./internal/telemetry/track-stats"},{"path":"src/errors.ts","kind":"import-statement","original":"./errors"}],"format":"esm"},"src/internal/media/errors.ts":{"bytes":3035,"imports":[{"path":"src/errors.ts","kind":"import-statement","original":"../../errors"}],"format":"esm"},"src/internal/telemetry/rtc-stats.ts":{"bytes":6313,"imports":[],"format":"esm"},"src/internal/media/native-track.ts":{"bytes":7387,"imports":[{"path":"src/internal/telemetry/rtc-stats.ts","kind":"import-statement","original":"../telemetry/rtc-stats"}],"format":"esm"},"src/internal/media/capture.ts":{"bytes":5838,"imports":[{"path":"src/errors.ts","kind":"import-statement","original":"../../errors"},{"path":"src/track.ts","kind":"import-statement","original":"../../track"},{"path":"src/internal/media/errors.ts","kind":"import-statement","original":"./errors"},{"path":"src/internal/media/native-track.ts","kind":"import-statement","original":"./native-track"}],"format":"esm"},"src/events.ts":{"bytes":1570,"imports":[],"format":"esm"},"src/participant.ts":{"bytes":1181,"imports":[],"format":"esm"},"src/internal/signaling/protocol.ts":{"bytes":4987,"imports":[],"format":"esm"},"src/internal/signaling/signaling-client.ts":{"bytes":13927,"imports":[{"path":"src/errors.ts","kind":"import-statement","original":"../../errors"},{"path":"src/events.ts","kind":"import-statement","original":"../../events"},{"path":"src/internal/signaling/protocol.ts","kind":"import-statement","original":"./protocol"}],"format":"esm"},"src/internal/sfu/raven-adapter.ts":{"bytes":42732,"imports":[{"path":"src/errors.ts","kind":"import-statement","original":"../../errors"},{"path":"src/events.ts","kind":"import-statement","original":"../../events"},{"path":"src/participant.ts","kind":"import-statement","original":"../../participant"},{"path":"src/track.ts","kind":"import-statement","original":"../../track"},{"path":"src/internal/media/capture.ts","kind":"import-statement","original":"../media/capture"},{"path":"src/internal/media/native-track.ts","kind":"import-statement","original":"../media/native-track"},{"path":"src/internal/devices/enumerate.ts","kind":"import-statement","original":"../devices/enumerate"},{"path":"src/internal/telemetry/rtc-stats.ts","kind":"import-statement","original":"../telemetry/rtc-stats"},{"path":"src/internal/signaling/protocol.ts","kind":"import-statement","original":"../signaling/protocol"},{"path":"src/internal/signaling/signaling-client.ts","kind":"import-statement","original":"../signaling/signaling-client"}],"format":"esm"},"src/internal/telemetry/connection-id.ts":{"bytes":724,"imports":[],"format":"esm"},"src/internal/telemetry/platform.ts":{"bytes":1153,"imports":[],"format":"esm"},"src/internal/telemetry/telemetry-client.ts":{"bytes":3005,"imports":[{"path":"src/internal/telemetry/connection-id.ts","kind":"import-statement","original":"./connection-id"},{"path":"src/internal/telemetry/platform.ts","kind":"import-statement","original":"./platform"}],"format":"esm"},"src/version.ts":{"bytes":141,"imports":[],"format":"esm"},"src/room.ts":{"bytes":16952,"imports":[{"path":"src/errors.ts","kind":"import-statement","original":"./errors"},{"path":"src/events.ts","kind":"import-statement","original":"./events"},{"path":"src/internal/telemetry/telemetry-client.ts","kind":"import-statement","original":"./internal/telemetry/telemetry-client"},{"path":"src/internal/telemetry/platform.ts","kind":"import-statement","original":"./internal/telemetry/platform"},{"path":"./participant","kind":"import-statement","external":true},{"path":"./track","kind":"import-statement","external":true},{"path":"src/version.ts","kind":"import-statement","original":"./version"}],"format":"esm"},"src/client.ts":{"bytes":6084,"imports":[{"path":"src/config.ts","kind":"import-statement","original":"./config"},{"path":"src/errors.ts","kind":"import-statement","original":"./errors"},{"path":"src/logger.ts","kind":"import-statement","original":"./logger"},{"path":"src/internal/devices/enumerate.ts","kind":"import-statement","original":"./internal/devices/enumerate"},{"path":"src/internal/media/capture.ts","kind":"import-statement","original":"./internal/media/capture"},{"path":"src/internal/sfu/raven-adapter.ts","kind":"import-statement","original":"./internal/sfu/raven-adapter"},{"path":"src/internal/telemetry/telemetry-client.ts","kind":"import-statement","original":"./internal/telemetry/telemetry-client"},{"path":"src/room.ts","kind":"import-statement","original":"./room"},{"path":"./track","kind":"import-statement","external":true},{"path":"src/version.ts","kind":"import-statement","original":"./version"}],"format":"esm"},"src/browser-support.ts":{"bytes":921,"imports":[],"format":"esm"},"src/index.ts":{"bytes":1275,"imports":[{"path":"src/client.ts","kind":"import-statement","original":"./client"},{"path":"src/room.ts","kind":"import-statement","original":"./room"},{"path":"src/participant.ts","kind":"import-statement","original":"./participant"},{"path":"src/track.ts","kind":"import-statement","original":"./track"},{"path":"src/errors.ts","kind":"import-statement","original":"./errors"},{"path":"src/browser-support.ts","kind":"import-statement","original":"./browser-support"}],"format":"esm"}},"outputs":{"dist/index.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":188921},"dist/index.js":{"imports":[],"exports":["LocalParticipant","LocalTrack","Participant","RTCClient","RTCError","RemoteParticipant","RemoteTrack","Room","Track","createRTCClient","getBrowserSupportDetails","isBrowserSupported","isRTCError"],"entryPoint":"src/index.ts","inputs":{"src/errors.ts":{"bytesInOutput":243},"src/config.ts":{"bytesInOutput":2104},"src/logger.ts":{"bytesInOutput":602},"src/internal/devices/enumerate.ts":{"bytesInOutput":512},"src/internal/telemetry/track-stats.ts":{"bytesInOutput":1728},"src/track.ts":{"bytesInOutput":4570},"src/internal/media/errors.ts":{"bytesInOutput":1480},"src/internal/telemetry/rtc-stats.ts":{"bytesInOutput":3232},"src/internal/media/native-track.ts":{"bytesInOutput":4842},"src/internal/media/capture.ts":{"bytesInOutput":2837},"src/events.ts":{"bytesInOutput":891},"src/participant.ts":{"bytesInOutput":936},"src/internal/signaling/protocol.ts":{"bytesInOutput":1273},"src/internal/signaling/signaling-client.ts":{"bytesInOutput":7903},"src/internal/sfu/raven-adapter.ts":{"bytesInOutput":29731},"src/internal/telemetry/connection-id.ts":{"bytesInOutput":312},"src/internal/telemetry/platform.ts":{"bytesInOutput":734},"src/internal/telemetry/telemetry-client.ts":{"bytesInOutput":1233},"src/version.ts":{"bytesInOutput":27},"src/room.ts":{"bytesInOutput":11788},"src/client.ts":{"bytesInOutput":4377},"src/index.ts":{"bytesInOutput":0},"src/browser-support.ts":{"bytesInOutput":482}},"bytes":82729}}}
|