@livekit/rtc-node 0.13.4 → 0.13.6

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 (97) hide show
  1. package/dist/data_streams/index.d.cts +2 -2
  2. package/dist/data_streams/index.d.ts +2 -2
  3. package/dist/data_streams/stream_reader.cjs +5 -9
  4. package/dist/data_streams/stream_reader.cjs.map +1 -1
  5. package/dist/data_streams/stream_reader.d.cts +1 -1
  6. package/dist/data_streams/stream_reader.d.ts +1 -1
  7. package/dist/data_streams/stream_reader.d.ts.map +1 -1
  8. package/dist/data_streams/stream_reader.js +5 -9
  9. package/dist/data_streams/stream_reader.js.map +1 -1
  10. package/dist/data_streams/stream_writer.cjs +2 -2
  11. package/dist/data_streams/stream_writer.cjs.map +1 -1
  12. package/dist/data_streams/stream_writer.d.cts +5 -5
  13. package/dist/data_streams/stream_writer.d.ts +5 -5
  14. package/dist/data_streams/stream_writer.d.ts.map +1 -1
  15. package/dist/data_streams/stream_writer.js +2 -2
  16. package/dist/data_streams/stream_writer.js.map +1 -1
  17. package/dist/data_streams/types.cjs.map +1 -1
  18. package/dist/data_streams/types.d.cts +1 -1
  19. package/dist/data_streams/types.d.ts +1 -1
  20. package/dist/data_streams/types.d.ts.map +1 -1
  21. package/dist/index.cjs +15 -13
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +17 -17
  24. package/dist/index.d.ts +17 -17
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +29 -28
  27. package/dist/index.js.map +1 -1
  28. package/dist/participant.cjs +9 -20
  29. package/dist/participant.cjs.map +1 -1
  30. package/dist/participant.d.cts +2 -2
  31. package/dist/participant.d.ts +2 -2
  32. package/dist/participant.d.ts.map +1 -1
  33. package/dist/participant.js +9 -20
  34. package/dist/participant.js.map +1 -1
  35. package/dist/proto/ffi_pb.cjs +2 -0
  36. package/dist/proto/ffi_pb.cjs.map +1 -1
  37. package/dist/proto/ffi_pb.d.cts +13 -1
  38. package/dist/proto/ffi_pb.d.ts +13 -1
  39. package/dist/proto/ffi_pb.d.ts.map +1 -1
  40. package/dist/proto/ffi_pb.js +3 -1
  41. package/dist/proto/ffi_pb.js.map +1 -1
  42. package/dist/proto/room_pb.cjs +2 -1
  43. package/dist/proto/room_pb.cjs.map +1 -1
  44. package/dist/proto/room_pb.d.cts +4 -0
  45. package/dist/proto/room_pb.d.ts +4 -0
  46. package/dist/proto/room_pb.d.ts.map +1 -1
  47. package/dist/proto/room_pb.js +2 -1
  48. package/dist/proto/room_pb.js.map +1 -1
  49. package/dist/proto/track_pb.cjs +90 -0
  50. package/dist/proto/track_pb.cjs.map +1 -1
  51. package/dist/proto/track_pb.d.cts +70 -1
  52. package/dist/proto/track_pb.d.ts +70 -1
  53. package/dist/proto/track_pb.d.ts.map +1 -1
  54. package/dist/proto/track_pb.js +87 -0
  55. package/dist/proto/track_pb.js.map +1 -1
  56. package/dist/proto/video_frame_pb.cjs +1 -1
  57. package/dist/proto/video_frame_pb.cjs.map +1 -1
  58. package/dist/proto/video_frame_pb.d.cts +1 -1
  59. package/dist/proto/video_frame_pb.d.ts +1 -1
  60. package/dist/proto/video_frame_pb.js +1 -1
  61. package/dist/proto/video_frame_pb.js.map +1 -1
  62. package/dist/room.cjs +7 -7
  63. package/dist/room.cjs.map +1 -1
  64. package/dist/room.d.cts +1 -1
  65. package/dist/room.d.ts +1 -1
  66. package/dist/room.d.ts.map +1 -1
  67. package/dist/room.js +2 -4
  68. package/dist/room.js.map +1 -1
  69. package/dist/{types-Ca3IVRvo.d.ts → stream_reader-DWUV4eJB.d.ts} +43 -48
  70. package/dist/{types-BWsKf9LP.d.cts → stream_reader-a8_oiaOi.d.cts} +43 -48
  71. package/dist/utils.cjs +15 -5
  72. package/dist/utils.cjs.map +1 -1
  73. package/dist/utils.d.cts +1 -1
  74. package/dist/utils.d.ts +1 -1
  75. package/dist/utils.d.ts.map +1 -1
  76. package/dist/utils.js +15 -5
  77. package/dist/utils.js.map +1 -1
  78. package/dist/version.cjs +1 -1
  79. package/dist/version.cjs.map +1 -1
  80. package/dist/version.d.cts +1 -1
  81. package/dist/version.d.ts +1 -1
  82. package/dist/version.js +1 -1
  83. package/dist/version.js.map +1 -1
  84. package/package.json +6 -6
  85. package/src/data_streams/stream_reader.ts +8 -15
  86. package/src/data_streams/stream_writer.ts +5 -5
  87. package/src/data_streams/types.ts +0 -6
  88. package/src/index.ts +33 -33
  89. package/src/participant.ts +11 -25
  90. package/src/proto/ffi_pb.ts +15 -1
  91. package/src/proto/room_pb.ts +6 -0
  92. package/src/proto/track_pb.ts +135 -0
  93. package/src/proto/video_frame_pb.ts +2 -2
  94. package/src/room.ts +7 -8
  95. package/src/utils.test.ts +51 -0
  96. package/src/utils.ts +17 -8
  97. package/src/version.ts +1 -1
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "LiveKit RTC Node",
4
4
  "license": "Apache-2.0",
