@livekit/rtc-node 0.13.29 → 0.13.31

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 (77) hide show
  1. package/dist/audio_source.cjs +38 -19
  2. package/dist/audio_source.cjs.map +1 -1
  3. package/dist/audio_source.d.cts +12 -4
  4. package/dist/audio_source.d.ts +12 -4
  5. package/dist/audio_source.d.ts.map +1 -1
  6. package/dist/audio_source.js +38 -19
  7. package/dist/audio_source.js.map +1 -1
  8. package/dist/audio_stream-B4hGVcKz.d.cts +498 -0
  9. package/dist/audio_stream-DEG1JKge.d.ts +498 -0
  10. package/dist/audio_stream.cjs +21 -6
  11. package/dist/audio_stream.cjs.map +1 -1
  12. package/dist/audio_stream.d.cts +12 -22
  13. package/dist/audio_stream.d.ts +12 -22
  14. package/dist/audio_stream.d.ts.map +1 -1
  15. package/dist/audio_stream.js +19 -5
  16. package/dist/audio_stream.js.map +1 -1
  17. package/dist/data_streams/index.d.cts +1 -1
  18. package/dist/data_streams/index.d.ts +1 -1
  19. package/dist/data_streams/stream_reader.d.cts +1 -1
  20. package/dist/data_streams/stream_reader.d.ts +1 -1
  21. package/dist/data_streams/stream_writer.d.cts +1 -1
  22. package/dist/data_streams/stream_writer.d.ts +1 -1
  23. package/dist/data_streams/types.d.cts +1 -1
  24. package/dist/data_streams/types.d.ts +1 -1
  25. package/dist/frame_processor.cjs +6 -0
  26. package/dist/frame_processor.cjs.map +1 -1
  27. package/dist/frame_processor.d.cts +2 -0
  28. package/dist/frame_processor.d.ts +2 -0
  29. package/dist/frame_processor.d.ts.map +1 -1
  30. package/dist/frame_processor.js +6 -0
  31. package/dist/frame_processor.js.map +1 -1
  32. package/dist/index.d.cts +4 -7
  33. package/dist/index.d.ts +4 -7
  34. package/dist/participant.cjs +6 -0
  35. package/dist/participant.cjs.map +1 -1
  36. package/dist/participant.d.cts +14 -153
  37. package/dist/participant.d.ts +14 -153
  38. package/dist/participant.d.ts.map +1 -1
  39. package/dist/participant.js +6 -0
  40. package/dist/participant.js.map +1 -1
  41. package/dist/room.cjs +28 -0
  42. package/dist/room.cjs.map +1 -1
  43. package/dist/room.d.cts +12 -221
  44. package/dist/room.d.ts +12 -221
  45. package/dist/room.d.ts.map +1 -1
  46. package/dist/room.js +28 -0
  47. package/dist/room.js.map +1 -1
  48. package/dist/track.cjs +123 -0
  49. package/dist/track.cjs.map +1 -1
  50. package/dist/track.d.cts +15 -42
  51. package/dist/track.d.ts +15 -42
  52. package/dist/track.d.ts.map +1 -1
  53. package/dist/track.js +123 -0
  54. package/dist/track.js.map +1 -1
  55. package/dist/track_publication.d.cts +14 -47
  56. package/dist/track_publication.d.ts +14 -47
  57. package/dist/{stream_reader-CuG4b8Y-.d.cts → types-_PdPVish.d.cts} +40 -40
  58. package/dist/{stream_reader-CuG4b8Y-.d.ts → types-_PdPVish.d.ts} +40 -40
  59. package/dist/version.cjs +1 -1
  60. package/dist/version.cjs.map +1 -1
  61. package/dist/version.d.cts +1 -1
  62. package/dist/version.d.ts +1 -1
  63. package/dist/version.js +1 -1
  64. package/dist/version.js.map +1 -1
  65. package/dist/video_stream.d.cts +12 -2
  66. package/dist/video_stream.d.ts +12 -2
  67. package/package.json +3 -3
  68. package/src/audio_source.test.ts +92 -0
  69. package/src/audio_source.ts +42 -18
  70. package/src/audio_stream.ts +28 -4
  71. package/src/audio_stream_room_lifecycle.test.ts +753 -0
  72. package/src/bun_runtime.test.ts +27 -0
  73. package/src/frame_processor.ts +4 -0
  74. package/src/participant.ts +17 -0
  75. package/src/room.ts +44 -0
  76. package/src/track.ts +141 -0
  77. package/src/version.ts +1 -1
@@ -1,28 +1,18 @@
1
- import { AudioFrame } from './audio_frame.js';
2
- import { FrameProcessor } from './frame_processor.js';
3
- import { Track } from './track.js';
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-DEG1JKge.js';
4
5
  import '@livekit/rtc-ffi-bindings';
5
6
  import './video_frame.js';
6
7
  import './audio_source.js';
7
8
  import './ffi_client.js';
8
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';
9
18
  import './video_source.js';
