@livekit/rtc-node 0.13.32 → 0.13.34

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.
Files changed (141) hide show
  1. package/dist/async_queue.d.ts +2 -3
  2. package/dist/audio_filter.d.ts +2 -3
  3. package/dist/audio_frame.d.ts +5 -6
  4. package/dist/audio_mixer.d.ts +3 -6
  5. package/dist/audio_resampler.d.ts +3 -6
  6. package/dist/audio_source.d.ts +5 -6
  7. package/dist/{audio_stream-4M8XlO4-.d.cts → audio_stream-BNVaONuH.d.cts} +36 -10
  8. package/dist/audio_stream.d.cts +2 -2
  9. package/dist/audio_stream.d.ts +61 -18
  10. package/dist/data_streams/index.d.cts +1 -1
  11. package/dist/data_streams/index.d.ts +4 -3
  12. package/dist/data_streams/stream_reader.cjs +97 -58
  13. package/dist/data_streams/stream_reader.cjs.map +1 -1
  14. package/dist/data_streams/stream_reader.d.cts +1 -1
  15. package/dist/data_streams/stream_reader.d.ts +65 -2
  16. package/dist/data_streams/stream_reader.d.ts.map +1 -1
  17. package/dist/data_streams/stream_writer.d.cts +1 -1
  18. package/dist/data_streams/stream_writer.d.ts +5 -7
  19. package/dist/data_streams/types.cjs.map +1 -1
  20. package/dist/data_streams/types.d.cts +1 -1
  21. package/dist/data_streams/types.d.ts +47 -2
  22. package/dist/data_streams/types.d.ts.map +1 -1
  23. package/dist/e2ee.cjs +5 -1
  24. package/dist/e2ee.cjs.map +1 -1
  25. package/dist/e2ee.d.cts +3 -1
  26. package/dist/e2ee.d.ts +11 -11
  27. package/dist/e2ee.d.ts.map +1 -1
  28. package/dist/ffi_client.d.ts +8 -10
  29. package/dist/frame_processor.d.ts +8 -11
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.cts +2 -2
  32. package/dist/index.d.ts +22 -17
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +1 -107
  35. package/dist/log.d.ts +5 -7
  36. package/dist/participant.cjs +179 -192
  37. package/dist/participant.cjs.map +1 -1
  38. package/dist/participant.d.cts +2 -2
  39. package/dist/participant.d.ts +169 -18
  40. package/dist/participant.d.ts.map +1 -1
  41. package/dist/room.cjs +166 -120
  42. package/dist/room.cjs.map +1 -1
  43. package/dist/room.d.cts +2 -2
  44. package/dist/room.d.ts +228 -18
  45. package/dist/room.d.ts.map +1 -1
  46. package/dist/rpc.d.ts +7 -9
  47. package/dist/tests/e2e_common.cjs +157 -0
  48. package/dist/tests/e2e_common.cjs.map +1 -0
  49. package/dist/tests/e2e_common.d.cts +56 -0
  50. package/dist/tests/e2e_common.d.ts +37 -0
  51. package/dist/tests/e2e_common.d.ts.map +1 -0
  52. package/dist/track.d.cts +2 -2
  53. package/dist/track.d.ts +67 -18
  54. package/dist/track_publication.d.cts +2 -2
  55. package/dist/track_publication.d.ts +45 -18
  56. package/dist/transcription.d.ts +3 -4
  57. package/dist/{types-_PdPVish.d.ts → types-f7wTlFjs.d.cts} +34 -11
  58. package/dist/types.d.ts +2 -3
  59. package/dist/utils.cjs +27 -2
  60. package/dist/utils.cjs.map +1 -1
  61. package/dist/utils.d.cts +8 -1
  62. package/dist/utils.d.ts +10 -5
  63. package/dist/utils.d.ts.map +1 -1
  64. package/dist/version.cjs +1 -1
  65. package/dist/version.cjs.map +1 -1
  66. package/dist/version.d.cts +1 -1
  67. package/dist/version.d.ts +2 -3
  68. package/dist/video_frame.d.ts +4 -5
  69. package/dist/video_source.d.ts +6 -8
  70. package/dist/video_stream.d.cts +2 -2
  71. package/dist/video_stream.d.ts +5 -22
  72. package/package.json +6 -7
  73. package/src/audio_stream_room_lifecycle.test.ts +4 -1
  74. package/src/data_streams/stream_reader.ts +132 -82
  75. package/src/data_streams/types.ts +6 -0
  76. package/src/e2ee.ts +7 -0
  77. package/src/index.ts +8 -1
  78. package/src/participant.ts +252 -223
  79. package/src/room.ts +233 -134
  80. package/src/tests/e2e.test.ts +50 -139
  81. package/src/tests/e2e_common.ts +163 -0
  82. package/src/tests/e2e_data_streams.test.ts +639 -0
  83. package/src/utils.ts +30 -0
  84. package/src/version.ts +1 -1
  85. package/dist/async_queue.js +0 -56
  86. package/dist/async_queue.js.map +0 -1
  87. package/dist/audio_filter.js +0 -24
  88. package/dist/audio_filter.js.map +0 -1
  89. package/dist/audio_frame.js +0 -78
  90. package/dist/audio_frame.js.map +0 -1
  91. package/dist/audio_mixer.js +0 -269
  92. package/dist/audio_mixer.js.map +0 -1
  93. package/dist/audio_resampler.js +0 -154
  94. package/dist/audio_resampler.js.map +0 -1
  95. package/dist/audio_source.js +0 -134
  96. package/dist/audio_source.js.map +0 -1
  97. package/dist/audio_stream-CTyN1Ldy.d.ts +0 -523
  98. package/dist/audio_stream.js +0 -122
  99. package/dist/audio_stream.js.map +0 -1
  100. package/dist/data_streams/index.js +0 -3
  101. package/dist/data_streams/index.js.map +0 -1
  102. package/dist/data_streams/stream_reader.js +0 -124
  103. package/dist/data_streams/stream_reader.js.map +0 -1
  104. package/dist/data_streams/stream_writer.js +0 -26
  105. package/dist/data_streams/stream_writer.js.map +0 -1
  106. package/dist/data_streams/types.js +0 -1
  107. package/dist/data_streams/types.js.map +0 -1
  108. package/dist/e2ee.js +0 -251
  109. package/dist/e2ee.js.map +0 -1
  110. package/dist/ffi_client.js +0 -89
  111. package/dist/ffi_client.js.map +0 -1
  112. package/dist/frame_processor.js +0 -29
  113. package/dist/frame_processor.js.map +0 -1
  114. package/dist/index.js.map +0 -1
  115. package/dist/log.js +0 -9
  116. package/dist/log.js.map +0 -1
  117. package/dist/participant.js +0 -715
  118. package/dist/participant.js.map +0 -1
  119. package/dist/room.js +0 -900
  120. package/dist/room.js.map +0 -1
  121. package/dist/rpc.js +0 -65
  122. package/dist/rpc.js.map +0 -1
  123. package/dist/track.js +0 -234
  124. package/dist/track.js.map +0 -1
  125. package/dist/track_publication.js +0 -100
  126. package/dist/track_publication.js.map +0 -1
  127. package/dist/transcription.js +0 -1
  128. package/dist/transcription.js.map +0 -1
  129. package/dist/types-_PdPVish.d.cts +0 -87
  130. package/dist/types.js +0 -1
  131. package/dist/types.js.map +0 -1
  132. package/dist/utils.js +0 -35
  133. package/dist/utils.js.map +0 -1
  134. package/dist/version.js +0 -5
  135. package/dist/version.js.map +0 -1
  136. package/dist/video_frame.js +0 -207
  137. package/dist/video_frame.js.map +0 -1
  138. package/dist/video_source.js +0 -53
  139. package/dist/video_source.js.map +0 -1
  140. package/dist/video_stream.js +0 -70
  141. package/dist/video_stream.js.map +0 -1