5
5
  "author": "LiveKit",
6
- "version": "0.13.4",
6
+ "version": "0.13.6",
7
7
  "main": "dist/index.js",
8
8
  "require": "dist/index.cjs",
9
9
  "types": "dist/index.d.ts",
@@ -61,11 +61,11 @@
61
61
  "@bufbuild/protoc-gen-es": "^1.10.0"
62
62
  },
63
63
  "optionalDependencies": {
64
- "@livekit/rtc-node-darwin-arm64": "0.13.4",
65
- "@livekit/rtc-node-darwin-x64": "0.13.4",
66
- "@livekit/rtc-node-linux-arm64-gnu": "0.13.4",
67
- "@livekit/rtc-node-linux-x64-gnu": "0.13.4",
68
- "@livekit/rtc-node-win32-x64-msvc": "0.13.4"
64
+ "@livekit/rtc-node-darwin-x64": "0.13.6",
65
+ "@livekit/rtc-node-linux-arm64-gnu": "0.13.6",
66
+ "@livekit/rtc-node-linux-x64-gnu": "0.13.6",
67
+ "@livekit/rtc-node-win32-x64-msvc": "0.13.6",
68
+ "@livekit/rtc-node-darwin-arm64": "0.13.6"
69
69
  },
70
70
  "engines": {
71
71
  "node": ">= 18"
@@ -5,7 +5,7 @@ import type { ReadableStream } from 'node:stream/web';
5
5
  import { log } from '../log.js';
6
6
  import type { DataStream_Chunk } from '../proto/room_pb.js';
7
7
  import { bigIntToNumber } from '../utils.js';
8
- import type { BaseStreamInfo, ByteStreamInfo, TextStreamChunk, TextStreamInfo } from './types.js';
8
+ import type { BaseStreamInfo, ByteStreamInfo, TextStreamInfo } from './types.js';
9
9
 
10
10
  abstract class BaseStreamReader<T extends BaseStreamInfo> {
11
11
  protected reader: ReadableStream<DataStream_Chunk>;
@@ -124,7 +124,7 @@ export class TextStreamReader extends BaseStreamReader<TextStreamInfo> {
124
124
  const decoder = new TextDecoder();
125
125
 
126
126
  return {
127
- next: async (): Promise<IteratorResult<TextStreamChunk>> => {
127
+ next: async (): Promise<IteratorResult<string>> => {
128
128
  try {
129
129
  const { done, value } = await reader.read();
130
130
  if (done) {
@@ -133,14 +133,7 @@ export class TextStreamReader extends BaseStreamReader<TextStreamInfo> {
133
133
  this.handleChunkReceived(value);
134
134
  return {
135
135
  done: false,
136
- value: {
137
- index: bigIntToNumber(value.chunkIndex)!,
138
- current: decoder.decode(value.content!),
139
- collected: Array.from(this.receivedChunks.values())
140
- .sort((a, b) => bigIntToNumber(a.chunkIndex!) - bigIntToNumber(b.chunkIndex!))
141
- .map((chunk) => decoder.decode(chunk.content!))
142
- .join(''),
143
- },
136
+ value: decoder.decode(value.content!),
144
137
  };
145
138
  }
146
139
  } catch (error) {
@@ -149,7 +142,7 @@ export class TextStreamReader extends BaseStreamReader<TextStreamInfo> {
149
142
  }
150
143
  },
151
144
 
152
- return(): IteratorResult<TextStreamChunk> {
145
+ return(): IteratorResult<string> {
153
146
  reader.releaseLock();
154
147
  return { done: true, value: undefined };
155
148
  },
@@ -157,10 +150,10 @@ export class TextStreamReader extends BaseStreamReader<TextStreamInfo> {
157
150
  }
158
151
 
159
152
  async readAll(): Promise<string> {
160
- let latestString: string = '';
161
- for await (const { collected } of this) {
162
- latestString = collected;
153
+ let finalString: string = '';
154
+ for await (const chunk of this) {
155
+ finalString += chunk;
163
156
  }
164
- return latestString;
157
+ return finalString;
165
158
  }
166
159
  }
@@ -5,23 +5,23 @@ import type { WritableStream } from 'node:stream/web';
5
5
  import type { BaseStreamInfo, ByteStreamInfo, TextStreamInfo } from './types.js';
6
6
 
7
7
  class BaseStreamWriter<T, InfoType extends BaseStreamInfo> {
8
- protected writableStream: WritableStream<[T, number?]>;
8
+ protected writableStream: WritableStream<T>;
9
9
 
10
- protected defaultWriter: WritableStreamDefaultWriter<[T, number?]>;
10
+ protected defaultWriter: WritableStreamDefaultWriter<T>;
11
11
 
12
12
  protected onClose?: () => void;
13
13
 
14
14
  readonly info: InfoType;
15
15
 
16
- constructor(writableStream: WritableStream<[T, number?]>, info: InfoType, onClose?: () => void) {
16
+ constructor(writableStream: WritableStream<T>, info: InfoType, onClose?: () => void) {
17
17
  this.writableStream = writableStream;
18
18
  this.defaultWriter = writableStream.getWriter();
19
19
  this.onClose = onClose;
20
20
  this.info = info;
21
21
  }
22
22
 
23
- write(chunk: T, chunkIndex?: number): Promise<void> {
24
- return this.defaultWriter.write([chunk, chunkIndex]);
23
+ write(chunk: T): Promise<void> {
24
+ return this.defaultWriter.write(chunk);
25
25
  }
26
26
 
27
27
  async close() {
@@ -27,12 +27,6 @@ export type ByteStreamInfo = BaseStreamInfo & {
27
27
 
28
28
  export type TextStreamInfo = BaseStreamInfo;
29
29
 
30
- export type TextStreamChunk = {
31
- index: number;
32
- current: string;
33
- collected: string;
34
- };
35
-
36
30
  export interface DataStreamOptions {
37
31
  topic?: string;
38
32
  destinationIdentities?: Array<string>;
package/src/index.ts CHANGED
@@ -2,48 +2,48 @@
2
2
  //
3
3
  // SPDX-License-Identifier: Apache-2.0
4
4
 
5
- export { Room, RoomEvent, ConnectError, type RoomOptions, type RtcConfiguration } from './room.js';
6
- export { Participant, RemoteParticipant, LocalParticipant } from './participant.js';
7
- export {
8
- Track,
9
- type LocalTrack,
10
- type RemoteTrack,
11
- type VideoTrack,
12
- LocalAudioTrack,
13
- LocalVideoTrack,
14
- RemoteAudioTrack,
15
- RemoteVideoTrack,
16
- type AudioTrack,
17
- } from './track.js';
18
- export { VideoFrame } from './video_frame.js';
19
5
  export { AudioFrame, combineAudioFrames } from './audio_frame.js';
20
- export { AudioStream } from './audio_stream.js';
21
6
  export { AudioResampler, AudioResamplerQuality } from './audio_resampler.js';
22
- export { VideoStream, type VideoFrameEvent } from './video_stream.js';
23
7
  export { AudioSource } from './audio_source.js';
24
- export { VideoSource } from './video_source.js';
25
- export {
26
- TrackPublication,
27
- RemoteTrackPublication,
28
- LocalTrackPublication,
29
- } from './track_publication.js';
30
- export type { Transcription, TranscriptionSegment } from './transcription.js';
31
- export { E2EEManager, KeyProvider, FrameCryptor } from './e2ee.js';
32
- export type { E2EEOptions, KeyProviderOptions } from './e2ee.js';
8
+ export { AudioStream } from './audio_stream.js';
33
9
  export * from './data_streams/index.js';
10
+ export { E2EEManager, FrameCryptor, KeyProvider } from './e2ee.js';
11
+ export type { E2EEOptions, KeyProviderOptions } from './e2ee.js';
12
+ export { dispose } from './ffi_client.js';
13
+ export { LocalParticipant, Participant, RemoteParticipant } from './participant.js';
14
+ export { EncryptionState, EncryptionType } from './proto/e2ee_pb.js';
15
+ export { DisconnectReason, ParticipantKind } from './proto/participant_pb.js';
34
16
  export {
35
17
  ConnectionQuality,
18
+ ConnectionState,
19
+ ContinualGatheringPolicy,
20
+ DataPacketKind,
36
21
  IceServer,
37
22
  IceTransportType,
38
- DataPacketKind,
39
- ContinualGatheringPolicy,
40
23
  TrackPublishOptions,
41
- ConnectionState,
42
24
  } from './proto/room_pb.js';
43
- export { RpcError, type RpcInvocationData, type PerformRpcParams } from './rpc.js';
44
- export { EncryptionType, EncryptionState } from './proto/e2ee_pb.js';
45
25
  export { StreamState, TrackKind, TrackSource } from './proto/track_pb.js';
46
- export { VideoBufferType, VideoRotation, VideoCodec } from './proto/video_frame_pb.js';
47
- export { ParticipantKind } from './proto/participant_pb.js';
48
- export { dispose } from './ffi_client.js';
26
+ export { VideoBufferType, VideoCodec, VideoRotation } from './proto/video_frame_pb.js';
27
+ export { ConnectError, Room, RoomEvent, type RoomOptions, type RtcConfiguration } from './room.js';
28
+ export { RpcError, type PerformRpcParams, type RpcInvocationData } from './rpc.js';
29
+ export {
30
+ LocalAudioTrack,
31
+ LocalVideoTrack,
32
+ RemoteAudioTrack,
33
+ RemoteVideoTrack,
34
+ Track,
35
+ type AudioTrack,
36
+ type LocalTrack,
37
+ type RemoteTrack,
38
+ type VideoTrack,
39
+ } from './track.js';
40
+ export {
41
+ LocalTrackPublication,
42
+ RemoteTrackPublication,
43
+ TrackPublication,
44
+ } from './track_publication.js';
45
+ export type { Transcription, TranscriptionSegment } from './transcription.js';
49
46
  export type { ChatMessage } from './types.js';
47
+ export { VideoFrame } from './video_frame.js';
48
+ export { VideoSource } from './video_source.js';
49
+ export { VideoStream, type VideoFrameEvent } from './video_stream.js';
@@ -293,40 +293,29 @@ export class LocalParticipant extends Participant {
293
293
 
294
294
  await this.sendStreamHeader(headerReq);
295
295
 
296
- let chunkId = 0;
296
+ let nextChunkId = 0;
297
297
  const localHandle = this.ffi_handle.handle;
298
298
  const sendTrailer = this.sendStreamTrailer;
299
299
  const sendChunk = this.sendStreamChunk;
300
300
 
301
- const writableStream = new WritableStream<[string, number?]>({
301
+ const writableStream = new WritableStream<string>({
302
302
  // Implement the sink
303
- write([textChunk, overrideChunkId]) {
304
- const textInBytes = new TextEncoder().encode(textChunk);
305
-
306
- if (textInBytes.byteLength > STREAM_CHUNK_SIZE) {
307
- this.abort?.();
308
- throw new Error('chunk size too large');
309
- }
310
-
311
- return new Promise(async (resolve) => {
303
+ async write(text) {
304
+ for (const textByteChunk of splitUtf8(text, STREAM_CHUNK_SIZE)) {
312
305
  const chunkRequest = new SendStreamChunkRequest({
313
306
  senderIdentity,
314
307
  localParticipantHandle: localHandle,
315
308
  destinationIdentities,
316
309
  chunk: new DataStream_Chunk({
317
- content: textInBytes,
310
+ content: textByteChunk,
318
311
  streamId,
319
- chunkIndex: numberToBigInt(overrideChunkId ?? chunkId),
312
+ chunkIndex: numberToBigInt(nextChunkId),
320
313
  }),
321
314
  });
322
315
 
323
316
  await sendChunk(chunkRequest);
324
-
325
- if (!overrideChunkId) {
326
- chunkId += 1;
327
- resolve();
328
- }
329
- });
317
+ nextChunkId += 1;
318
+ }
330
319
  },
331
320
  async close() {
332
321
  const trailerReq = new SendStreamTrailerRequest({
@@ -360,10 +349,7 @@ export class LocalParticipant extends Participant {
360
349
  },
361
350
  ) {
362
351
  const writer = await this.streamText(options);
363
-
364
- for (const chunk in splitUtf8(text, STREAM_CHUNK_SIZE)) {
365
- await writer.write(chunk);
366
- }
352
+ await writer.write(text);
367
353
  await writer.close();
368
354
  return writer.info;
369
355
  }
@@ -419,8 +405,8 @@ export class LocalParticipant extends Participant {
419
405
  const sendChunk = this.sendStreamChunk;
420
406
  const writeMutex = new Mutex();
421
407
 
422
- const writableStream = new WritableStream<[Uint8Array, number?]>({
423
- async write([chunk]) {
408
+ const writableStream = new WritableStream<Uint8Array>({
409
+ async write(chunk) {
424
410
  const unlock = await writeMutex.lock();
425
411
 
426
412
  let byteOffset = 0;
@@ -20,7 +20,7 @@
20
20
  import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf";
21
21
  import { Message, proto2 } from "@bufbuild/protobuf";
22
22
  import { ConnectCallback, ConnectRequest, ConnectResponse, DisconnectCallback, DisconnectRequest, DisconnectResponse, EditChatMessageRequest, GetSessionStatsCallback, GetSessionStatsRequest, GetSessionStatsResponse, PublishDataCallback, PublishDataRequest, PublishDataResponse, PublishSipDtmfCallback, PublishSipDtmfRequest, PublishSipDtmfResponse, PublishTrackCallback, PublishTrackRequest, PublishTrackResponse, PublishTranscriptionCallback, PublishTranscriptionRequest, PublishTranscriptionResponse, RoomEvent, SendChatMessageCallback, SendChatMessageRequest, SendChatMessageResponse, SendStreamChunkCallback, SendStreamChunkRequest, SendStreamChunkResponse, SendStreamHeaderCallback, SendStreamHeaderRequest, SendStreamHeaderResponse, SendStreamTrailerCallback, SendStreamTrailerRequest, SendStreamTrailerResponse, SetDataChannelBufferedAmountLowThresholdRequest, SetDataChannelBufferedAmountLowThresholdResponse, SetLocalAttributesCallback, SetLocalAttributesRequest, SetLocalAttributesResponse, SetLocalMetadataCallback, SetLocalMetadataRequest, SetLocalMetadataResponse, SetLocalNameCallback, SetLocalNameRequest, SetLocalNameResponse, SetSubscribedRequest, SetSubscribedResponse, UnpublishTrackCallback, UnpublishTrackRequest, UnpublishTrackResponse } from "./room_pb.js";
23
- import { CreateAudioTrackRequest, CreateAudioTrackResponse, CreateVideoTrackRequest, CreateVideoTrackResponse, EnableRemoteTrackRequest, EnableRemoteTrackResponse, GetStatsCallback, GetStatsRequest, GetStatsResponse, LocalTrackMuteRequest, LocalTrackMuteResponse, TrackEvent } from "./track_pb.js";
23
+ import { CreateAudioTrackRequest, CreateAudioTrackResponse, CreateVideoTrackRequest, CreateVideoTrackResponse, EnableRemoteTrackRequest, EnableRemoteTrackResponse, GetStatsCallback, GetStatsRequest, GetStatsResponse, LocalTrackMuteRequest, LocalTrackMuteResponse, SetTrackSubscriptionPermissionsRequest, SetTrackSubscriptionPermissionsResponse, TrackEvent } from "./track_pb.js";
24
24
  import { CaptureVideoFrameRequest, CaptureVideoFrameResponse, NewVideoSourceRequest, NewVideoSourceResponse, NewVideoStreamRequest, NewVideoStreamResponse, VideoConvertRequest, VideoConvertResponse, VideoStreamEvent, VideoStreamFromParticipantRequest, VideoStreamFromParticipantResponse } from "./video_frame_pb.js";
25
25
  import { AudioStreamEvent, AudioStreamFromParticipantRequest, AudioStreamFromParticipantResponse, CaptureAudioFrameCallback, CaptureAudioFrameRequest, CaptureAudioFrameResponse, ClearAudioBufferRequest, ClearAudioBufferResponse, FlushSoxResamplerRequest, FlushSoxResamplerResponse, NewAudioResamplerRequest, NewAudioResamplerResponse, NewAudioSourceRequest, NewAudioSourceResponse, NewAudioStreamRequest, NewAudioStreamResponse, NewSoxResamplerRequest, NewSoxResamplerResponse, PushSoxResamplerRequest, PushSoxResamplerResponse, RemixAndResampleRequest, RemixAndResampleResponse } from "./audio_frame_pb.js";
26
26
  import { E2eeRequest, E2eeResponse } from "./e2ee_pb.js";
@@ -187,6 +187,12 @@ export class FfiRequest extends Message<FfiRequest> {
187
187
  */
188
188
  value: GetStatsRequest;
189
189
  case: "getStats";
190
+ } | {
191
+ /**
192
+ * @generated from field: livekit.proto.SetTrackSubscriptionPermissionsRequest set_track_subscription_permissions = 48;
193
+ */
194
+ value: SetTrackSubscriptionPermissionsRequest;
195
+ case: "setTrackSubscriptionPermissions";
190
196
  } | {
191
197
  /**
192
198
  * Video
@@ -395,6 +401,7 @@ export class FfiRequest extends Message<FfiRequest> {
395
401
  { no: 17, name: "local_track_mute", kind: "message", T: LocalTrackMuteRequest, oneof: "message" },
396
402
  { no: 18, name: "enable_remote_track", kind: "message", T: EnableRemoteTrackRequest, oneof: "message" },
397
403
  { no: 19, name: "get_stats", kind: "message", T: GetStatsRequest, oneof: "message" },
404
+ { no: 48, name: "set_track_subscription_permissions", kind: "message", T: SetTrackSubscriptionPermissionsRequest, oneof: "message" },
398
405
  { no: 20, name: "new_video_stream", kind: "message", T: NewVideoStreamRequest, oneof: "message" },
399
406
  { no: 21, name: "new_video_source", kind: "message", T: NewVideoSourceRequest, oneof: "message" },
400
407
  { no: 22, name: "capture_video_frame", kind: "message", T: CaptureVideoFrameRequest, oneof: "message" },
@@ -563,6 +570,12 @@ export class FfiResponse extends Message<FfiResponse> {
563
570
  */
564
571
  value: GetStatsResponse;
565
572
  case: "getStats";
573
+ } | {
574
+ /**
575
+ * @generated from field: livekit.proto.SetTrackSubscriptionPermissionsResponse set_track_subscription_permissions = 47;
576
+ */
577
+ value: SetTrackSubscriptionPermissionsResponse;
578
+ case: "setTrackSubscriptionPermissions";
566
579
  } | {
567
580
  /**
568
581
  * Video
@@ -765,6 +778,7 @@ export class FfiResponse extends Message<FfiResponse> {
765
778
  { no: 17, name: "local_track_mute", kind: "message", T: LocalTrackMuteResponse, oneof: "message" },
766
779
  { no: 18, name: "enable_remote_track", kind: "message", T: EnableRemoteTrackResponse, oneof: "message" },
767
780
  { no: 19, name: "get_stats", kind: "message", T: GetStatsResponse, oneof: "message" },
781
+ { no: 47, name: "set_track_subscription_permissions", kind: "message", T: SetTrackSubscriptionPermissionsResponse, oneof: "message" },
768
782
  { no: 20, name: "new_video_stream", kind: "message", T: NewVideoStreamResponse, oneof: "message" },
769
783
  { no: 21, name: "new_video_source", kind: "message", T: NewVideoSourceResponse, oneof: "message" },
770
784
  { no: 22, name: "capture_video_frame", kind: "message", T: CaptureVideoFrameResponse, oneof: "message" },
@@ -2986,6 +2986,11 @@ export class ParticipantDisconnected extends Message<ParticipantDisconnected> {
2986
2986
  */
2987
2987
  participantIdentity?: string;
2988
2988
 
2989
+ /**
2990
+ * @generated from field: required livekit.proto.DisconnectReason disconnect_reason = 2;
2991
+ */
2992
+ disconnectReason?: DisconnectReason;
2993
+
2989
2994
  constructor(data?: PartialMessage<ParticipantDisconnected>) {
2990
2995
  super();
2991
2996
  proto2.util.initPartial(data, this);
@@ -2995,6 +3000,7 @@ export class ParticipantDisconnected extends Message<ParticipantDisconnected> {
2995
3000
  static readonly typeName = "livekit.proto.ParticipantDisconnected";
2996
3001
  static readonly fields: FieldList = proto2.util.newFieldList(() => [
2997
3002
  { no: 1, name: "participant_identity", kind: "scalar", T: 9 /* ScalarType.STRING */, req: true },
3003
+ { no: 2, name: "disconnect_reason", kind: "enum", T: proto2.getEnumType(DisconnectReason), req: true },
2998
3004
  ]);
2999
3005
 
3000
3006
  static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ParticipantDisconnected {
@@ -845,3 +845,138 @@ export class EnableRemoteTrackResponse extends Message<EnableRemoteTrackResponse
845
845
  }
846
846
  }
847
847
 
848
+ /**
849
+ * @generated from message livekit.proto.SetTrackSubscriptionPermissionsRequest
850
+ */
851
+ export class SetTrackSubscriptionPermissionsRequest extends Message<SetTrackSubscriptionPermissionsRequest> {
852
+ /**
853
+ * @generated from field: required uint64 local_participant_handle = 1;
854
+ */
855
+ localParticipantHandle?: bigint;
856
+
857
+ /**
858
+ * @generated from field: required bool all_participants_allowed = 2;
859
+ */
860
+ allParticipantsAllowed?: boolean;
861
+
862
+ /**
863
+ * @generated from field: repeated livekit.proto.ParticipantTrackPermission permissions = 3;
864
+ */
865
+ permissions: ParticipantTrackPermission[] = [];
866
+
867
+ constructor(data?: PartialMessage<SetTrackSubscriptionPermissionsRequest>) {
868
+ super();
869
+ proto2.util.initPartial(data, this);
870
+ }
871
+
872
+ static readonly runtime: typeof proto2 = proto2;
873
+ static readonly typeName = "livekit.proto.SetTrackSubscriptionPermissionsRequest";
874
+ static readonly fields: FieldList = proto2.util.newFieldList(() => [
875
+ { no: 1, name: "local_participant_handle", kind: "scalar", T: 4 /* ScalarType.UINT64 */, req: true },
876
+ { no: 2, name: "all_participants_allowed", kind: "scalar", T: 8 /* ScalarType.BOOL */, req: true },
877
+ { no: 3, name: "permissions", kind: "message", T: ParticipantTrackPermission, repeated: true },
878
+ ]);
879
+
880
+ static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): SetTrackSubscriptionPermissionsRequest {
881
+ return new SetTrackSubscriptionPermissionsRequest().fromBinary(bytes, options);
882
+ }
883
+
884
+ static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): SetTrackSubscriptionPermissionsRequest {
885
+ return new SetTrackSubscriptionPermissionsRequest().fromJson(jsonValue, options);
886
+ }
887
+
888
+ static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): SetTrackSubscriptionPermissionsRequest {
889
+ return new SetTrackSubscriptionPermissionsRequest().fromJsonString(jsonString, options);
890
+ }
891
+
892
+ static equals(a: SetTrackSubscriptionPermissionsRequest | PlainMessage<SetTrackSubscriptionPermissionsRequest> | undefined, b: SetTrackSubscriptionPermissionsRequest | PlainMessage<SetTrackSubscriptionPermissionsRequest> | undefined): boolean {
893
+ return proto2.util.equals(SetTrackSubscriptionPermissionsRequest, a, b);
894
+ }
895
+ }
896
+
897
+ /**
898
+ * @generated from message livekit.proto.ParticipantTrackPermission
899
+ */
900
+ export class ParticipantTrackPermission extends Message<ParticipantTrackPermission> {
901
+ /**
902
+ * The participant identity this permission applies to.
903
+ *
904
+ * @generated from field: required string participant_identity = 1;
905
+ */
906
+ participantIdentity?: string;
907
+
908
+ /**
909
+ * Grant permission to all all tracks. Takes precedence over allowedTrackSids.
910
+ *
911
+ * @generated from field: optional bool allow_all = 2;
912
+ */
913
+ allowAll?: boolean;
914
+
915
+ /**
916
+ * List of track sids to grant permission to.
917
+ *
918
+ * @generated from field: repeated string allowed_track_sids = 3;
919
+ */
920
+ allowedTrackSids: string[] = [];
921
+
922
+ constructor(data?: PartialMessage<ParticipantTrackPermission>) {
923
+ super();
924
+ proto2.util.initPartial(data, this);
925
+ }
926
+
927
+ static readonly runtime: typeof proto2 = proto2;
928
+ static readonly typeName = "livekit.proto.ParticipantTrackPermission";
929
+ static readonly fields: FieldList = proto2.util.newFieldList(() => [
930
+ { no: 1, name: "participant_identity", kind: "scalar", T: 9 /* ScalarType.STRING */, req: true },
931
+ { no: 2, name: "allow_all", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true },
932
+ { no: 3, name: "allowed_track_sids", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true },
933
+ ]);
934
+
935
+ static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ParticipantTrackPermission {
936
+ return new ParticipantTrackPermission().fromBinary(bytes, options);
937
+ }
938
+
939
+ static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): ParticipantTrackPermission {
940
+ return new ParticipantTrackPermission().fromJson(jsonValue, options);
941
+ }
942
+
943
+ static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): ParticipantTrackPermission {
944
+ return new ParticipantTrackPermission().fromJsonString(jsonString, options);
945
+ }
946
+
947
+ static equals(a: ParticipantTrackPermission | PlainMessage<ParticipantTrackPermission> | undefined, b: ParticipantTrackPermission | PlainMessage<ParticipantTrackPermission> | undefined): boolean {
948
+ return proto2.util.equals(ParticipantTrackPermission, a, b);
949
+ }
950
+ }
951
+
952
+ /**
953
+ * @generated from message livekit.proto.SetTrackSubscriptionPermissionsResponse
954
+ */
955
+ export class SetTrackSubscriptionPermissionsResponse extends Message<SetTrackSubscriptionPermissionsResponse> {
956
+ constructor(data?: PartialMessage<SetTrackSubscriptionPermissionsResponse>) {
957
+ super();
958
+ proto2.util.initPartial(data, this);
959
+ }
960
+
961
+ static readonly runtime: typeof proto2 = proto2;
962
+ static readonly typeName = "livekit.proto.SetTrackSubscriptionPermissionsResponse";
963
+ static readonly fields: FieldList = proto2.util.newFieldList(() => [
964
+ ]);
965
+
966
+ static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): SetTrackSubscriptionPermissionsResponse {
967
+ return new SetTrackSubscriptionPermissionsResponse().fromBinary(bytes, options);
968
+ }
969
+
970
+ static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): SetTrackSubscriptionPermissionsResponse {
971
+ return new SetTrackSubscriptionPermissionsResponse().fromJson(jsonValue, options);
972
+ }
973
+
974
+ static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): SetTrackSubscriptionPermissionsResponse {
975
+ return new SetTrackSubscriptionPermissionsResponse().fromJsonString(jsonString, options);
976
+ }
977
+
978
+ static equals(a: SetTrackSubscriptionPermissionsResponse | PlainMessage<SetTrackSubscriptionPermissionsResponse> | undefined, b: SetTrackSubscriptionPermissionsResponse | PlainMessage<SetTrackSubscriptionPermissionsResponse> | undefined): boolean {
979
+ return proto2.util.equals(SetTrackSubscriptionPermissionsResponse, a, b);
980
+ }
981
+ }
982
+
@@ -753,7 +753,7 @@ export class VideoBufferInfo extends Message<VideoBufferInfo> {
753
753
  /**
754
754
  * only for packed formats
755
755
  *
756
- * @generated from field: required uint32 stride = 6;
756
+ * @generated from field: optional uint32 stride = 6;
757
757
  */
758
758
  stride?: number;
759
759
 
@@ -774,7 +774,7 @@ export class VideoBufferInfo extends Message<VideoBufferInfo> {
774
774
  { no: 2, name: "width", kind: "scalar", T: 13 /* ScalarType.UINT32 */, req: true },
775
775
  { no: 3, name: "height", kind: "scalar", T: 13 /* ScalarType.UINT32 */, req: true },
776
776
  { no: 4, name: "data_ptr", kind: "scalar", T: 4 /* ScalarType.UINT64 */, req: true },
777
- { no: 6, name: "stride", kind: "scalar", T: 13 /* ScalarType.UINT32 */, req: true },
777
+ { no: 6, name: "stride", kind: "scalar", T: 13 /* ScalarType.UINT32 */, opt: true },
778
778
  { no: 7, name: "components", kind: "message", T: VideoBufferInfo_ComponentInfo, repeated: true },
779
779
  ]);
780
780
 
package/src/room.ts CHANGED
@@ -21,24 +21,22 @@ import { LocalParticipant, RemoteParticipant } from './participant.js';
21
21
  import { EncryptionState } from './proto/e2ee_pb.js';
22
22
  import type { FfiEvent } from './proto/ffi_pb.js';
23
23
  import type { DisconnectReason, OwnedParticipant } from './proto/participant_pb.js';
24
+ import type { DataStream_Trailer } from './proto/room_pb.js';
24
25
  import {
25
26
  type ConnectCallback,
27
+ ConnectRequest,
26
28
  type ConnectResponse,
27
29
  type ConnectionQuality,
30
+ ConnectionState,
31
+ ContinualGatheringPolicy,
28
32
  type DataPacketKind,
29
33
  type DataStream_Chunk,
30
34
  type DataStream_Header,
31
- DataStream_Trailer,
32
35
  type DisconnectResponse,
33
36
  RoomOptions as FfiRoomOptions,
34
37
  type IceServer,
35
- type RoomInfo,
36
- } from './proto/room_pb.js';
37
- import {
38
- ConnectRequest,
39
- ConnectionState,
40
- ContinualGatheringPolicy,
41
38
  IceTransportType,
39
+ type RoomInfo,
42
40
  } from './proto/room_pb.js';
43
41
  import { TrackKind } from './proto/track_pb.js';
44
42
  import type { LocalTrack, RemoteTrack } from './track.js';
@@ -249,7 +247,8 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
249
247
  this.emit(RoomEvent.ParticipantConnected, participant);
250
248
  } else if (ev.case == 'participantDisconnected') {
251
249
  const participant = this.remoteParticipants.get(ev.value.participantIdentity!);
252
- this.remoteParticipants.delete(participant!.identity!);
250
+ this.remoteParticipants.delete(participant!.identity);
251
+ participant!.info.disconnectReason = ev.value.disconnectReason;
253
252
  this.emit(RoomEvent.ParticipantDisconnected, participant!);
254
253
  } else if (ev.case == 'localTrackPublished') {
255
254
  const publication = this.localParticipant!.trackPublications.get(ev.value.trackSid!);
@@ -0,0 +1,51 @@
1
+ // SPDX-FileCopyrightText: 2024 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import { describe, expect, it } from 'vitest';
5
+ import { splitUtf8 } from './utils.js';
6
+
7
+ describe('splitUtf8', () => {
8
+ it('splits a string into chunks of the given size', () => {
9
+ expect(splitUtf8('hello world', 5)).toEqual([
10
+ new TextEncoder().encode('hello'),
11
+ new TextEncoder().encode(' worl'),
12
+ new TextEncoder().encode('d'),
13
+ ]);
14
+ });
15
+
16
+ it('splits a string with special characters into chunks of the given size', () => {
17
+ expect(splitUtf8('héllo wörld', 5)).toEqual([
18
+ new TextEncoder().encode('héll'),
19
+ new TextEncoder().encode('o wö'),
20
+ new TextEncoder().encode('rld'),
21
+ ]);
22
+ });
23
+
24
+ it('splits a string with multi-byte utf8 characters correctly', () => {
25
+ expect(splitUtf8('こんにちは世界', 5)).toEqual([
26
+ new TextEncoder().encode('こ'),
27
+ new TextEncoder().encode('ん'),
28
+ new TextEncoder().encode('に'),
29
+ new TextEncoder().encode('ち'),
30
+ new TextEncoder().encode('は'),
31
+ new TextEncoder().encode('世'),
32
+ new TextEncoder().encode('界'),
33
+ ]);
34
+ });
35
+
36
+ it('handles a string with a single multi-byte utf8 character', () => {
37
+ expect(splitUtf8('😊', 5)).toEqual([new TextEncoder().encode('😊')]);
38
+ });
39
+
40
+ it('handles a string with mixed single and multi-byte utf8 characters', () => {
41
+ expect(splitUtf8('a😊b', 4)).toEqual([
42
+ new TextEncoder().encode('a'),
43
+ new TextEncoder().encode('😊'),
44
+ new TextEncoder().encode('b'),
45
+ ]);
46
+ });
47
+
48
+ it('handles an empty string', () => {
49
+ expect(splitUtf8('', 5)).toEqual([]);
50
+ });
51
+ });
package/src/utils.ts CHANGED
@@ -16,18 +16,27 @@ export function numberToBigInt<T extends number | undefined>(
16
16
  return (value !== undefined ? BigInt(value) : undefined) as T extends number ? bigint : undefined;
17
17
  }
18
18
 
19
- export function splitUtf8(s: string, n: number): string[] {
19
+ export function splitUtf8(s: string, n: number): Uint8Array[] {
20
+ if (n < 4) {
21
+ throw new Error('n must be at least 4 due to utf8 encoding rules');
22
+ }
20
23
  // adapted from https://stackoverflow.com/a/6043797
21
- const result: string[] = [];
22
- while (s.length > n) {
24
+ const result: Uint8Array[] = [];
25
+ let encoded = new TextEncoder().encode(s);
26
+ while (encoded.length > n) {
23
27
  let k = n;
24
- // Move back to find the start of a UTF-8 character
25
- while ((s.charCodeAt(k) & 0xc0) === 0x80) {
28
+ while (k > 0) {
29
+ const byte = encoded[k];
30
+ if (byte !== undefined && (byte & 0xc0) !== 0x80) {
31
+ break;
32
+ }
26
33
  k--;
27
34
  }
28
- result.push(s.slice(0, k));
29
- s = s.slice(k);
35
+ result.push(encoded.slice(0, k));
36
+ encoded = encoded.slice(k);
37
+ }
38
+ if (encoded.length > 0) {
39
+ result.push(encoded);
30
40
  }
31
- result.push(s);
32
41
  return result;
33
42
  }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const SDK_VERSION = "0.13.4";
1
+ export const SDK_VERSION = "0.13.6";