10
-
11
- interface AudioStreamOptions {
12
- noiseCancellation?: NoiseCancellationOptions | FrameProcessor<AudioFrame>;
13
- sampleRate?: number;
14
- numChannels?: number;
15
- frameSizeMs?: number;
16
- }
17
- interface NoiseCancellationOptions {
18
- moduleId: string;
19
- options: Record<string, any>;
20
- }
21
- declare class AudioStream extends ReadableStream<AudioFrame> {
22
- constructor(track: Track);
23
- constructor(track: Track, sampleRate: number);
24
- constructor(track: Track, sampleRate: number, numChannels: number);
25
- constructor(track: Track, options: AudioStreamOptions);
26
- }
27
-
28
- export { AudioStream, type AudioStreamOptions, type NoiseCancellationOptions };
@@ -1 +1 @@
1
- {"version":3,"file":"audio_stream.d.ts","sourceRoot":"","sources":["../src/audio_stream.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,OAAO,EAAE,KAAK,cAAc,EAAoB,MAAM,sBAAsB,CAAC;AAE7E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,WAAW,kBAAkB;IACjC,iBAAiB,CAAC,EAAE,wBAAwB,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IAEjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B;AAkHD,qBAAa,WAAY,SAAQ,cAAc,CAAC,UAAU,CAAC;gBAC7C,KAAK,EAAE,KAAK;gBACZ,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM;gBAChC,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;gBACrD,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB;CAQtD"}
1
+ {"version":3,"file":"audio_stream.d.ts","sourceRoot":"","sources":["../src/audio_stream.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,OAAO,EAAE,KAAK,cAAc,EAAoB,MAAM,sBAAsB,CAAC;AAE7E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,WAAW,kBAAkB;IACjC,iBAAiB,CAAC,EAAE,wBAAwB,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAC1E;;;;;OAKG;IACH,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IAEjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B;AAED,gBAAgB;AAChB,qBAAa,iBAAkB,YAAW,gBAAgB,CAAC,UAAU,CAAC;IACpE,OAAO,CAAC,UAAU,CAAC,CAA8C;IACjE,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,eAAe,CAAC,CAA2B;IACnD,OAAO,CAAC,cAAc,CAA2C;IACjE,OAAO,CAAC,kBAAkB,CAAQ;IAClC,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,KAAK,CAAQ;gBAGnB,KAAK,EAAE,KAAK,EACZ,mBAAmB,CAAC,EAAE,MAAM,GAAG,kBAAkB,EACjD,WAAW,CAAC,EAAE,MAAM;IA6CtB,gBAAgB;IAChB,IAAI,SAAS,IAAI,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAEjD;IAED,OAAO,CAAC,OAAO,CA0Cb;IAEF,KAAK,CAAC,UAAU,EAAE,+BAA+B,CAAC,UAAU,CAAC;IAI7D,MAAM;CAaP;AAED,qBAAa,WAAY,SAAQ,cAAc,CAAC,UAAU,CAAC;gBAC7C,KAAK,EAAE,KAAK;gBACZ,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM;gBAChC,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;gBACrD,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB;CAQtD"}
@@ -6,8 +6,9 @@ import { log } from "./log.js";
6
6
  class AudioStreamSource {
7
7
  constructor(track, sampleRateOrOptions, numChannels) {
8
8
  this.disposed = false;
9
+ this.frameProcessor = null;
10
+ this.autoCloseProcessor = true;
9
11
  this.onEvent = (ev) => {
10
- var _a;
11
12
  if (!this.controller) {
12
13
  throw new Error("Stream controller not initialized");
13
14
  }
@@ -32,17 +33,22 @@ class AudioStreamSource {
32
33
  this.controller.close();
33
34
  if (!this.disposed) {
34
35
  this.disposed = true;
36
+ this.track.unregisterAudioStream(this);
35
37
  this.ffiHandle.dispose();
36
- (_a = this.frameProcessor) == null ? void 0 : _a.close();
38
+ if (this.frameProcessor && this.autoCloseProcessor) {
39
+ this.frameProcessor.close();
40
+ }
37
41
  }
38
42
  break;
39
43
  }
40
44
  };
45
+ this.track = track;
41
46
  if (sampleRateOrOptions !== void 0 && typeof sampleRateOrOptions !== "number") {
42
47
  this.sampleRate = sampleRateOrOptions.sampleRate ?? 48e3;
43
48
  this.numChannels = sampleRateOrOptions.numChannels ?? 1;
44
49
  if (isFrameProcessor(sampleRateOrOptions.noiseCancellation)) {
45
50
  this.frameProcessor = sampleRateOrOptions.noiseCancellation;
51
+ this.autoCloseProcessor = sampleRateOrOptions.autoCloseNoiseCancellation ?? true;
46
52
  } else {
47
53
  this.legacyNcOptions = sampleRateOrOptions.noiseCancellation;
48
54
  }
@@ -70,17 +76,24 @@ class AudioStreamSource {
70
76
  });
71
77
  this.ffiHandle = new FfiHandle(res.stream.handle.id);
72
78
  FfiClient.instance.on(FfiClientEvent.FfiEvent, this.onEvent);
79
+ track.registerAudioStream(this);
80
+ }
81
+ /** @internal */
82
+ get processor() {
83
+ return this.frameProcessor;
73
84
  }
74
85
  start(controller) {
75
86
  this.controller = controller;
76
87
  }
77
88
  cancel() {
78
- var _a;
79
89
  FfiClient.instance.off(FfiClientEvent.FfiEvent, this.onEvent);
80
90
  if (!this.disposed) {
81
91
  this.disposed = true;
92
+ this.track.unregisterAudioStream(this);
82
93
  this.ffiHandle.dispose();
83
- (_a = this.frameProcessor) == null ? void 0 : _a.close();
94
+ if (this.frameProcessor && this.autoCloseProcessor) {
95
+ this.frameProcessor.close();
96
+ }
84
97
  }
85
98
  }
86
99
  }
@@ -90,6 +103,7 @@ class AudioStream extends ReadableStream {
90
103
  }
91
104
  }
92
105
  export {
93
- AudioStream
106
+ AudioStream,
107
+ AudioStreamSource
94
108
  };
95
109
  //# sourceMappingURL=audio_stream.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/audio_stream.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { NewAudioStreamResponse } from '@livekit/rtc-ffi-bindings';\nimport { AudioStreamType, NewAudioStreamRequest } from '@livekit/rtc-ffi-bindings';\nimport type { UnderlyingSource } from 'node:stream/web';\nimport { AudioFrame } from './audio_frame.js';\nimport type { FfiEvent } from './ffi_client.js';\nimport { FfiClient, FfiClientEvent, FfiHandle } from './ffi_client.js';\nimport { type FrameProcessor, isFrameProcessor } from './frame_processor.js';\nimport { log } from './log.js';\nimport type { Track } from './track.js';\n\nexport interface AudioStreamOptions {\n noiseCancellation?: NoiseCancellationOptions | FrameProcessor<AudioFrame>;\n sampleRate?: number;\n numChannels?: number;\n frameSizeMs?: number;\n}\n\nexport interface NoiseCancellationOptions {\n moduleId: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n options: Record<string, any>;\n}\n\nclass AudioStreamSource implements UnderlyingSource<AudioFrame> {\n private controller?: ReadableStreamDefaultController<AudioFrame>;\n private ffiHandle: FfiHandle;\n private disposed = false;\n private sampleRate: number;\n private numChannels: number;\n private legacyNcOptions?: NoiseCancellationOptions;\n private frameProcessor?: FrameProcessor<AudioFrame>;\n private frameSizeMs?: number;\n\n constructor(\n track: Track,\n sampleRateOrOptions?: number | AudioStreamOptions,\n numChannels?: number,\n ) {\n if (sampleRateOrOptions !== undefined && typeof sampleRateOrOptions !== 'number') {\n this.sampleRate = sampleRateOrOptions.sampleRate ?? 48000;\n this.numChannels = sampleRateOrOptions.numChannels ?? 1;\n if (isFrameProcessor(sampleRateOrOptions.noiseCancellation)) {\n this.frameProcessor = sampleRateOrOptions.noiseCancellation;\n } else {\n this.legacyNcOptions = sampleRateOrOptions.noiseCancellation;\n }\n this.frameSizeMs = sampleRateOrOptions.frameSizeMs;\n } else {\n this.sampleRate = (sampleRateOrOptions as number) ?? 48000;\n this.numChannels = numChannels ?? 1;\n }\n\n const req = new NewAudioStreamRequest({\n type: AudioStreamType.AUDIO_STREAM_NATIVE,\n trackHandle: track.ffi_handle.handle,\n sampleRate: this.sampleRate,\n numChannels: this.numChannels,\n frameSizeMs: this.frameSizeMs,\n ...(this.legacyNcOptions\n ? {\n audioFilterModuleId: this.legacyNcOptions.moduleId,\n audioFilterOptions: JSON.stringify(this.legacyNcOptions.options),\n }\n : {}),\n });\n\n const res = FfiClient.instance.request<NewAudioStreamResponse>({\n message: {\n case: 'newAudioStream',\n value: req,\n },\n });\n\n this.ffiHandle = new FfiHandle(res.stream!.handle!.id!);\n\n FfiClient.instance.on(FfiClientEvent.FfiEvent, this.onEvent);\n }\n\n private onEvent = (ev: FfiEvent) => {\n if (!this.controller) {\n throw new Error('Stream controller not initialized');\n }\n\n if (\n ev.message.case != 'audioStreamEvent' ||\n ev.message.value.streamHandle != this.ffiHandle.handle\n ) {\n return;\n }\n\n const streamEvent = ev.message.value.message;\n switch (streamEvent.case) {\n case 'frameReceived':\n let frame = AudioFrame.fromOwnedInfo(streamEvent.value.frame!);\n if (this.frameProcessor && this.frameProcessor.isEnabled()) {\n try {\n frame = this.frameProcessor.process(frame);\n } catch (err: unknown) {\n log.warn(`Frame processing failed, passing through original frame: ${err}`);\n }\n }\n this.controller.enqueue(frame);\n break;\n case 'eos':\n FfiClient.instance.off(FfiClientEvent.FfiEvent, this.onEvent);\n this.controller.close();\n // Dispose the native handle so the FD is released on stream end,\n // not just when cancel() is called explicitly by the consumer.\n // Guard against double-dispose if cancel() is called after EOS\n // while buffered frames are still in the ReadableStream queue.\n if (!this.disposed) {\n this.disposed = true;\n this.ffiHandle.dispose();\n this.frameProcessor?.close();\n }\n break;\n }\n };\n\n start(controller: ReadableStreamDefaultController<AudioFrame>) {\n this.controller = controller;\n }\n\n cancel() {\n FfiClient.instance.off(FfiClientEvent.FfiEvent, this.onEvent);\n if (!this.disposed) {\n this.disposed = true;\n this.ffiHandle.dispose();\n // Also close the frame processor on cancel for symmetry with the EOS path,\n // so resources are released regardless of how the stream ends.\n this.frameProcessor?.close();\n }\n }\n}\n\nexport class AudioStream extends ReadableStream<AudioFrame> {\n constructor(track: Track);\n constructor(track: Track, sampleRate: number);\n constructor(track: Track, sampleRate: number, numChannels: number);\n constructor(track: Track, options: AudioStreamOptions);\n constructor(\n track: Track,\n sampleRateOrOptions?: number | AudioStreamOptions,\n numChannels?: number,\n ) {\n super(new AudioStreamSource(track, sampleRateOrOptions, numChannels));\n }\n}\n"],"mappings":"AAIA,SAAS,iBAAiB,6BAA6B;AAEvD,SAAS,kBAAkB;AAE3B,SAAS,WAAW,gBAAgB,iBAAiB;AACrD,SAA8B,wBAAwB;AACtD,SAAS,WAAW;AAgBpB,MAAM,kBAA0D;AAAA,EAU9D,YACE,OACA,qBACA,aACA;AAXF,SAAQ,WAAW;AAoDnB,SAAQ,UAAU,CAAC,OAAiB;AAjFtC;AAkFI,UAAI,CAAC,KAAK,YAAY;AACpB,cAAM,IAAI,MAAM,mCAAmC;AAAA,MACrD;AAEA,UACE,GAAG,QAAQ,QAAQ,sBACnB,GAAG,QAAQ,MAAM,gBAAgB,KAAK,UAAU,QAChD;AACA;AAAA,MACF;AAEA,YAAM,cAAc,GAAG,QAAQ,MAAM;AACrC,cAAQ,YAAY,MAAM;AAAA,QACxB,KAAK;AACH,cAAI,QAAQ,WAAW,cAAc,YAAY,MAAM,KAAM;AAC7D,cAAI,KAAK,kBAAkB,KAAK,eAAe,UAAU,GAAG;AAC1D,gBAAI;AACF,sBAAQ,KAAK,eAAe,QAAQ,KAAK;AAAA,YAC3C,SAAS,KAAc;AACrB,kBAAI,KAAK,4DAA4D,GAAG,EAAE;AAAA,YAC5E;AAAA,UACF;AACA,eAAK,WAAW,QAAQ,KAAK;AAC7B;AAAA,QACF,KAAK;AACH,oBAAU,SAAS,IAAI,eAAe,UAAU,KAAK,OAAO;AAC5D,eAAK,WAAW,MAAM;AAKtB,cAAI,CAAC,KAAK,UAAU;AAClB,iBAAK,WAAW;AAChB,iBAAK,UAAU,QAAQ;AACvB,uBAAK,mBAAL,mBAAqB;AAAA,UACvB;AACA;AAAA,MACJ;AAAA,IACF;AA/EE,QAAI,wBAAwB,UAAa,OAAO,wBAAwB,UAAU;AAChF,WAAK,aAAa,oBAAoB,cAAc;AACpD,WAAK,cAAc,oBAAoB,eAAe;AACtD,UAAI,iBAAiB,oBAAoB,iBAAiB,GAAG;AAC3D,aAAK,iBAAiB,oBAAoB;AAAA,MAC5C,OAAO;AACL,aAAK,kBAAkB,oBAAoB;AAAA,MAC7C;AACA,WAAK,cAAc,oBAAoB;AAAA,IACzC,OAAO;AACL,WAAK,aAAc,uBAAkC;AACrD,WAAK,cAAc,eAAe;AAAA,IACpC;AAEA,UAAM,MAAM,IAAI,sBAAsB;AAAA,MACpC,MAAM,gBAAgB;AAAA,MACtB,aAAa,MAAM,WAAW;AAAA,MAC9B,YAAY,KAAK;AAAA,MACjB,aAAa,KAAK;AAAA,MAClB,aAAa,KAAK;AAAA,MAClB,GAAI,KAAK,kBACL;AAAA,QACE,qBAAqB,KAAK,gBAAgB;AAAA,QAC1C,oBAAoB,KAAK,UAAU,KAAK,gBAAgB,OAAO;AAAA,MACjE,IACA,CAAC;AAAA,IACP,CAAC;AAED,UAAM,MAAM,UAAU,SAAS,QAAgC;AAAA,MAC7D,SAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,SAAK,YAAY,IAAI,UAAU,IAAI,OAAQ,OAAQ,EAAG;AAEtD,cAAU,SAAS,GAAG,eAAe,UAAU,KAAK,OAAO;AAAA,EAC7D;AAAA,EA2CA,MAAM,YAAyD;AAC7D,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,SAAS;AA9HX;AA+HI,cAAU,SAAS,IAAI,eAAe,UAAU,KAAK,OAAO;AAC5D,QAAI,CAAC,KAAK,UAAU;AAClB,WAAK,WAAW;AAChB,WAAK,UAAU,QAAQ;AAGvB,iBAAK,mBAAL,mBAAqB;AAAA,IACvB;AAAA,EACF;AACF;AAEO,MAAM,oBAAoB,eAA2B;AAAA,EAK1D,YACE,OACA,qBACA,aACA;AACA,UAAM,IAAI,kBAAkB,OAAO,qBAAqB,WAAW,CAAC;AAAA,EACtE;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/audio_stream.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { NewAudioStreamResponse } from '@livekit/rtc-ffi-bindings';\nimport { AudioStreamType, NewAudioStreamRequest } from '@livekit/rtc-ffi-bindings';\nimport type { UnderlyingSource } from 'node:stream/web';\nimport { AudioFrame } from './audio_frame.js';\nimport type { FfiEvent } from './ffi_client.js';\nimport { FfiClient, FfiClientEvent, FfiHandle } from './ffi_client.js';\nimport { type FrameProcessor, isFrameProcessor } from './frame_processor.js';\nimport { log } from './log.js';\nimport type { Track } from './track.js';\n\nexport interface AudioStreamOptions {\n noiseCancellation?: NoiseCancellationOptions | FrameProcessor<AudioFrame>;\n /**\n * When the audio stream closes, whether to run the {@link FrameProcessor}'s\n * `close()` method. If `false`, the processor is left open so it can be\n * reused with another {@link AudioStream}. Only relevant when\n * `noiseCancellation` is a {@link FrameProcessor}. Defaults to `true`.\n */\n autoCloseNoiseCancellation?: boolean;\n sampleRate?: number;\n numChannels?: number;\n frameSizeMs?: number;\n}\n\nexport interface NoiseCancellationOptions {\n moduleId: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n options: Record<string, any>;\n}\n\n/** @internal */\nexport class AudioStreamSource implements UnderlyingSource<AudioFrame> {\n private controller?: ReadableStreamDefaultController<AudioFrame>;\n private ffiHandle: FfiHandle;\n private disposed = false;\n private sampleRate: number;\n private numChannels: number;\n private legacyNcOptions?: NoiseCancellationOptions;\n private frameProcessor: FrameProcessor<AudioFrame> | null = null;\n private autoCloseProcessor = true;\n private frameSizeMs?: number;\n private track: Track;\n\n constructor(\n track: Track,\n sampleRateOrOptions?: number | AudioStreamOptions,\n numChannels?: number,\n ) {\n this.track = track;\n if (sampleRateOrOptions !== undefined && typeof sampleRateOrOptions !== 'number') {\n this.sampleRate = sampleRateOrOptions.sampleRate ?? 48000;\n this.numChannels = sampleRateOrOptions.numChannels ?? 1;\n if (isFrameProcessor(sampleRateOrOptions.noiseCancellation)) {\n this.frameProcessor = sampleRateOrOptions.noiseCancellation;\n this.autoCloseProcessor = sampleRateOrOptions.autoCloseNoiseCancellation ?? true;\n } else {\n this.legacyNcOptions = sampleRateOrOptions.noiseCancellation;\n }\n this.frameSizeMs = sampleRateOrOptions.frameSizeMs;\n } else {\n this.sampleRate = (sampleRateOrOptions as number) ?? 48000;\n this.numChannels = numChannels ?? 1;\n }\n\n const req = new NewAudioStreamRequest({\n type: AudioStreamType.AUDIO_STREAM_NATIVE,\n trackHandle: track.ffi_handle.handle,\n sampleRate: this.sampleRate,\n numChannels: this.numChannels,\n frameSizeMs: this.frameSizeMs,\n ...(this.legacyNcOptions\n ? {\n audioFilterModuleId: this.legacyNcOptions.moduleId,\n audioFilterOptions: JSON.stringify(this.legacyNcOptions.options),\n }\n : {}),\n });\n\n const res = FfiClient.instance.request<NewAudioStreamResponse>({\n message: {\n case: 'newAudioStream',\n value: req,\n },\n });\n\n this.ffiHandle = new FfiHandle(res.stream!.handle!.id!);\n\n FfiClient.instance.on(FfiClientEvent.FfiEvent, this.onEvent);\n track.registerAudioStream(this);\n }\n\n /** @internal */\n get processor(): FrameProcessor<AudioFrame> | null {\n return this.frameProcessor;\n }\n\n private onEvent = (ev: FfiEvent) => {\n if (!this.controller) {\n throw new Error('Stream controller not initialized');\n }\n\n if (\n ev.message.case != 'audioStreamEvent' ||\n ev.message.value.streamHandle != this.ffiHandle.handle\n ) {\n return;\n }\n\n const streamEvent = ev.message.value.message;\n switch (streamEvent.case) {\n case 'frameReceived':\n let frame = AudioFrame.fromOwnedInfo(streamEvent.value.frame!);\n if (this.frameProcessor && this.frameProcessor.isEnabled()) {\n try {\n frame = this.frameProcessor.process(frame);\n } catch (err: unknown) {\n log.warn(`Frame processing failed, passing through original frame: ${err}`);\n }\n }\n this.controller.enqueue(frame);\n break;\n case 'eos':\n FfiClient.instance.off(FfiClientEvent.FfiEvent, this.onEvent);\n this.controller.close();\n // Dispose the native handle so the FD is released on stream end,\n // not just when cancel() is called explicitly by the consumer.\n // Guard against double-dispose if cancel() is called after EOS\n // while buffered frames are still in the ReadableStream queue.\n if (!this.disposed) {\n this.disposed = true;\n this.track.unregisterAudioStream(this);\n this.ffiHandle.dispose();\n if (this.frameProcessor && this.autoCloseProcessor) {\n this.frameProcessor.close();\n }\n }\n break;\n }\n };\n\n start(controller: ReadableStreamDefaultController<AudioFrame>) {\n this.controller = controller;\n }\n\n cancel() {\n FfiClient.instance.off(FfiClientEvent.FfiEvent, this.onEvent);\n if (!this.disposed) {\n this.disposed = true;\n this.track.unregisterAudioStream(this);\n this.ffiHandle.dispose();\n // Also close the frame processor on cancel for symmetry with the EOS path,\n // so resources are released regardless of how the stream ends.\n if (this.frameProcessor && this.autoCloseProcessor) {\n this.frameProcessor.close();\n }\n }\n }\n}\n\nexport class AudioStream extends ReadableStream<AudioFrame> {\n constructor(track: Track);\n constructor(track: Track, sampleRate: number);\n constructor(track: Track, sampleRate: number, numChannels: number);\n constructor(track: Track, options: AudioStreamOptions);\n constructor(\n track: Track,\n sampleRateOrOptions?: number | AudioStreamOptions,\n numChannels?: number,\n ) {\n super(new AudioStreamSource(track, sampleRateOrOptions, numChannels));\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,3 +1,3 @@
1
- export { a as BaseStreamInfo, f as ByteStreamHandler, b as ByteStreamInfo, e as ByteStreamOptions, B as ByteStreamReader, D as DataStreamOptions, S as StreamController, g as TextStreamHandler, c as TextStreamInfo, d as TextStreamOptions, T as TextStreamReader } from '../stream_reader-CuG4b8Y-.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-_PdPVish.cjs';
2
2
  export { ByteStreamWriter, TextStreamWriter } from './stream_writer.cjs';
3
3
  import '@livekit/rtc-ffi-bindings';
@@ -1,3 +1,3 @@
1
- export { a as BaseStreamInfo, f as ByteStreamHandler, b as ByteStreamInfo, e as ByteStreamOptions, B as ByteStreamReader, D as DataStreamOptions, S as StreamController, g as TextStreamHandler, c as TextStreamInfo, d as TextStreamOptions, T as TextStreamReader } from '../stream_reader-CuG4b8Y-.js';
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
2
  export { ByteStreamWriter, TextStreamWriter } from './stream_writer.js';
3
3
  import '@livekit/rtc-ffi-bindings';
@@ -1,2 +1,2 @@
1
1
  import '@livekit/rtc-ffi-bindings';
2
- export { B as ByteStreamReader, T as TextStreamReader } from '../stream_reader-CuG4b8Y-.cjs';
2
+ export { d as ByteStreamReader, g as TextStreamReader } from '../types-_PdPVish.cjs';
@@ -1,2 +1,2 @@
1
1
  import '@livekit/rtc-ffi-bindings';
2
- export { B as ByteStreamReader, T as TextStreamReader } from '../stream_reader-CuG4b8Y-.js';
2
+ export { d as ByteStreamReader, g as TextStreamReader } from '../types-_PdPVish.js';
@@ -1,4 +1,4 @@
1
- import { a as BaseStreamInfo, c as TextStreamInfo, b as ByteStreamInfo } from '../stream_reader-CuG4b8Y-.cjs';
1
+ import { B as BaseStreamInfo, e as TextStreamInfo, b as ByteStreamInfo } from '../types-_PdPVish.cjs';
2
2
  import '@livekit/rtc-ffi-bindings';
3
3
 
4
4
  declare class BaseStreamWriter<T, InfoType extends BaseStreamInfo> {
@@ -1,4 +1,4 @@
1
- import { a as BaseStreamInfo, c as TextStreamInfo, b as ByteStreamInfo } from '../stream_reader-CuG4b8Y-.js';
1
+ import { B as BaseStreamInfo, e as TextStreamInfo, b as ByteStreamInfo } from '../types-_PdPVish.js';
2
2
  import '@livekit/rtc-ffi-bindings';
3
3
 
4
4
  declare class BaseStreamWriter<T, InfoType extends BaseStreamInfo> {
@@ -1,2 +1,2 @@
1
1
  import '@livekit/rtc-ffi-bindings';
2
- export { a as BaseStreamInfo, f as ByteStreamHandler, b as ByteStreamInfo, e as ByteStreamOptions, D as DataStreamOptions, S as StreamController, g as TextStreamHandler, c as TextStreamInfo, d as TextStreamOptions } from '../stream_reader-CuG4b8Y-.cjs';
2
+ export { B as BaseStreamInfo, a as ByteStreamHandler, b as ByteStreamInfo, c as ByteStreamOptions, D as DataStreamOptions, S as StreamController, T as TextStreamHandler, e as TextStreamInfo, f as TextStreamOptions } from '../types-_PdPVish.cjs';
@@ -1,2 +1,2 @@
1
1
  import '@livekit/rtc-ffi-bindings';
2
- export { a as BaseStreamInfo, f as ByteStreamHandler, b as ByteStreamInfo, e as ByteStreamOptions, D as DataStreamOptions, S as StreamController, g as TextStreamHandler, c as TextStreamInfo, d as TextStreamOptions } from '../stream_reader-CuG4b8Y-.js';
2
+ export { B as BaseStreamInfo, a as ByteStreamHandler, b as ByteStreamInfo, c as ByteStreamOptions, D as DataStreamOptions, S as StreamController, T as TextStreamHandler, e as TextStreamInfo, f as TextStreamOptions } from '../types-_PdPVish.js';
@@ -37,8 +37,14 @@ class FrameProcessor {
37
37
  onStreamInfoUpdated(_info) {
38
38
  }
39
39
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
40
+ onStreamInfoCleared() {
41
+ }
42
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
40
43
  onCredentialsUpdated(_credentials) {
41
44
  }
45
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
46
+ onCredentialsCleared() {
47
+ }
42
48
  }
43
49
  // Annotate the CommonJS export names for ESM import in node:
44
50
  0 && (module.exports = {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/frame_processor.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { type AudioFrame } from './audio_frame.js';\nimport { type VideoFrame } from './video_frame.js';\n\nexport type FrameProcessorStreamInfo = {\n roomName: string;\n participantIdentity: string;\n publicationSid: string;\n};\n\nexport type FrameProcessorCredentials = {\n token: string;\n url: string;\n};\n\nexport const FrameProcessorSymbol = Symbol.for('lk.frame-processor');\n\nexport function isFrameProcessor<\n T extends FrameProcessor<AudioFrame> | FrameProcessor<VideoFrame> | unknown,\n>(\n maybeProcessor: unknown,\n): maybeProcessor is T extends FrameProcessor<AudioFrame>\n ? FrameProcessor<AudioFrame>\n : T extends FrameProcessor<VideoFrame>\n ? FrameProcessor<VideoFrame>\n : FrameProcessor<AudioFrame> | FrameProcessor<VideoFrame> {\n return (\n maybeProcessor !== null &&\n typeof maybeProcessor === 'object' &&\n 'symbol' in maybeProcessor &&\n maybeProcessor.symbol === FrameProcessorSymbol\n );\n}\n\nexport abstract class FrameProcessor<Frame extends VideoFrame | AudioFrame> {\n readonly symbol = FrameProcessorSymbol;\n\n abstract isEnabled(): boolean;\n abstract setEnabled(enabled: boolean): void;\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onStreamInfoUpdated(_info: FrameProcessorStreamInfo): void {}\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onCredentialsUpdated(_credentials: FrameProcessorCredentials): void {}\n\n abstract process(frame: Frame): Frame;\n abstract close(): void;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,yBAAgC;AAChC,yBAAgC;AAazB,MAAM,uBAAuB,OAAO,IAAI,oBAAoB;AAE5D,SAAS,iBAGd,gBAK4D;AAC5D,SACE,mBAAmB,QACnB,OAAO,mBAAmB,YAC1B,YAAY,kBACZ,eAAe,WAAW;AAE9B;AAEO,MAAe,eAAsD;AAAA,EAArE;AACL,SAAS,SAAS;AAAA;AAAA;AAAA,EAMlB,oBAAoB,OAAuC;AAAA,EAAC;AAAA;AAAA,EAE5D,qBAAqB,cAA+C;AAAA,EAAC;AAIvE;","names":[]}
1
+ {"version":3,"sources":["../src/frame_processor.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { type AudioFrame } from './audio_frame.js';\nimport { type VideoFrame } from './video_frame.js';\n\nexport type FrameProcessorStreamInfo = {\n roomName: string;\n participantIdentity: string;\n publicationSid: string;\n};\n\nexport type FrameProcessorCredentials = {\n token: string;\n url: string;\n};\n\nexport const FrameProcessorSymbol = Symbol.for('lk.frame-processor');\n\nexport function isFrameProcessor<\n T extends FrameProcessor<AudioFrame> | FrameProcessor<VideoFrame> | unknown,\n>(\n maybeProcessor: unknown,\n): maybeProcessor is T extends FrameProcessor<AudioFrame>\n ? FrameProcessor<AudioFrame>\n : T extends FrameProcessor<VideoFrame>\n ? FrameProcessor<VideoFrame>\n : FrameProcessor<AudioFrame> | FrameProcessor<VideoFrame> {\n return (\n maybeProcessor !== null &&\n typeof maybeProcessor === 'object' &&\n 'symbol' in maybeProcessor &&\n maybeProcessor.symbol === FrameProcessorSymbol\n );\n}\n\nexport abstract class FrameProcessor<Frame extends VideoFrame | AudioFrame> {\n readonly symbol = FrameProcessorSymbol;\n\n abstract isEnabled(): boolean;\n abstract setEnabled(enabled: boolean): void;\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onStreamInfoUpdated(_info: FrameProcessorStreamInfo): void {}\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onStreamInfoCleared(): void {}\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onCredentialsUpdated(_credentials: FrameProcessorCredentials): void {}\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onCredentialsCleared(): void {}\n\n abstract process(frame: Frame): Frame;\n abstract close(): void;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,yBAAgC;AAChC,yBAAgC;AAazB,MAAM,uBAAuB,OAAO,IAAI,oBAAoB;AAE5D,SAAS,iBAGd,gBAK4D;AAC5D,SACE,mBAAmB,QACnB,OAAO,mBAAmB,YAC1B,YAAY,kBACZ,eAAe,WAAW;AAE9B;AAEO,MAAe,eAAsD;AAAA,EAArE;AACL,SAAS,SAAS;AAAA;AAAA;AAAA,EAMlB,oBAAoB,OAAuC;AAAA,EAAC;AAAA;AAAA,EAE5D,sBAA4B;AAAA,EAAC;AAAA;AAAA,EAE7B,qBAAqB,cAA+C;AAAA,EAAC;AAAA;AAAA,EAErE,uBAA6B;AAAA,EAAC;AAIhC;","names":[]}
@@ -18,7 +18,9 @@ declare abstract class FrameProcessor<Frame extends VideoFrame | AudioFrame> {
18
18
  abstract isEnabled(): boolean;
19
19
  abstract setEnabled(enabled: boolean): void;
20
20
  onStreamInfoUpdated(_info: FrameProcessorStreamInfo): void;
21
+ onStreamInfoCleared(): void;
21
22
  onCredentialsUpdated(_credentials: FrameProcessorCredentials): void;
23
+ onCredentialsCleared(): void;
22
24
  abstract process(frame: Frame): Frame;
23
25
  abstract close(): void;
24
26
  }
@@ -18,7 +18,9 @@ declare abstract class FrameProcessor<Frame extends VideoFrame | AudioFrame> {
18
18
  abstract isEnabled(): boolean;
19
19
  abstract setEnabled(enabled: boolean): void;
20
20
  onStreamInfoUpdated(_info: FrameProcessorStreamInfo): void;
21
+ onStreamInfoCleared(): void;
21
22
  onCredentialsUpdated(_credentials: FrameProcessorCredentials): void;
23
+ onCredentialsCleared(): void;
22
24
  abstract process(frame: Frame): Frame;
23
25
  abstract close(): void;
24
26
  }
@@ -1 +1 @@
1
- {"version":3,"file":"frame_processor.d.ts","sourceRoot":"","sources":["../src/frame_processor.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,eAAO,MAAM,oBAAoB,eAAmC,CAAC;AAErE,wBAAgB,gBAAgB,CAC9B,CAAC,SAAS,cAAc,CAAC,UAAU,CAAC,GAAG,cAAc,CAAC,UAAU,CAAC,GAAG,OAAO,EAE3E,cAAc,EAAE,OAAO,GACtB,cAAc,IAAI,CAAC,SAAS,cAAc,CAAC,UAAU,CAAC,GACrD,cAAc,CAAC,UAAU,CAAC,GAC1B,CAAC,SAAS,cAAc,CAAC,UAAU,CAAC,GAClC,cAAc,CAAC,UAAU,CAAC,GAC1B,cAAc,CAAC,UAAU,CAAC,GAAG,cAAc,CAAC,UAAU,CAAC,CAO5D;AAED,8BAAsB,cAAc,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU;IACxE,QAAQ,CAAC,MAAM,SAAwB;IAEvC,QAAQ,CAAC,SAAS,IAAI,OAAO;IAC7B,QAAQ,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAG3C,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,GAAG,IAAI;IAE1D,oBAAoB,CAAC,YAAY,EAAE,yBAAyB,GAAG,IAAI;IAEnE,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK;IACrC,QAAQ,CAAC,KAAK,IAAI,IAAI;CACvB"}
1
+ {"version":3,"file":"frame_processor.d.ts","sourceRoot":"","sources":["../src/frame_processor.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,eAAO,MAAM,oBAAoB,eAAmC,CAAC;AAErE,wBAAgB,gBAAgB,CAC9B,CAAC,SAAS,cAAc,CAAC,UAAU,CAAC,GAAG,cAAc,CAAC,UAAU,CAAC,GAAG,OAAO,EAE3E,cAAc,EAAE,OAAO,GACtB,cAAc,IAAI,CAAC,SAAS,cAAc,CAAC,UAAU,CAAC,GACrD,cAAc,CAAC,UAAU,CAAC,GAC1B,CAAC,SAAS,cAAc,CAAC,UAAU,CAAC,GAClC,cAAc,CAAC,UAAU,CAAC,GAC1B,cAAc,CAAC,UAAU,CAAC,GAAG,cAAc,CAAC,UAAU,CAAC,CAO5D;AAED,8BAAsB,cAAc,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU;IACxE,QAAQ,CAAC,MAAM,SAAwB;IAEvC,QAAQ,CAAC,SAAS,IAAI,OAAO;IAC7B,QAAQ,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAG3C,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,GAAG,IAAI;IAE1D,mBAAmB,IAAI,IAAI;IAE3B,oBAAoB,CAAC,YAAY,EAAE,yBAAyB,GAAG,IAAI;IAEnE,oBAAoB,IAAI,IAAI;IAE5B,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK;IACrC,QAAQ,CAAC,KAAK,IAAI,IAAI;CACvB"}
@@ -12,8 +12,14 @@ class FrameProcessor {
12
12
  onStreamInfoUpdated(_info) {
13
13
  }
14
14
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
15
+ onStreamInfoCleared() {
16
+ }
17
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
15
18
  onCredentialsUpdated(_credentials) {
16
19
  }
20
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
21
+ onCredentialsCleared() {
22
+ }
17
23
  }
18
24
  export {
19
25
  FrameProcessor,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/frame_processor.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { type AudioFrame } from './audio_frame.js';\nimport { type VideoFrame } from './video_frame.js';\n\nexport type FrameProcessorStreamInfo = {\n roomName: string;\n participantIdentity: string;\n publicationSid: string;\n};\n\nexport type FrameProcessorCredentials = {\n token: string;\n url: string;\n};\n\nexport const FrameProcessorSymbol = Symbol.for('lk.frame-processor');\n\nexport function isFrameProcessor<\n T extends FrameProcessor<AudioFrame> | FrameProcessor<VideoFrame> | unknown,\n>(\n maybeProcessor: unknown,\n): maybeProcessor is T extends FrameProcessor<AudioFrame>\n ? FrameProcessor<AudioFrame>\n : T extends FrameProcessor<VideoFrame>\n ? FrameProcessor<VideoFrame>\n : FrameProcessor<AudioFrame> | FrameProcessor<VideoFrame> {\n return (\n maybeProcessor !== null &&\n typeof maybeProcessor === 'object' &&\n 'symbol' in maybeProcessor &&\n maybeProcessor.symbol === FrameProcessorSymbol\n );\n}\n\nexport abstract class FrameProcessor<Frame extends VideoFrame | AudioFrame> {\n readonly symbol = FrameProcessorSymbol;\n\n abstract isEnabled(): boolean;\n abstract setEnabled(enabled: boolean): void;\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onStreamInfoUpdated(_info: FrameProcessorStreamInfo): void {}\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onCredentialsUpdated(_credentials: FrameProcessorCredentials): void {}\n\n abstract process(frame: Frame): Frame;\n abstract close(): void;\n}\n"],"mappings":"AAGA,eAAgC;AAChC,eAAgC;AAazB,MAAM,uBAAuB,OAAO,IAAI,oBAAoB;AAE5D,SAAS,iBAGd,gBAK4D;AAC5D,SACE,mBAAmB,QACnB,OAAO,mBAAmB,YAC1B,YAAY,kBACZ,eAAe,WAAW;AAE9B;AAEO,MAAe,eAAsD;AAAA,EAArE;AACL,SAAS,SAAS;AAAA;AAAA;AAAA,EAMlB,oBAAoB,OAAuC;AAAA,EAAC;AAAA;AAAA,EAE5D,qBAAqB,cAA+C;AAAA,EAAC;AAIvE;","names":[]}
1
+ {"version":3,"sources":["../src/frame_processor.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { type AudioFrame } from './audio_frame.js';\nimport { type VideoFrame } from './video_frame.js';\n\nexport type FrameProcessorStreamInfo = {\n roomName: string;\n participantIdentity: string;\n publicationSid: string;\n};\n\nexport type FrameProcessorCredentials = {\n token: string;\n url: string;\n};\n\nexport const FrameProcessorSymbol = Symbol.for('lk.frame-processor');\n\nexport function isFrameProcessor<\n T extends FrameProcessor<AudioFrame> | FrameProcessor<VideoFrame> | unknown,\n>(\n maybeProcessor: unknown,\n): maybeProcessor is T extends FrameProcessor<AudioFrame>\n ? FrameProcessor<AudioFrame>\n : T extends FrameProcessor<VideoFrame>\n ? FrameProcessor<VideoFrame>\n : FrameProcessor<AudioFrame> | FrameProcessor<VideoFrame> {\n return (\n maybeProcessor !== null &&\n typeof maybeProcessor === 'object' &&\n 'symbol' in maybeProcessor &&\n maybeProcessor.symbol === FrameProcessorSymbol\n );\n}\n\nexport abstract class FrameProcessor<Frame extends VideoFrame | AudioFrame> {\n readonly symbol = FrameProcessorSymbol;\n\n abstract isEnabled(): boolean;\n abstract setEnabled(enabled: boolean): void;\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onStreamInfoUpdated(_info: FrameProcessorStreamInfo): void {}\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onStreamInfoCleared(): void {}\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onCredentialsUpdated(_credentials: FrameProcessorCredentials): void {}\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onCredentialsCleared(): void {}\n\n abstract process(frame: Frame): Frame;\n abstract close(): void;\n}\n"],"mappings":"AAGA,eAAgC;AAChC,eAAgC;AAazB,MAAM,uBAAuB,OAAO,IAAI,oBAAoB;AAE5D,SAAS,iBAGd,gBAK4D;AAC5D,SACE,mBAAmB,QACnB,OAAO,mBAAmB,YAC1B,YAAY,kBACZ,eAAe,WAAW;AAE9B;AAEO,MAAe,eAAsD;AAAA,EAArE;AACL,SAAS,SAAS;AAAA;AAAA;AAAA,EAMlB,oBAAoB,OAAuC;AAAA,EAAC;AAAA;AAAA,EAE5D,sBAA4B;AAAA,EAAC;AAAA;AAAA,EAE7B,qBAAqB,cAA+C;AAAA,EAAC;AAAA;AAAA,EAErE,uBAA6B;AAAA,EAAC;AAIhC;","names":[]}
package/dist/index.d.cts CHANGED
@@ -1,26 +1,23 @@
1
1
  export { AudioFrame, combineAudioFrames } from './audio_frame.cjs';
2
2
  export { AudioResampler, AudioResamplerQuality } from './audio_resampler.cjs';
3
3
  export { AudioSource } from './audio_source.cjs';
4
- export { AudioStream, NoiseCancellationOptions } from './audio_stream.cjs';
4
+ export { A as AudioStream, a as AudioTrack, C as ConnectError, L as LocalAudioTrack, b as LocalParticipant, c as LocalTrack, d as LocalTrackPublication, e as LocalVideoTrack, N as NoiseCancellationOptions, P as Participant, R as RemoteAudioTrack, f as RemoteParticipant, g as RemoteTrack, h as RemoteTrackPublication, i as RemoteVideoTrack, j as Room, k as RoomEvent, l as RoomOptions, m as RtcConfiguration, T as Track, n as TrackPublication, V as VideoTrack } from './audio_stream-B4hGVcKz.cjs';
5
5
  export { AudioFilter } from './audio_filter.cjs';
6
6
  export { AudioMixer, AudioMixerOptions } from './audio_mixer.cjs';
7
- export { a as BaseStreamInfo, f as ByteStreamHandler, b as ByteStreamInfo, e as ByteStreamOptions, B as ByteStreamReader, D as DataStreamOptions, S as StreamController, g as TextStreamHandler, c as TextStreamInfo, d as TextStreamOptions, T as TextStreamReader } from './stream_reader-CuG4b8Y-.cjs';
7
+ 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';
8
8
  export { ByteStreamWriter, TextStreamWriter } from './data_streams/stream_writer.cjs';
9
9
  export { E2EEManager, E2EEOptions, FrameCryptor, KeyProvider, KeyProviderOptions } from './e2ee.cjs';
10
10
  import './ffi_client.cjs';
11
- export { LocalParticipant, Participant, RemoteParticipant } from './participant.cjs';
12
11
  export { ConnectionQuality, ConnectionState, ContinualGatheringPolicy, DataPacketKind, DisconnectReason, EncryptionState, EncryptionType, IceServer, IceTransportType, ParticipantKind, ParticipantKindDetail, SimulateScenarioKind, StreamState, TrackKind, TrackPublishOptions, TrackSource, VideoBufferType, VideoCodec, VideoRotation, livekitDispose as dispose } from '@livekit/rtc-ffi-bindings';
13
- export { ConnectError, Room, RoomEvent, RoomOptions, RtcConfiguration } from './room.cjs';
14
12
  export { PerformRpcParams, RpcError, RpcInvocationData } from './rpc.cjs';
15
- export { AudioTrack, LocalAudioTrack, LocalTrack, LocalVideoTrack, RemoteAudioTrack, RemoteTrack, RemoteVideoTrack, Track, VideoTrack } from './track.cjs';
16
- export { LocalTrackPublication, RemoteTrackPublication, TrackPublication } from './track_publication.cjs';
17
13
  export { Transcription, TranscriptionSegment } from './transcription.cjs';
18
14
  export { ChatMessage } from './types.cjs';
19
15
  export { VideoFrame } from './video_frame.cjs';
20
16
  export { VideoSource } from './video_source.cjs';
21
17
  export { VideoFrameEvent, VideoStream } from './video_stream.cjs';
22
18
  export { FrameProcessor, FrameProcessorCredentials, FrameProcessorStreamInfo, isFrameProcessor } from './frame_processor.cjs';
23
- import './async_queue.cjs';
19
+ import 'node:stream/web';
24
20
  import '@livekit/typed-emitter';
25
21
  import '@livekit/mutex';
26
22
  import 'node:fs';
23
+ import './async_queue.cjs';
package/dist/index.d.ts CHANGED
@@ -1,26 +1,23 @@
1
1
  export { AudioFrame, combineAudioFrames } from './audio_frame.js';
2
2
  export { AudioResampler, AudioResamplerQuality } from './audio_resampler.js';
3
3
  export { AudioSource } from './audio_source.js';
4
- export { AudioStream, NoiseCancellationOptions } from './audio_stream.js';
4
+ export { A as AudioStream, a as AudioTrack, C as ConnectError, L as LocalAudioTrack, b as LocalParticipant, c as LocalTrack, d as LocalTrackPublication, e as LocalVideoTrack, N as NoiseCancellationOptions, P as Participant, R as RemoteAudioTrack, f as RemoteParticipant, g as RemoteTrack, h as RemoteTrackPublication, i as RemoteVideoTrack, j as Room, k as RoomEvent, l as RoomOptions, m as RtcConfiguration, T as Track, n as TrackPublication, V as VideoTrack } from './audio_stream-DEG1JKge.js';
5
5
  export { AudioFilter } from './audio_filter.js';
6
6
  export { AudioMixer, AudioMixerOptions } from './audio_mixer.js';
7
- export { a as BaseStreamInfo, f as ByteStreamHandler, b as ByteStreamInfo, e as ByteStreamOptions, B as ByteStreamReader, D as DataStreamOptions, S as StreamController, g as TextStreamHandler, c as TextStreamInfo, d as TextStreamOptions, T as TextStreamReader } from './stream_reader-CuG4b8Y-.js';
7
+ 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';
8
8
  export { ByteStreamWriter, TextStreamWriter } from './data_streams/stream_writer.js';
9
9
  export { E2EEManager, E2EEOptions, FrameCryptor, KeyProvider, KeyProviderOptions } from './e2ee.js';
10
10
  import './ffi_client.js';
11
- export { LocalParticipant, Participant, RemoteParticipant } from './participant.js';
12
11
  export { ConnectionQuality, ConnectionState, ContinualGatheringPolicy, DataPacketKind, DisconnectReason, EncryptionState, EncryptionType, IceServer, IceTransportType, ParticipantKind, ParticipantKindDetail, SimulateScenarioKind, StreamState, TrackKind, TrackPublishOptions, TrackSource, VideoBufferType, VideoCodec, VideoRotation, livekitDispose as dispose } from '@livekit/rtc-ffi-bindings';
13
- export { ConnectError, Room, RoomEvent, RoomOptions, RtcConfiguration } from './room.js';
14
12
  export { PerformRpcParams, RpcError, RpcInvocationData } from './rpc.js';
15
- export { AudioTrack, LocalAudioTrack, LocalTrack, LocalVideoTrack, RemoteAudioTrack, RemoteTrack, RemoteVideoTrack, Track, VideoTrack } from './track.js';
16
- export { LocalTrackPublication, RemoteTrackPublication, TrackPublication } from './track_publication.js';
17
13
  export { Transcription, TranscriptionSegment } from './transcription.js';
18
14
  export { ChatMessage } from './types.js';
19
15
  export { VideoFrame } from './video_frame.js';
20
16
  export { VideoSource } from './video_source.js';
21
17
  export { VideoFrameEvent, VideoStream } from './video_stream.js';
22
18
  export { FrameProcessor, FrameProcessorCredentials, FrameProcessorStreamInfo, isFrameProcessor } from './frame_processor.js';
23
- import './async_queue.js';
19
+ import 'node:stream/web';
24
20
  import '@livekit/typed-emitter';
25
21
  import '@livekit/mutex';
26
22
  import 'node:fs';
23
+ import './async_queue.js';
@@ -530,6 +530,9 @@ class LocalParticipant extends Participant {
530
530
  case "publication":
531
531
  const track_publication = new import_track_publication.LocalTrackPublication(cb.message.value);
532
532
  track_publication.track = track;
533
+ if (track.info && track_publication.sid) {
534
+ track.info.sid = track_publication.sid;
535
+ }
533
536
  this.trackPublications.set(track_publication.sid, track_publication);
534
537
  return track_publication;
535
538
  case "error":
@@ -560,6 +563,9 @@ class LocalParticipant extends Participant {
560
563
  }
561
564
  const pub = this.trackPublications.get(trackSid);
562
565
  if (pub) {
566
+ if (pub.track) {
567
+ pub.track.setRoom(null);
568
+ }
563
569
  pub.track = void 0;
564
570
  }
565
571
  this.trackPublications.delete(trackSid);