@@ -9,7 +9,7 @@
9
9
  * This eliminates the need for manual coordination logic, polling loops, and
10
10
  * complex state management throughout the rest of the codebase.
11
11
  */
12
- declare class AsyncQueue<T> {
12
+ export declare class AsyncQueue<T> {
13
13
  private capacity;
14
14
  private items;
15
15
  private waitingProducers;
@@ -26,5 +26,4 @@ declare class AsyncQueue<T> {
26
26
  close(): void;
27
27
  get length(): number;
28
28
  }
29
-
30
- export { AsyncQueue };
29
+ //# sourceMappingURL=async_queue.d.ts.map
@@ -1,5 +1,4 @@
1
- declare class AudioFilter {
1
+ export declare class AudioFilter {
2
2
  constructor(moduleId: string, path: string, dependencies?: string[]);
3
3
  }
4
-
5
- export { AudioFilter };
4
+ //# sourceMappingURL=audio_filter.d.ts.map
@@ -1,6 +1,6 @@
1
- import { OwnedAudioFrameBuffer, AudioFrameBufferInfo } from '@livekit/rtc-ffi-bindings';
2
-
3
- declare class AudioFrame {
1
+ import type { OwnedAudioFrameBuffer } from '@livekit/rtc-ffi-bindings';
2
+ import { AudioFrameBufferInfo } from '@livekit/rtc-ffi-bindings';
3
+ export declare class AudioFrame {
4
4
  data: Int16Array;
5
5
  sampleRate: number;
6
6
  channels: number;
@@ -24,6 +24,5 @@ declare class AudioFrame {
24
24
  *
25
25
  * @param buffer - a single AudioFrame or list thereof
26
26
  */
27
- declare const combineAudioFrames: (buffer: AudioFrame | AudioFrame[]) => AudioFrame;
28
-
29
- export { AudioFrame, combineAudioFrames };
27
+ export declare const combineAudioFrames: (buffer: AudioFrame | AudioFrame[]) => AudioFrame;
28
+ //# sourceMappingURL=audio_frame.d.ts.map
@@ -1,13 +1,11 @@
1
1
  import { AudioFrame } from './audio_frame.js';
2
2
  export { AsyncQueue } from './async_queue.js';
3
- import '@livekit/rtc-ffi-bindings';
4
-
5
3
  type AudioStream = {
6
4
  [Symbol.asyncIterator](): {
7
5
  next(): Promise<IteratorResult<AudioFrame>>;
8
6
  };
9
7
  };
10
- interface AudioMixerOptions {
8
+ export interface AudioMixerOptions {
11
9
  /**
12
10
  * The size of the audio block (in samples) for mixing.
13
11
  * If not provided, defaults to sampleRate / 10 (100ms).
@@ -47,7 +45,7 @@ interface AudioMixerOptions {
47
45
  * }
48
46
  * ```
49
47
  */
50
- declare class AudioMixer {
48
+ export declare class AudioMixer {
51
49
  private streams;
52
50
  private buffers;
53
51
  private streamIterators;
@@ -114,5 +112,4 @@ declare class AudioMixer {
114
112
  * cleared via `.finally()` so callers don't need to manage cleanup. */
115
113
  private timeoutRace;
116
114
  }
117
-
118
- export { AudioMixer, type AudioMixerOptions };
115
+ //# sourceMappingURL=audio_mixer.d.ts.map
@@ -1,11 +1,9 @@
1
1
  import { AudioFrame } from './audio_frame.js';
2
- import '@livekit/rtc-ffi-bindings';
3
-
4
2
  /**
5
3
  * Resampler quality. Higher quality settings result in better audio quality but require more
6
4
  * processing power.
7
5
  */
8
- declare enum AudioResamplerQuality {
6
+ export declare enum AudioResamplerQuality {
9
7
  QUICK = 0,
10
8
  LOW = 1,
11
9
  MEDIUM = 2,
@@ -17,7 +15,7 @@ declare enum AudioResamplerQuality {
17
15
  * an output sample rate using the Sox resampling library. It supports multiple channels and
18
16
  * configurable resampling quality.
19
17
  */
20
- declare class AudioResampler {
18
+ export declare class AudioResampler {
21
19
  #private;
22
20
  /**
23
21
  * Initializes a new AudioResampler.
@@ -58,5 +56,4 @@ declare class AudioResampler {
58
56
  */
59
57
  flush(): AudioFrame[];
60
58
  }
61
-
62
- export { AudioResampler, AudioResamplerQuality };
59
+ //# sourceMappingURL=audio_resampler.d.ts.map
@@ -1,7 +1,7 @@
1
- import { AudioSourceInfo, FfiHandle } from '@livekit/rtc-ffi-bindings';
2
- import { AudioFrame } from './audio_frame.js';
3
-
4
- declare class AudioSource {
1
+ import type { AudioSourceInfo } from '@livekit/rtc-ffi-bindings';
2
+ import { FfiHandle } from '@livekit/rtc-ffi-bindings';
3
+ import type { AudioFrame } from './audio_frame.js';
4
+ export declare class AudioSource {
5
5
  /** @internal */
6
6
  info: AudioSourceInfo;
7
7
  /** @internal */
@@ -37,5 +37,4 @@ declare class AudioSource {
37
37
  captureFrame(frame: AudioFrame): Promise<void>;
38
38
  close(): Promise<void>;
39
39
  }
40
-
41
- export { AudioSource };
40
+ //# sourceMappingURL=audio_source.d.ts.map
@@ -6,7 +6,7 @@ import { FfiHandle, TrackPublicationInfo, OwnedTrackPublication, TrackKind, Trac
6
6
  import { AudioSource } from './audio_source.cjs';
7
7
  import './ffi_client.cjs';
8
8
  import { TypedEventEmitter } from '@livekit/typed-emitter';
9
- import { B as BaseStreamInfo, c as ByteStreamOptions, T as TextStreamHandler, a as ByteStreamHandler } from './types-_PdPVish.cjs';
9
+ import { B as BaseStreamInfo, c as ByteStreamOptions, T as TextStreamHandler, a as ByteStreamHandler } from './types-f7wTlFjs.cjs';
10
10
  import { E2EEManager, E2EEOptions } from './e2ee.cjs';
11
11
  import { Mutex } from '@livekit/mutex';
12
12
  import { PathLike } from 'node:fs';
@@ -92,6 +92,7 @@ declare class LocalParticipant extends Participant {
92
92
  private rpcHandlers;
93
93
  private ffiEventLock;
94
94
  private disconnectSignal;
95
+ private openStreamWriters;
95
96
  trackPublications: Map<string, LocalTrackPublication>;
96
97
  constructor(info: OwnedParticipant, ffiEventLock: Mutex, disconnectSignal: AbortSignal);
97
98
  publishData(data: Uint8Array, options: DataPublishOptions): Promise<void>;
@@ -114,6 +115,12 @@ declare class LocalParticipant extends Participant {
114
115
  attributes?: Record<string, string>;
115
116
  destinationIdentities?: Array<string>;
116
117
  streamId?: string;
118
+ /**
119
+ * Whether the payload may be compressed on the wire. Defaults to true;
120
+ * compression is only applied when it actually reduces the payload size
121
+ * and every recipient supports it.
122
+ */
123
+ compress?: boolean;
117
124
  }): Promise<BaseStreamInfo>;
118
125
  streamBytes(options?: {
119
126
  name?: string;
@@ -126,9 +133,20 @@ declare class LocalParticipant extends Participant {
126
133
  }): Promise<ByteStreamWriter>;
127
134
  /** Sends a file provided as PathLike to specified recipients */
128
135
  sendFile(path: PathLike, options?: ByteStreamOptions): Promise<void>;
129
- private sendStreamHeader;
130
- private sendStreamChunk;
131
- private sendStreamTrailer;
136
+ private textStreamWriterWrite;
137
+ private textStreamWriterClose;
138
+ private byteStreamWriterWrite;
139
+ private byteStreamWriterClose;
140
+ /**
141
+ * Drops the native writers of any data streams that were opened but never
142
+ * closed — a writer the caller abandoned, or one whose write failed. Their
143
+ * handles would otherwise be held by the FFI server for the lifetime of the
144
+ * process. The room is already gone at this point, so the handles are dropped
145
+ * directly rather than closed: there is no end-of-stream left to deliver.
146
+ *
147
+ * @internal
148
+ */
149
+ disposeOpenStreamWriters(): void;
132
150
  /**
133
151
  * Sends a chat message to participants in the room
134
152
  *
@@ -202,6 +220,14 @@ interface RtcConfiguration {
202
220
  iceServers: IceServer[];
203
221
  }
204
222
  declare const defaultRtcConfiguration: RtcConfiguration;
223
+ interface RoomDataStreamOptions {
224
+ /**
225
+ * Maximum decompressed payload size in bytes accepted for a single incoming
226
+ * data stream. Incoming streams exceeding this limit terminate with an error
227
+ * on the receiving side. Unset falls back to the SDK default of 5gb.
228
+ */
229
+ maxPayloadByteLength?: number;
230
+ }
205
231
  interface RoomOptions {
206
232
  autoSubscribe: boolean;
207
233
  dynacast: boolean;
@@ -211,6 +237,8 @@ interface RoomOptions {
211
237
  e2ee?: E2EEOptions;
212
238
  encryption?: E2EEOptions;
213
239
  rtcConfig?: RtcConfiguration;
240
+ /** Options controlling data stream behavior for this room. */
241
+ dataStream?: RoomDataStreamOptions;
214
242
  }
215
243
  declare const defaultRoomOptions: RoomOptions$1;
216
244
  declare const Room_base: new () => TypedEventEmitter<RoomCallbacks>;
@@ -223,8 +251,7 @@ declare class Room extends Room_base {
223
251
  * before processing the next events
224
252
  */
225
253
  private ffiEventLock;
226
- private byteStreamControllers;
227
- private textStreamControllers;
254
+ private streamReaders;
228
255
  private byteStreamHandlers;
229
256
  private textStreamHandlers;
230
257
  private preConnectEvents;
@@ -316,9 +343,8 @@ declare class Room extends Room_base {
316
343
  private requirePublicationOfParticipant;
317
344
  private requirePublicationOfRemoteParticipant;
318
345
  private createRemoteParticipant;
319
- private handleStreamHeader;
320
- private handleStreamChunk;
321
- private handleStreamTrailer;
346
+ private handleByteStreamOpened;
347
+ private handleTextStreamOpened;
322
348
  }
323
349
  declare class ConnectError extends Error {
324
350
  constructor(message: string);
@@ -520,4 +546,4 @@ declare class AudioStream extends ReadableStream<AudioFrame> {
520
546
  constructor(track: Track, options: AudioStreamOptions);
521
547
  }
522
548
 
523
- export { AudioStream as A, ConnectError as C, type DataPublishOptions as D, LocalAudioTrack as L, type NoiseCancellationOptions as N, Participant as P, RemoteAudioTrack as R, Track as T, type VideoTrack as V, type AudioTrack as a, LocalParticipant as b, type LocalTrack as c, LocalTrackPublication as d, LocalVideoTrack as e, RemoteParticipant as f, type RemoteTrack as g, RemoteTrackPublication as h, RemoteVideoTrack as i, Room as j, RoomEvent as k, type RoomOptions as l, type RtcConfiguration as m, TrackPublication as n, type RoomCallbacks as o, defaultRoomOptions as p, defaultRtcConfiguration as q, type AudioStreamOptions as r, AudioStreamSource as s };
549
+ export { AudioStream as A, ConnectError as C, type DataPublishOptions as D, LocalAudioTrack as L, type NoiseCancellationOptions as N, Participant as P, RemoteAudioTrack as R, Track as T, type VideoTrack as V, type AudioTrack as a, LocalParticipant as b, type LocalTrack as c, LocalTrackPublication as d, LocalVideoTrack as e, RemoteParticipant as f, type RemoteTrack as g, RemoteTrackPublication as h, RemoteVideoTrack as i, Room as j, type RoomDataStreamOptions as k, RoomEvent as l, type RoomOptions as m, type RtcConfiguration as n, TrackPublication as o, type RoomCallbacks as p, defaultRoomOptions as q, defaultRtcConfiguration as r, type AudioStreamOptions as s, AudioStreamSource as t };
@@ -1,13 +1,13 @@
1
1
  import 'node:stream/web';
2
2
  import './audio_frame.cjs';
3
3
  import './frame_processor.cjs';
4
- export { A as AudioStream, r as AudioStreamOptions, s as AudioStreamSource, N as NoiseCancellationOptions } from './audio_stream-4M8XlO4-.cjs';
4
+ export { A as AudioStream, s as AudioStreamOptions, t as AudioStreamSource, N as NoiseCancellationOptions } from './audio_stream-BNVaONuH.cjs';
5
5
  import '@livekit/rtc-ffi-bindings';
6
6
  import './video_frame.cjs';
7
7
  import './audio_source.cjs';
8
8
  import './ffi_client.cjs';
9
9
  import '@livekit/typed-emitter';
10
- import './types-_PdPVish.cjs';
10
+ import './types-f7wTlFjs.cjs';
11
11
  import './e2ee.cjs';
12
12
  import '@livekit/mutex';
13
13
  import 'node:fs';
@@ -1,18 +1,61 @@
1
- import 'node:stream/web';
2
- import './audio_frame.js';
3
- import './frame_processor.js';
4
- export { A as AudioStream, r as AudioStreamOptions, s as AudioStreamSource, N as NoiseCancellationOptions } from './audio_stream-CTyN1Ldy.js';
5
- import '@livekit/rtc-ffi-bindings';
6
- import './video_frame.js';
7
- import './audio_source.js';
8
- import './ffi_client.js';
9
- import '@livekit/typed-emitter';
10
- import './types-_PdPVish.js';
11
- import './e2ee.js';
12
- import '@livekit/mutex';
13
- import 'node:fs';
14
- import './data_streams/stream_writer.js';
15
- import './rpc.js';
16
- import './transcription.js';
17
- import './types.js';
18
- import './video_source.js';
1
+ import type { UnderlyingSource } from 'node:stream/web';
2
+ import { AudioFrame } from './audio_frame.js';
3
+ import { type FrameProcessor } from './frame_processor.js';
4
+ import type { Track } from './track.js';
5
+ export interface AudioStreamOptions {
6
+ noiseCancellation?: NoiseCancellationOptions | FrameProcessor<AudioFrame>;
7
+ /**
8
+ * When the audio stream closes, whether to run the {@link FrameProcessor}'s
9
+ * `close()` method. If `false`, the processor is left open so it can be
10
+ * reused with another {@link AudioStream}. Only relevant when
11
+ * `noiseCancellation` is a {@link FrameProcessor}. Defaults to `true`.
12
+ */
13
+ autoCloseNoiseCancellation?: boolean;
14
+ sampleRate?: number;
15
+ numChannels?: number;
16
+ frameSizeMs?: number;
17
+ }
18
+ export interface NoiseCancellationOptions {
19
+ moduleId: string;
20
+ options: Record<string, any>;
21
+ }
22
+ /** @internal */
23
+ export declare class AudioStreamSource implements UnderlyingSource<AudioFrame> {
24
+ private controller?;
25
+ private ffiHandle;
26
+ private disposed;
27
+ private sampleRate;
28
+ private numChannels;
29
+ private legacyNcOptions?;
30
+ private frameProcessor;
31
+ private autoCloseProcessor;
32
+ private frameSizeMs?;
33
+ private track;
34
+ constructor(track: Track, sampleRateOrOptions?: number | AudioStreamOptions, numChannels?: number);
35
+ /** @internal */
36
+ get processor(): FrameProcessor<AudioFrame> | null;
37
+ private onEvent;
38
+ start(controller: ReadableStreamDefaultController<AudioFrame>): void;
39
+ /**
40
+ * Detach from the FFI and release resources: on `eos`, on `cancel()`, or
41
+ * because the track went away (e.g. it was unsubscribed — which never
42
+ * produces an `eos`, so without this the stream would keep delivering
43
+ * frames). Already-buffered frames stay readable and the consumer sees `done`
44
+ * after draining them.
45
+ *
46
+ * @remarks
47
+ * Idempotent, so `eos` arriving after a `cancel()` (or vice versa) doesn't
48
+ * double-dispose the handle while buffered frames are still queued.
49
+ *
50
+ * @internal
51
+ */
52
+ teardown(): void;
53
+ cancel(): void;
54
+ }
55
+ export declare class AudioStream extends ReadableStream<AudioFrame> {
56
+ constructor(track: Track);
57
+ constructor(track: Track, sampleRate: number);
58
+ constructor(track: Track, sampleRate: number, numChannels: number);
59
+ constructor(track: Track, options: AudioStreamOptions);
60
+ }
61
+ //# sourceMappingURL=audio_stream.d.ts.map
@@ -1,3 +1,3 @@
1
- export { B as BaseStreamInfo, a as ByteStreamHandler, b as ByteStreamInfo, c as ByteStreamOptions, d as ByteStreamReader, D as DataStreamOptions, S as StreamController, T as TextStreamHandler, e as TextStreamInfo, f as TextStreamOptions, g as TextStreamReader } from '../types-_PdPVish.cjs';
1
+ export { B as BaseStreamInfo, a as ByteStreamHandler, b as ByteStreamInfo, c as ByteStreamOptions, d as ByteStreamReader, D as DataStreamOptions, S as StreamController, T as TextStreamHandler, e as TextStreamInfo, f as TextStreamOptions, g as TextStreamReader } from '../types-f7wTlFjs.cjs';
2
2
  export { ByteStreamWriter, TextStreamWriter } from './stream_writer.cjs';
3
3
  import '@livekit/rtc-ffi-bindings';
@@ -1,3 +1,4 @@
1
- export { B as BaseStreamInfo, a as ByteStreamHandler, b as ByteStreamInfo, c as ByteStreamOptions, d as ByteStreamReader, D as DataStreamOptions, S as StreamController, T as TextStreamHandler, e as TextStreamInfo, f as TextStreamOptions, g as TextStreamReader } from '../types-_PdPVish.js';
2
- export { ByteStreamWriter, TextStreamWriter } from './stream_writer.js';
3
- import '@livekit/rtc-ffi-bindings';
1
+ export * from './stream_reader.js';
2
+ export * from './stream_writer.js';
3
+ export type * from './types.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -23,46 +23,105 @@ __export(stream_reader_exports, {
23
23
  });
24
24
  module.exports = __toCommonJS(stream_reader_exports);
25
25
  var import_log = require("../log.cjs");
26
- var import_utils = require("../utils.cjs");
27
26
  class BaseStreamReader {
28
- get info() {
29
- return this._info;
30
- }
31
27
  constructor(info, stream, totalByteSize) {
28
+ this.closed = false;
29
+ // The reader held by an in-progress iteration. Cancelling has to go through
30
+ // it, since it holds the stream's lock.
31
+ this.activeReader = null;
32
32
  this.reader = stream;
33
33
  this.totalByteSize = totalByteSize;
34
34
  this._info = info;
35
35
  this.bytesReceived = 0;
36
36
  }
37
- }
38
- class ByteStreamReader extends BaseStreamReader {
37
+ get info() {
38
+ return this._info;
39
+ }
39
40
  handleChunkReceived(chunk) {
40
41
  var _a;
41
42
  this.bytesReceived += chunk.content.byteLength;
42
43
  const currentProgress = this.totalByteSize ? this.bytesReceived / this.totalByteSize : void 0;
43
44
  (_a = this.onProgress) == null ? void 0 : _a.call(this, currentProgress);
44
45
  }
45
- [Symbol.asyncIterator]() {
46
+ /** Takes the stream's reader for an iteration, remembering it so that
47
+ * close() can cancel a read that is still in flight. */
48
+ acquireReader() {
46
49
  const reader = this.reader.getReader();
50
+ this.activeReader = reader;
51
+ return reader;
52
+ }
53
+ /** Releases the stream lock after an iteration ended on its own — because a
54
+ * read reported end-of-stream, or because the stream itself errored. Either
55
+ * way the stream is in a terminal state and the FFI subscription behind it
56
+ * was already dropped by that terminal event, so there is nothing to cancel.
57
+ *
58
+ * An error raised *around* a read rather than by it — a chunk that failed to
59
+ * process — leaves the stream live, so it has to go through close() instead. */
60
+ finishIteration(reader) {
61
+ this.closed = true;
62
+ if (this.activeReader === reader) {
63
+ this.activeReader = null;
64
+ }
65
+ reader.releaseLock();
66
+ }
67
+ /**
68
+ * Stops receiving this stream and releases the resources behind it.
69
+ *
70
+ * A reader is subscribed to FFI events from the moment it is handed to a
71
+ * stream handler, and only unsubscribes once a read consumes the stream's
72
+ * end-of-stream event. So a reader that is abandoned part-way through, or
73
+ * that a handler never reads at all, has to be closed here or its
74
+ * subscription lives for the rest of the process. Reading to completion — or
75
+ * breaking out of a `for await` — closes the reader for you, and closing an
76
+ * already-closed reader is a no-op.
77
+ */
78
+ async close() {
79
+ if (this.closed) {
80
+ return;
81
+ }
82
+ this.closed = true;
83
+ const active = this.activeReader;
84
+ this.activeReader = null;
85
+ try {
86
+ if (active) {
87
+ await active.cancel();
88
+ active.releaseLock();
89
+ } else {
90
+ await this.reader.cancel();
91
+ }
92
+ } catch (error) {
93
+ import_log.log.debug("error closing stream reader: %s", error);
94
+ }
95
+ }
96
+ }
97
+ class ByteStreamReader extends BaseStreamReader {
98
+ [Symbol.asyncIterator]() {
99
+ const reader = this.acquireReader();
47
100
  return {
48
101
  next: async () => {
102
+ let read;
49
103
  try {
50
- const { done, value } = await reader.read();
51
- if (done) {
52
- reader.releaseLock();
53
- return { done: true, value: void 0 };
54
- } else {
55
- this.handleChunkReceived(value);
56
- return { done: false, value: value.content };
57
- }
104
+ read = await reader.read();
58
105
  } catch (error) {
59
- reader.releaseLock();
60
- import_log.log.error("error processing stream update: %s", error);
106
+ this.finishIteration(reader);
107
+ import_log.log.error("error reading stream: %s", error);
108
+ throw error;
109
+ }
110
+ if (read.done) {
111
+ this.finishIteration(reader);
61
112
  return { done: true, value: void 0 };
62
113
  }
114
+ try {
115
+ this.handleChunkReceived(read.value);
116
+ return { done: false, value: read.value.content };
117
+ } catch (error) {
118
+ await this.close();
119
+ import_log.log.error("error processing stream update: %s", error);
120
+ throw error;
121
+ }
63
122
  },
64
- return() {
65
- reader.releaseLock();
123
+ return: async () => {
124
+ await this.close();
66
125
  return { done: true, value: void 0 };
67
126
  }
68
127
  };
@@ -76,59 +135,39 @@ class ByteStreamReader extends BaseStreamReader {
76
135
  }
77
136
  }
78
137
  class TextStreamReader extends BaseStreamReader {
79
- /**
80
- * A TextStreamReader instance can be used as an AsyncIterator that returns the entire string
81
- * that has been received up to the current point in time.
82
- */
83
- constructor(info, stream, totalChunkCount) {
84
- super(info, stream, totalChunkCount);
85
- this.receivedChunks = /* @__PURE__ */ new Map();
86
- }
87
- handleChunkReceived(chunk) {
88
- var _a;
89
- const index = (0, import_utils.bigIntToNumber)(chunk.chunkIndex);
90
- const previousChunkAtIndex = this.receivedChunks.get(index);
91
- if (previousChunkAtIndex && previousChunkAtIndex.version > chunk.version) {
92
- return;
93
- }
94
- this.receivedChunks.set(index, chunk);
95
- const currentProgress = this.totalByteSize ? this.receivedChunks.size / this.totalByteSize : void 0;
96
- (_a = this.onProgress) == null ? void 0 : _a.call(this, currentProgress);
97
- }
98
138
  /**
99
139
  * Async iterator implementation to allow usage of `for await...of` syntax.
100
140
  * Yields structured chunks from the stream.
101
141
  *
102
142
  */
103
143
  [Symbol.asyncIterator]() {
104
- const reader = this.reader.getReader();
144
+ const reader = this.acquireReader();
105
145
  const decoder = new TextDecoder();
106
- const receivedChunks = this.receivedChunks;
107
146
  return {
108
147
  next: async () => {
148
+ let read;
109
149
  try {
110
- const { done, value } = await reader.read();
111
- if (done) {
112
- reader.releaseLock();
113
- receivedChunks.clear();
114
- return { done: true, value: void 0 };
115
- } else {
116
- this.handleChunkReceived(value);
117
- return {
118
- done: false,
119
- value: decoder.decode(value.content)
120
- };
121
- }
150
+ read = await reader.read();
122
151
  } catch (error) {
123
- reader.releaseLock();
124
- receivedChunks.clear();
125
- import_log.log.error("error processing stream update: %s", error);
152
+ this.finishIteration(reader);
153
+ import_log.log.error("error reading stream: %s", error);
154
+ throw error;
155
+ }
156
+ if (read.done) {
157
+ this.finishIteration(reader);
126
158
  return { done: true, value: void 0 };
127
159
  }
160
+ try {
161
+ this.handleChunkReceived(read.value);
162
+ return { done: false, value: decoder.decode(read.value.content) };
163
+ } catch (error) {
164
+ await this.close();
165
+ import_log.log.error("error processing stream update: %s", error);
166
+ throw error;
167
+ }
128
168
  },
129
- return() {
130
- reader.releaseLock();
131
- receivedChunks.clear();
169
+ return: async () => {
170
+ await this.close();
132
171
  return { done: true, value: void 0 };
133
172
  }
134
173
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/data_streams/stream_reader.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { DataStream_Chunk } from '@livekit/rtc-ffi-bindings';\nimport { log } from '../log.js';\nimport { bigIntToNumber } from '../utils.js';\nimport type { BaseStreamInfo, ByteStreamInfo, TextStreamInfo } from './types.js';\n\nabstract class BaseStreamReader<T extends BaseStreamInfo> {\n protected reader: ReadableStream<DataStream_Chunk>;\n\n protected totalByteSize?: number;\n\n protected _info: T;\n\n protected bytesReceived: number;\n\n get info() {\n return this._info;\n }\n\n constructor(info: T, stream: ReadableStream<DataStream_Chunk>, totalByteSize?: number) {\n this.reader = stream;\n this.totalByteSize = totalByteSize;\n this._info = info;\n this.bytesReceived = 0;\n }\n\n protected abstract handleChunkReceived(chunk: DataStream_Chunk): void;\n\n onProgress?: (progress: number | undefined) => void;\n\n abstract readAll(): Promise<string | Array<Uint8Array>>;\n}\n\n/**\n * A class to read chunks from a ReadableStream and provide them in a structured format.\n */\nexport class ByteStreamReader extends BaseStreamReader<ByteStreamInfo> {\n protected handleChunkReceived(chunk: DataStream_Chunk) {\n this.bytesReceived += chunk.content!.byteLength;\n const currentProgress = this.totalByteSize\n ? this.bytesReceived / this.totalByteSize\n : undefined;\n this.onProgress?.(currentProgress);\n }\n\n [Symbol.asyncIterator]() {\n const reader = this.reader.getReader();\n\n return {\n next: async (): Promise<IteratorResult<Uint8Array>> => {\n try {\n const { done, value } = await reader.read();\n if (done) {\n // Release the lock when the stream is exhausted so the\n // underlying ReadableStream can be garbage-collected.\n reader.releaseLock();\n return { done: true, value: undefined as unknown };\n } else {\n this.handleChunkReceived(value);\n return { done: false, value: value.content! };\n }\n } catch (error: unknown) {\n // Release the lock on error so it doesn't stay held when the\n // consumer never calls return() (e.g. breaking out of for-await).\n reader.releaseLock();\n log.error('error processing stream update: %s', error);\n return { done: true, value: undefined as unknown };\n }\n },\n\n return(): IteratorResult<Uint8Array> {\n reader.releaseLock();\n return { done: true, value: undefined };\n },\n };\n }\n\n async readAll(): Promise<Array<Uint8Array>> {\n const chunks: Set<Uint8Array> = new Set();\n for await (const chunk of this) {\n chunks.add(chunk);\n }\n return Array.from(chunks);\n }\n}\n\n/**\n * A class to read chunks from a ReadableStream and provide them in a structured format.\n */\nexport class TextStreamReader extends BaseStreamReader<TextStreamInfo> {\n private receivedChunks: Map<number, DataStream_Chunk>;\n\n /**\n * A TextStreamReader instance can be used as an AsyncIterator that returns the entire string\n * that has been received up to the current point in time.\n */\n constructor(\n info: TextStreamInfo,\n stream: ReadableStream<DataStream_Chunk>,\n totalChunkCount?: number,\n ) {\n super(info, stream, totalChunkCount);\n this.receivedChunks = new Map();\n }\n\n protected handleChunkReceived(chunk: DataStream_Chunk) {\n const index = bigIntToNumber(chunk.chunkIndex!);\n const previousChunkAtIndex = this.receivedChunks.get(index!);\n if (previousChunkAtIndex && previousChunkAtIndex.version! > chunk.version!) {\n // we have a newer version already, dropping the old one\n return;\n }\n this.receivedChunks.set(index, chunk);\n const currentProgress = this.totalByteSize\n ? this.receivedChunks.size / this.totalByteSize\n : undefined;\n this.onProgress?.(currentProgress);\n }\n\n /**\n * Async iterator implementation to allow usage of `for await...of` syntax.\n * Yields structured chunks from the stream.\n *\n */\n [Symbol.asyncIterator]() {\n const reader = this.reader.getReader();\n const decoder = new TextDecoder();\n const receivedChunks = this.receivedChunks;\n\n return {\n next: async (): Promise<IteratorResult<string>> => {\n try {\n const { done, value } = await reader.read();\n if (done) {\n // Release the lock when the stream is exhausted so the\n // underlying ReadableStream can be garbage-collected.\n reader.releaseLock();\n // Clear received chunks so the buffered data can be GC'd.\n receivedChunks.clear();\n return { done: true, value: undefined };\n } else {\n this.handleChunkReceived(value);\n return {\n done: false,\n value: decoder.decode(value.content!),\n };\n }\n } catch (error: unknown) {\n // Release the lock on error so it doesn't stay held when the\n // consumer never calls return() (e.g. breaking out of for-await).\n reader.releaseLock();\n receivedChunks.clear();\n log.error('error processing stream update: %s', error);\n return { done: true, value: undefined };\n }\n },\n\n return(): IteratorResult<string> {\n reader.releaseLock();\n // Clear received chunks so the buffered data can be GC'd.\n receivedChunks.clear();\n return { done: true, value: undefined };\n },\n };\n }\n\n async readAll(): Promise<string> {\n let finalString: string = '';\n for await (const chunk of this) {\n finalString += chunk;\n }\n return finalString;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/data_streams/stream_reader.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { DataStream_Chunk } from '@livekit/rtc-ffi-bindings';\nimport { log } from '../log.js';\nimport type { BaseStreamInfo, ByteStreamInfo, TextStreamInfo } from './types.js';\n\nabstract class BaseStreamReader<T extends BaseStreamInfo> {\n protected reader: ReadableStream<DataStream_Chunk>;\n\n protected totalByteSize?: number;\n\n protected _info: T;\n\n protected bytesReceived: number;\n\n private closed = false;\n\n // The reader held by an in-progress iteration. Cancelling has to go through\n // it, since it holds the stream's lock.\n private activeReader: ReadableStreamDefaultReader<DataStream_Chunk> | null = null;\n\n get info() {\n return this._info;\n }\n\n constructor(info: T, stream: ReadableStream<DataStream_Chunk>, totalByteSize?: number) {\n this.reader = stream;\n this.totalByteSize = totalByteSize;\n this._info = info;\n this.bytesReceived = 0;\n }\n\n protected handleChunkReceived(chunk: DataStream_Chunk) {\n this.bytesReceived += chunk.content!.byteLength;\n const currentProgress = this.totalByteSize\n ? this.bytesReceived / this.totalByteSize\n : undefined;\n this.onProgress?.(currentProgress);\n }\n\n /** Takes the stream's reader for an iteration, remembering it so that\n * close() can cancel a read that is still in flight. */\n protected acquireReader(): ReadableStreamDefaultReader<DataStream_Chunk> {\n const reader = this.reader.getReader();\n this.activeReader = reader;\n return reader;\n }\n\n /** Releases the stream lock after an iteration ended on its own — because a\n * read reported end-of-stream, or because the stream itself errored. Either\n * way the stream is in a terminal state and the FFI subscription behind it\n * was already dropped by that terminal event, so there is nothing to cancel.\n *\n * An error raised *around* a read rather than by it — a chunk that failed to\n * process — leaves the stream live, so it has to go through close() instead. */\n protected finishIteration(reader: ReadableStreamDefaultReader<DataStream_Chunk>) {\n this.closed = true;\n if (this.activeReader === reader) {\n this.activeReader = null;\n }\n reader.releaseLock();\n }\n\n /**\n * Stops receiving this stream and releases the resources behind it.\n *\n * A reader is subscribed to FFI events from the moment it is handed to a\n * stream handler, and only unsubscribes once a read consumes the stream's\n * end-of-stream event. So a reader that is abandoned part-way through, or\n * that a handler never reads at all, has to be closed here or its\n * subscription lives for the rest of the process. Reading to completion — or\n * breaking out of a `for await` — closes the reader for you, and closing an\n * already-closed reader is a no-op.\n */\n async close(): Promise<void> {\n if (this.closed) {\n return;\n }\n this.closed = true;\n const active = this.activeReader;\n this.activeReader = null;\n try {\n if (active) {\n await active.cancel();\n active.releaseLock();\n } else {\n await this.reader.cancel();\n }\n } catch (error: unknown) {\n // The stream was already closed or errored (e.g. the room disconnected\n // mid-stream), in which case its subscription is already gone.\n log.debug('error closing stream reader: %s', error);\n }\n }\n\n onProgress?: (progress: number | undefined) => void;\n\n abstract readAll(): Promise<string | Array<Uint8Array>>;\n}\n\n/**\n * A class to read chunks from a ReadableStream and provide them in a structured format.\n */\nexport class ByteStreamReader extends BaseStreamReader<ByteStreamInfo> {\n [Symbol.asyncIterator]() {\n const reader = this.acquireReader();\n\n return {\n next: async (): Promise<IteratorResult<Uint8Array>> => {\n let read: Awaited<ReturnType<typeof reader.read>>;\n try {\n read = await reader.read();\n } catch (error: unknown) {\n // The stream errored, which is terminal: release the lock so it\n // doesn't stay held when the consumer never calls return() (a\n // rejecting next() doesn't trigger it).\n this.finishIteration(reader);\n log.error('error reading stream: %s', error);\n // Propagate abnormal termination (e.g. remote abort, payload over\n // the receiver's size limit) instead of presenting the truncated\n // payload as a clean EOF.\n throw error;\n }\n\n if (read.done) {\n // Release the lock when the stream is exhausted so the\n // underlying ReadableStream can be garbage-collected.\n this.finishIteration(reader);\n return { done: true, value: undefined as unknown };\n }\n\n try {\n this.handleChunkReceived(read.value);\n return { done: false, value: read.value.content! };\n } catch (error: unknown) {\n // The chunk arrived fine but handling it threw (e.g. a consumer's\n // onProgress callback). The stream is still live, so it has to be\n // cancelled to release its FFI subscription.\n await this.close();\n log.error('error processing stream update: %s', error);\n throw error;\n }\n },\n\n return: async (): Promise<IteratorResult<Uint8Array>> => {\n await this.close();\n return { done: true, value: undefined };\n },\n };\n }\n\n async readAll(): Promise<Array<Uint8Array>> {\n const chunks: Set<Uint8Array> = new Set();\n for await (const chunk of this) {\n chunks.add(chunk);\n }\n return Array.from(chunks);\n }\n}\n\n/**\n * A class to read chunks from a ReadableStream and provide them in a structured format.\n */\nexport class TextStreamReader extends BaseStreamReader<TextStreamInfo> {\n /**\n * Async iterator implementation to allow usage of `for await...of` syntax.\n * Yields structured chunks from the stream.\n *\n */\n [Symbol.asyncIterator]() {\n const reader = this.acquireReader();\n const decoder = new TextDecoder();\n\n return {\n next: async (): Promise<IteratorResult<string>> => {\n let read: Awaited<ReturnType<typeof reader.read>>;\n try {\n read = await reader.read();\n } catch (error: unknown) {\n // The stream errored, which is terminal: release the lock so it\n // doesn't stay held when the consumer never calls return() (a\n // rejecting next() doesn't trigger it).\n this.finishIteration(reader);\n log.error('error reading stream: %s', error);\n // Propagate abnormal termination (e.g. remote abort, payload over\n // the receiver's size limit) instead of presenting the truncated\n // payload as a clean EOF.\n throw error;\n }\n\n if (read.done) {\n // Release the lock when the stream is exhausted so the\n // underlying ReadableStream can be garbage-collected.\n this.finishIteration(reader);\n return { done: true, value: undefined };\n }\n\n try {\n this.handleChunkReceived(read.value);\n return { done: false, value: decoder.decode(read.value.content!) };\n } catch (error: unknown) {\n // The chunk arrived fine but handling it threw (e.g. a consumer's\n // onProgress callback). The stream is still live, so it has to be\n // cancelled to release its FFI subscription.\n await this.close();\n log.error('error processing stream update: %s', error);\n throw error;\n }\n },\n\n return: async (): Promise<IteratorResult<string>> => {\n await this.close();\n return { done: true, value: undefined };\n },\n };\n }\n\n async readAll(): Promise<string> {\n let finalString: string = '';\n for await (const chunk of this) {\n finalString += chunk;\n }\n return finalString;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,iBAAoB;AAGpB,MAAe,iBAA2C;AAAA,EAmBxD,YAAY,MAAS,QAA0C,eAAwB;AAVvF,SAAQ,SAAS;AAIjB;AAAA;AAAA,SAAQ,eAAqE;AAO3E,SAAK,SAAS;AACd,SAAK,gBAAgB;AACrB,SAAK,QAAQ;AACb,SAAK,gBAAgB;AAAA,EACvB;AAAA,EATA,IAAI,OAAO;AACT,WAAO,KAAK;AAAA,EACd;AAAA,EASU,oBAAoB,OAAyB;AAjCzD;AAkCI,SAAK,iBAAiB,MAAM,QAAS;AACrC,UAAM,kBAAkB,KAAK,gBACzB,KAAK,gBAAgB,KAAK,gBAC1B;AACJ,eAAK,eAAL,8BAAkB;AAAA,EACpB;AAAA;AAAA;AAAA,EAIU,gBAA+D;AACvE,UAAM,SAAS,KAAK,OAAO,UAAU;AACrC,SAAK,eAAe;AACpB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASU,gBAAgB,QAAuD;AAC/E,SAAK,SAAS;AACd,QAAI,KAAK,iBAAiB,QAAQ;AAChC,WAAK,eAAe;AAAA,IACtB;AACA,WAAO,YAAY;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,QAAuB;AAC3B,QAAI,KAAK,QAAQ;AACf;AAAA,IACF;AACA,SAAK,SAAS;AACd,UAAM,SAAS,KAAK;AACpB,SAAK,eAAe;AACpB,QAAI;AACF,UAAI,QAAQ;AACV,cAAM,OAAO,OAAO;AACpB,eAAO,YAAY;AAAA,MACrB,OAAO;AACL,cAAM,KAAK,OAAO,OAAO;AAAA,MAC3B;AAAA,IACF,SAAS,OAAgB;AAGvB,qBAAI,MAAM,mCAAmC,KAAK;AAAA,IACpD;AAAA,EACF;AAKF;AAKO,MAAM,yBAAyB,iBAAiC;AAAA,EACrE,CAAC,OAAO,aAAa,IAAI;AACvB,UAAM,SAAS,KAAK,cAAc;AAElC,WAAO;AAAA,MACL,MAAM,YAAiD;AACrD,YAAI;AACJ,YAAI;AACF,iBAAO,MAAM,OAAO,KAAK;AAAA,QAC3B,SAAS,OAAgB;AAIvB,eAAK,gBAAgB,MAAM;AAC3B,yBAAI,MAAM,4BAA4B,KAAK;AAI3C,gBAAM;AAAA,QACR;AAEA,YAAI,KAAK,MAAM;AAGb,eAAK,gBAAgB,MAAM;AAC3B,iBAAO,EAAE,MAAM,MAAM,OAAO,OAAqB;AAAA,QACnD;AAEA,YAAI;AACF,eAAK,oBAAoB,KAAK,KAAK;AACnC,iBAAO,EAAE,MAAM,OAAO,OAAO,KAAK,MAAM,QAAS;AAAA,QACnD,SAAS,OAAgB;AAIvB,gBAAM,KAAK,MAAM;AACjB,yBAAI,MAAM,sCAAsC,KAAK;AACrD,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,MAEA,QAAQ,YAAiD;AACvD,cAAM,KAAK,MAAM;AACjB,eAAO,EAAE,MAAM,MAAM,OAAO,OAAU;AAAA,MACxC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,UAAsC;AAC1C,UAAM,SAA0B,oBAAI,IAAI;AACxC,qBAAiB,SAAS,MAAM;AAC9B,aAAO,IAAI,KAAK;AAAA,IAClB;AACA,WAAO,MAAM,KAAK,MAAM;AAAA,EAC1B;AACF;AAKO,MAAM,yBAAyB,iBAAiC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMrE,CAAC,OAAO,aAAa,IAAI;AACvB,UAAM,SAAS,KAAK,cAAc;AAClC,UAAM,UAAU,IAAI,YAAY;AAEhC,WAAO;AAAA,MACL,MAAM,YAA6C;AACjD,YAAI;AACJ,YAAI;AACF,iBAAO,MAAM,OAAO,KAAK;AAAA,QAC3B,SAAS,OAAgB;AAIvB,eAAK,gBAAgB,MAAM;AAC3B,yBAAI,MAAM,4BAA4B,KAAK;AAI3C,gBAAM;AAAA,QACR;AAEA,YAAI,KAAK,MAAM;AAGb,eAAK,gBAAgB,MAAM;AAC3B,iBAAO,EAAE,MAAM,MAAM,OAAO,OAAU;AAAA,QACxC;AAEA,YAAI;AACF,eAAK,oBAAoB,KAAK,KAAK;AACnC,iBAAO,EAAE,MAAM,OAAO,OAAO,QAAQ,OAAO,KAAK,MAAM,OAAQ,EAAE;AAAA,QACnE,SAAS,OAAgB;AAIvB,gBAAM,KAAK,MAAM;AACjB,yBAAI,MAAM,sCAAsC,KAAK;AACrD,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,MAEA,QAAQ,YAA6C;AACnD,cAAM,KAAK,MAAM;AACjB,eAAO,EAAE,MAAM,MAAM,OAAO,OAAU;AAAA,MACxC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,UAA2B;AAC/B,QAAI,cAAsB;AAC1B,qBAAiB,SAAS,MAAM;AAC9B,qBAAe;AAAA,IACjB;AACA,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -1,2 +1,2 @@
1
1
  import '@livekit/rtc-ffi-bindings';
2
- export { d as ByteStreamReader, g as TextStreamReader } from '../types-_PdPVish.cjs';
2
+ export { d as ByteStreamReader, g as TextStreamReader } from '../types-f7wTlFjs.cjs';