@livekit/rtc-node 0.13.31 → 0.13.33

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 (120) 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-B4hGVcKz.d.cts → audio_stream-CnODFAmo.d.cts} +26 -0
  8. package/dist/audio_stream.cjs +31 -18
  9. package/dist/audio_stream.cjs.map +1 -1
  10. package/dist/audio_stream.d.cts +1 -1
  11. package/dist/audio_stream.d.ts +61 -18
  12. package/dist/audio_stream.d.ts.map +1 -1
  13. package/dist/data_streams/index.d.ts +4 -3
  14. package/dist/data_streams/stream_reader.d.ts +48 -2
  15. package/dist/data_streams/stream_writer.d.ts +5 -7
  16. package/dist/data_streams/types.d.ts +41 -2
  17. package/dist/e2ee.d.ts +8 -10
  18. package/dist/ffi_client.d.ts +8 -10
  19. package/dist/frame_processor.d.ts +8 -11
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +2 -2
  22. package/dist/index.d.ts +22 -17
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +1 -107
  25. package/dist/log.d.ts +5 -7
  26. package/dist/participant.cjs +7 -2
  27. package/dist/participant.cjs.map +1 -1
  28. package/dist/participant.d.cts +1 -1
  29. package/dist/participant.d.ts +152 -18
  30. package/dist/participant.d.ts.map +1 -1
  31. package/dist/room.cjs +7 -0
  32. package/dist/room.cjs.map +1 -1
  33. package/dist/room.d.cts +2 -2
  34. package/dist/room.d.ts +220 -18
  35. package/dist/room.d.ts.map +1 -1
  36. package/dist/rpc.d.ts +7 -9
  37. package/dist/track.cjs +16 -0
  38. package/dist/track.cjs.map +1 -1
  39. package/dist/track.d.cts +1 -1
  40. package/dist/track.d.ts +67 -18
  41. package/dist/track.d.ts.map +1 -1
  42. package/dist/track_publication.d.cts +1 -1
  43. package/dist/track_publication.d.ts +45 -18
  44. package/dist/transcription.d.ts +3 -4
  45. package/dist/types.d.ts +2 -3
  46. package/dist/utils.d.ts +4 -5
  47. package/dist/version.cjs +1 -1
  48. package/dist/version.cjs.map +1 -1
  49. package/dist/version.d.cts +1 -1
  50. package/dist/version.d.ts +2 -3
  51. package/dist/video_frame.d.ts +4 -5
  52. package/dist/video_source.d.ts +6 -8
  53. package/dist/video_stream.d.cts +1 -1
  54. package/dist/video_stream.d.ts +5 -22
  55. package/package.json +5 -6
  56. package/src/audio_stream.ts +37 -24
  57. package/src/audio_stream_room_lifecycle.test.ts +50 -3
  58. package/src/index.ts +8 -1
  59. package/src/participant.ts +7 -1
  60. package/src/room.ts +14 -0
  61. package/src/tests/e2e.test.ts +137 -16
  62. package/src/track.ts +17 -0
  63. package/src/version.ts +1 -1
  64. package/dist/async_queue.js +0 -56
  65. package/dist/async_queue.js.map +0 -1
  66. package/dist/audio_filter.js +0 -24
  67. package/dist/audio_filter.js.map +0 -1
  68. package/dist/audio_frame.js +0 -78
  69. package/dist/audio_frame.js.map +0 -1
  70. package/dist/audio_mixer.js +0 -269
  71. package/dist/audio_mixer.js.map +0 -1
  72. package/dist/audio_resampler.js +0 -154
  73. package/dist/audio_resampler.js.map +0 -1
  74. package/dist/audio_source.js +0 -134
  75. package/dist/audio_source.js.map +0 -1
  76. package/dist/audio_stream-DEG1JKge.d.ts +0 -498
  77. package/dist/audio_stream.js +0 -109
  78. package/dist/audio_stream.js.map +0 -1
  79. package/dist/data_streams/index.js +0 -3
  80. package/dist/data_streams/index.js.map +0 -1
  81. package/dist/data_streams/stream_reader.js +0 -124
  82. package/dist/data_streams/stream_reader.js.map +0 -1
  83. package/dist/data_streams/stream_writer.js +0 -26
  84. package/dist/data_streams/stream_writer.js.map +0 -1
  85. package/dist/data_streams/types.js +0 -1
  86. package/dist/data_streams/types.js.map +0 -1
  87. package/dist/e2ee.js +0 -251
  88. package/dist/e2ee.js.map +0 -1
  89. package/dist/ffi_client.js +0 -89
  90. package/dist/ffi_client.js.map +0 -1
  91. package/dist/frame_processor.js +0 -29
  92. package/dist/frame_processor.js.map +0 -1
  93. package/dist/index.js.map +0 -1
  94. package/dist/log.js +0 -9
  95. package/dist/log.js.map +0 -1
  96. package/dist/participant.js +0 -715
  97. package/dist/participant.js.map +0 -1
  98. package/dist/room.js +0 -899
  99. package/dist/room.js.map +0 -1
  100. package/dist/rpc.js +0 -65
  101. package/dist/rpc.js.map +0 -1
  102. package/dist/track.js +0 -218
  103. package/dist/track.js.map +0 -1
  104. package/dist/track_publication.js +0 -100
  105. package/dist/track_publication.js.map +0 -1
  106. package/dist/transcription.js +0 -1
  107. package/dist/transcription.js.map +0 -1
  108. package/dist/types-_PdPVish.d.ts +0 -87
  109. package/dist/types.js +0 -1
  110. package/dist/types.js.map +0 -1
  111. package/dist/utils.js +0 -35
  112. package/dist/utils.js.map +0 -1
  113. package/dist/version.js +0 -5
  114. package/dist/version.js.map +0 -1
  115. package/dist/video_frame.js +0 -207
  116. package/dist/video_frame.js.map +0 -1
  117. package/dist/video_source.js +0 -53
  118. package/dist/video_source.js.map +0 -1
  119. package/dist/video_stream.js +0 -70
  120. package/dist/video_stream.js.map +0 -1
@@ -1,715 +0,0 @@
1
- import { Mutex } from "@livekit/mutex";
2
- import {
3
- DisconnectReason,
4
- ParticipantKind
5
- } from "@livekit/rtc-ffi-bindings";
6
- import {
7
- ChatMessage as ChatMessageModel,
8
- DataStream_ByteHeader,
9
- DataStream_Chunk,
10
- DataStream_Header,
11
- DataStream_OperationType,
12
- DataStream_TextHeader,
13
- DataStream_Trailer,
14
- EditChatMessageRequest,
15
- TranscriptionSegment as ProtoTranscriptionSegment,
16
- PublishDataRequest,
17
- PublishSipDtmfRequest,
18
- PublishTrackRequest,
19
- PublishTranscriptionRequest,
20
- SendChatMessageRequest,
21
- SendStreamChunkRequest,
22
- SendStreamHeaderRequest,
23
- SendStreamTrailerRequest,
24
- SetLocalAttributesRequest,
25
- SetLocalMetadataRequest,
26
- SetLocalNameRequest,
27
- UnpublishTrackRequest
28
- } from "@livekit/rtc-ffi-bindings";
29
- import {
30
- PerformRpcRequest,
31
- RegisterRpcMethodRequest,
32
- RpcMethodInvocationResponseRequest,
33
- UnregisterRpcMethodRequest
34
- } from "@livekit/rtc-ffi-bindings";
35
- import { open, stat } from "node:fs/promises";
36
- import {
37
- ByteStreamWriter,
38
- TextStreamWriter
39
- } from "./data_streams/index.js";
40
- import { FfiClient, FfiHandle } from "./ffi_client.js";
41
- import { log } from "./log.js";
42
- import { RpcError } from "./rpc.js";
43
- import { LocalTrackPublication } from "./track_publication.js";
44
- import { numberToBigInt, splitUtf8 } from "./utils.js";
45
- const STREAM_CHUNK_SIZE = 15e3;
46
- class Participant {
47
- constructor(owned_info) {
48
- this.trackPublications = /* @__PURE__ */ new Map();
49
- this.info = owned_info.info;
50
- this.ffi_handle = new FfiHandle(owned_info.handle.id);
51
- }
52
- get sid() {
53
- return this.info.sid;
54
- }
55
- get name() {
56
- return this.info.name;
57
- }
58
- get identity() {
59
- return this.info.identity ?? "";
60
- }
61
- get metadata() {
62
- return this.info.metadata ?? "";
63
- }
64
- get attributes() {
65
- return this.info.attributes ?? {};
66
- }
67
- get kind() {
68
- return this.info.kind ?? ParticipantKind.STANDARD;
69
- }
70
- get kindDetails() {
71
- return this.info.kindDetails ?? [];
72
- }
73
- get disconnectReason() {
74
- if (this.info.disconnectReason === DisconnectReason.UNKNOWN_REASON) {
75
- return void 0;
76
- }
77
- return this.info.disconnectReason;
78
- }
79
- }
80
- class LocalParticipant extends Participant {
81
- constructor(info, ffiEventLock, disconnectSignal) {
82
- super(info);
83
- this.rpcHandlers = /* @__PURE__ */ new Map();
84
- this.trackPublications = /* @__PURE__ */ new Map();
85
- this.sendStreamChunk = async (req) => {
86
- const type = "sendStreamChunk";
87
- const res = FfiClient.instance.request({
88
- message: { case: type, value: req }
89
- });
90
- const cb = await FfiClient.instance.waitFor(
91
- (ev) => ev.message.case == type && ev.message.value.asyncId == res.asyncId,
92
- { signal: this.disconnectSignal }
93
- );
94
- if (cb.error) {
95
- throw new Error(cb.error);
96
- }
97
- };
98
- this.sendStreamTrailer = async (req) => {
99
- const type = "sendStreamTrailer";
100
- const res = FfiClient.instance.request({
101
- message: { case: type, value: req }
102
- });
103
- const cb = await FfiClient.instance.waitFor(
104
- (ev) => ev.message.case == type && ev.message.value.asyncId == res.asyncId,
105
- { signal: this.disconnectSignal }
106
- );
107
- if (cb.error) {
108
- throw new Error(cb.error);
109
- }
110
- };
111
- this.ffiEventLock = ffiEventLock;
112
- this.disconnectSignal = disconnectSignal;
113
- }
114
- async publishData(data, options) {
115
- const req = new PublishDataRequest({
116
- localParticipantHandle: this.ffi_handle.handle,
117
- dataPtr: FfiClient.instance.retrievePtr(data),
118
- dataLen: BigInt(data.byteLength),
119
- reliable: options.reliable,
120
- topic: options.topic,
121
- destinationIdentities: options.destination_identities
122
- });
123
- const res = FfiClient.instance.request({
124
- message: { case: "publishData", value: req }
125
- });
126
- const cb = await FfiClient.instance.waitFor(
127
- (ev) => ev.message.case == "publishData" && ev.message.value.asyncId == res.asyncId,
128
- { signal: this.disconnectSignal }
129
- );
130
- if (cb.error) {
131
- throw new Error(cb.error);
132
- }
133
- }
134
- async publishDtmf(code, digit) {
135
- const req = new PublishSipDtmfRequest({
136
- localParticipantHandle: this.ffi_handle.handle,
137
- code,
138
- digit
139
- });
140
- const res = FfiClient.instance.request({
141
- message: { case: "publishSipDtmf", value: req }
142
- });
143
- const cb = await FfiClient.instance.waitFor(
144
- (ev) => ev.message.case == "publishSipDtmf" && ev.message.value.asyncId == res.asyncId,
145
- { signal: this.disconnectSignal }
146
- );
147
- if (cb.error) {
148
- throw new Error(cb.error);
149
- }
150
- }
151
- async publishTranscription(transcription) {
152
- const req = new PublishTranscriptionRequest({
153
- localParticipantHandle: this.ffi_handle.handle,
154
- participantIdentity: transcription.participantIdentity,
155
- segments: transcription.segments.map(
156
- (s) => new ProtoTranscriptionSegment({
157
- id: s.id,
158
- text: s.text,
159
- startTime: s.startTime,
160
- endTime: s.endTime,
161
- final: s.final,
162
- language: s.language
163
- })
164
- ),
165
- trackId: transcription.trackSid
166
- });
167
- const res = FfiClient.instance.request({
168
- message: { case: "publishTranscription", value: req }
169
- });
170
- const cb = await FfiClient.instance.waitFor(
171
- (ev) => ev.message.case == "publishTranscription" && ev.message.value.asyncId == res.asyncId,
172
- { signal: this.disconnectSignal }
173
- );
174
- if (cb.error) {
175
- throw new Error(cb.error);
176
- }
177
- }
178
- async updateMetadata(metadata) {
179
- const req = new SetLocalMetadataRequest({
180
- localParticipantHandle: this.ffi_handle.handle,
181
- metadata
182
- });
183
- const res = FfiClient.instance.request({
184
- message: { case: "setLocalMetadata", value: req }
185
- });
186
- await FfiClient.instance.waitFor(
187
- (ev) => ev.message.case == "setLocalMetadata" && ev.message.value.asyncId == res.asyncId,
188
- { signal: this.disconnectSignal }
189
- );
190
- }
191
- /**
192
- * Returns a `StreamWriter` instance that allows to write individual chunks of text to a stream.
193
- * Well suited for TTS and/or streaming LLM output. If you want to simply send a text then use sendText() instead
194
- */
195
- async streamText(options) {
196
- const senderIdentity = (options == null ? void 0 : options.senderIdentity) ?? this.identity;
197
- const streamId = (options == null ? void 0 : options.streamId) ?? crypto.randomUUID();
198
- const destinationIdentities = options == null ? void 0 : options.destinationIdentities;
199
- const info = {
200
- streamId,
201
- mimeType: "text/plain",
202
- topic: (options == null ? void 0 : options.topic) ?? "",
203
- timestamp: Date.now()
204
- };
205
- const headerReq = new SendStreamHeaderRequest({
206
- senderIdentity,
207
- destinationIdentities,
208
- localParticipantHandle: this.ffi_handle.handle,
209
- header: new DataStream_Header({
210
- streamId,
211
- mimeType: info.mimeType,
212
- topic: info.topic,
213
- timestamp: numberToBigInt(info.timestamp),
214
- attributes: options == null ? void 0 : options.attributes,
215
- contentHeader: {
216
- case: "textHeader",
217
- value: new DataStream_TextHeader({
218
- operationType: DataStream_OperationType.CREATE,
219
- version: 0,
220
- replyToStreamId: "",
221
- generated: false
222
- })
223
- }
224
- })
225
- });
226
- await this.sendStreamHeader(headerReq);
227
- let nextChunkId = 0;
228
- const localHandle = this.ffi_handle.handle;
229
- const sendTrailer = this.sendStreamTrailer;
230
- const sendChunk = this.sendStreamChunk;
231
- const writableStream = new WritableStream({
232
- // Implement the sink
233
- async write(text) {
234
- for (const textByteChunk of splitUtf8(text, STREAM_CHUNK_SIZE)) {
235
- const chunkRequest = new SendStreamChunkRequest({
236
- senderIdentity,
237
- localParticipantHandle: localHandle,
238
- destinationIdentities,
239
- chunk: new DataStream_Chunk({
240
- content: textByteChunk,
241
- streamId,
242
- chunkIndex: numberToBigInt(nextChunkId)
243
- })
244
- });
245
- await sendChunk(chunkRequest);
246
- nextChunkId += 1;
247
- }
248
- },
249
- async close() {
250
- const trailerReq = new SendStreamTrailerRequest({
251
- senderIdentity,
252
- localParticipantHandle: localHandle,
253
- destinationIdentities,
254
- trailer: new DataStream_Trailer({
255
- streamId,
256
- reason: ""
257
- })
258
- });
259
- await sendTrailer(trailerReq);
260
- },
261
- // Send a trailer with the error reason so the remote side's stream
262
- // controller is closed instead of waiting for data that won't arrive.
263
- async abort(err) {
264
- log.error(err, "Sink Error");
265
- try {
266
- const trailerReq = new SendStreamTrailerRequest({
267
- senderIdentity,
268
- localParticipantHandle: localHandle,
269
- destinationIdentities,
270
- trailer: new DataStream_Trailer({
271
- streamId,
272
- reason: err instanceof Error ? err.message : String(err ?? "")
273
- })
274
- });
275
- await sendTrailer(trailerReq);
276
- } catch {
277
- }
278
- }
279
- });
280
- const writer = new TextStreamWriter(writableStream, info);
281
- return writer;
282
- }
283
- async sendText(text, options) {
284
- const writer = await this.streamText(options);
285
- await writer.write(text);
286
- await writer.close();
287
- return writer.info;
288
- }
289
- async streamBytes(options) {
290
- const senderIdentity = this.identity;
291
- const streamId = (options == null ? void 0 : options.streamId) ?? crypto.randomUUID();
292
- const destinationIdentities = options == null ? void 0 : options.destinationIdentities;
293
- const info = {
294
- streamId,
295
- mimeType: (options == null ? void 0 : options.mimeType) ?? "application/octet-stream",
296
- topic: (options == null ? void 0 : options.topic) ?? "",
297
- timestamp: Date.now(),
298
- attributes: options == null ? void 0 : options.attributes,
299
- totalSize: options == null ? void 0 : options.totalSize,
300
- name: (options == null ? void 0 : options.name) ?? "unknown"
301
- };
302
- const headerReq = new SendStreamHeaderRequest({
303
- senderIdentity,
304
- destinationIdentities,
305
- localParticipantHandle: this.ffi_handle.handle,
306
- header: new DataStream_Header({
307
- streamId,
308
- mimeType: info.mimeType,
309
- topic: info.topic,
310
- timestamp: numberToBigInt(info.timestamp),
311
- attributes: info.attributes,
312
- totalLength: numberToBigInt(info.totalSize),
313
- contentHeader: {
314
- case: "byteHeader",
315
- value: new DataStream_ByteHeader({
316
- name: info.name
317
- })
318
- }
319
- })
320
- });
321
- await this.sendStreamHeader(headerReq);
322
- let chunkId = 0;
323
- const localHandle = this.ffi_handle.handle;
324
- const sendTrailer = this.sendStreamTrailer;
325
- const sendChunk = this.sendStreamChunk;
326
- const writeMutex = new Mutex();
327
- const writableStream = new WritableStream({
328
- async write(chunk) {
329
- const unlock = await writeMutex.lock();
330
- let byteOffset = 0;
331
- try {
332
- while (byteOffset < chunk.byteLength) {
333
- const subChunk = chunk.slice(byteOffset, byteOffset + STREAM_CHUNK_SIZE);
334
- const chunkRequest = new SendStreamChunkRequest({
335
- senderIdentity,
336
- localParticipantHandle: localHandle,
337
- destinationIdentities,
338
- chunk: new DataStream_Chunk({
339
- content: subChunk,
340
- streamId,
341
- chunkIndex: numberToBigInt(chunkId)
342
- })
343
- });
344
- await sendChunk(chunkRequest);
345
- chunkId += 1;
346
- byteOffset += subChunk.byteLength;
347
- }
348
- } finally {
349
- unlock();
350
- }
351
- },
352
- async close() {
353
- const trailerReq = new SendStreamTrailerRequest({
354
- senderIdentity,
355
- localParticipantHandle: localHandle,
356
- destinationIdentities,
357
- trailer: new DataStream_Trailer({
358
- streamId,
359
- reason: ""
360
- })
361
- });
362
- await sendTrailer(trailerReq);
363
- },
364
- // Send a trailer with the error reason so the remote side's stream
365
- // controller is closed instead of waiting for data that won't arrive.
366
- async abort(err) {
367
- log.error(err, "Sink error");
368
- try {
369
- const trailerReq = new SendStreamTrailerRequest({
370
- senderIdentity,
371
- localParticipantHandle: localHandle,
372
- destinationIdentities,
373
- trailer: new DataStream_Trailer({
374
- streamId,
375
- reason: err instanceof Error ? err.message : String(err ?? "")
376
- })
377
- });
378
- await sendTrailer(trailerReq);
379
- } catch {
380
- }
381
- }
382
- });
383
- const byteWriter = new ByteStreamWriter(writableStream, info);
384
- return byteWriter;
385
- }
386
- /** Sends a file provided as PathLike to specified recipients */
387
- async sendFile(path, options) {
388
- const fileStats = await stat(path);
389
- const file = await open(path);
390
- try {
391
- const stream = file.readableWebStream();
392
- const streamId = crypto.randomUUID();
393
- const destinationIdentities = options == null ? void 0 : options.destinationIdentities;
394
- const writer = await this.streamBytes({
395
- streamId,
396
- name: options == null ? void 0 : options.name,
397
- totalSize: fileStats.size,
398
- destinationIdentities,
399
- topic: options == null ? void 0 : options.topic,
400
- mimeType: options == null ? void 0 : options.mimeType,
401
- attributes: options == null ? void 0 : options.attributes
402
- });
403
- for await (const chunk of stream) {
404
- await writer.write(chunk);
405
- }
406
- await writer.close();
407
- } finally {
408
- await file.close();
409
- }
410
- }
411
- async sendStreamHeader(req) {
412
- const type = "sendStreamHeader";
413
- const res = FfiClient.instance.request({
414
- message: { case: type, value: req }
415
- });
416
- const cb = await FfiClient.instance.waitFor(
417
- (ev) => ev.message.case == type && ev.message.value.asyncId == res.asyncId,
418
- { signal: this.disconnectSignal }
419
- );
420
- if (cb.error) {
421
- throw new Error(cb.error);
422
- }
423
- }
424
- /**
425
- * Sends a chat message to participants in the room
426
- *
427
- * @param text - The text content of the chat message.
428
- * @param destinationIdentities - An optional array of recipient identities to whom the message will be sent. If omitted, the message is broadcast to all participants.
429
- * @param senderIdentity - An optional identity of the sender. If omitted, the default sender identity is used.
430
- *
431
- */
432
- async sendChatMessage(text, destinationIdentities, senderIdentity) {
433
- const req = new SendChatMessageRequest({
434
- localParticipantHandle: this.ffi_handle.handle,
435
- message: text,
436
- destinationIdentities,
437
- senderIdentity
438
- });
439
- const res = FfiClient.instance.request({
440
- message: { case: "sendChatMessage", value: req }
441
- });
442
- const cb = await FfiClient.instance.waitFor(
443
- (ev) => ev.message.case == "chatMessage" && ev.message.value.asyncId == res.asyncId,
444
- { signal: this.disconnectSignal }
445
- );
446
- switch (cb.message.case) {
447
- case "chatMessage":
448
- const { id, timestamp, editTimestamp, message } = cb.message.value;
449
- return {
450
- id,
451
- timestamp: Number(timestamp),
452
- editTimestamp: Number(editTimestamp),
453
- message
454
- };
455
- case "error":
456
- default:
457
- throw new Error(cb.message.value);
458
- }
459
- }
460
- /**
461
- * @experimental
462
- */
463
- async editChatMessage(editText, originalMessage, destinationIdentities, senderIdentity) {
464
- const req = new EditChatMessageRequest({
465
- localParticipantHandle: this.ffi_handle.handle,
466
- editText,
467
- originalMessage: new ChatMessageModel({
468
- ...originalMessage,
469
- timestamp: BigInt(originalMessage.timestamp),
470
- editTimestamp: originalMessage.editTimestamp ? BigInt(originalMessage.editTimestamp) : void 0
471
- }),
472
- destinationIdentities,
473
- senderIdentity
474
- });
475
- const res = FfiClient.instance.request({
476
- message: { case: "editChatMessage", value: req }
477
- });
478
- const cb = await FfiClient.instance.waitFor(
479
- (ev) => ev.message.case == "chatMessage" && ev.message.value.asyncId == res.asyncId,
480
- { signal: this.disconnectSignal }
481
- );
482
- switch (cb.message.case) {
483
- case "chatMessage":
484
- const { id, timestamp, editTimestamp, message } = cb.message.value;
485
- return {
486
- id,
487
- timestamp: Number(timestamp),
488
- editTimestamp: Number(editTimestamp),
489
- message
490
- };
491
- case "error":
492
- default:
493
- throw new Error(cb.message.value);
494
- }
495
- }
496
- async updateName(name) {
497
- const req = new SetLocalNameRequest({
498
- localParticipantHandle: this.ffi_handle.handle,
499
- name
500
- });
501
- const res = FfiClient.instance.request({
502
- message: { case: "setLocalName", value: req }
503
- });
504
- await FfiClient.instance.waitFor(
505
- (ev) => ev.message.case == "setLocalName" && ev.message.value.asyncId == res.asyncId,
506
- { signal: this.disconnectSignal }
507
- );
508
- }
509
- async setAttributes(attributes) {
510
- const req = new SetLocalAttributesRequest({
511
- localParticipantHandle: this.ffi_handle.handle,
512
- attributes: Object.entries(attributes).map(([key, value]) => ({ key, value }))
513
- });
514
- const res = FfiClient.instance.request({
515
- message: { case: "setLocalAttributes", value: req }
516
- });
517
- await FfiClient.instance.waitFor(
518
- (ev) => ev.message.case == "setLocalAttributes" && ev.message.value.asyncId == res.asyncId,
519
- { signal: this.disconnectSignal }
520
- );
521
- }
522
- async publishTrack(track, options) {
523
- const req = new PublishTrackRequest({
524
- localParticipantHandle: this.ffi_handle.handle,
525
- trackHandle: track.ffi_handle.handle,
526
- options
527
- });
528
- const unlock = await this.ffiEventLock.lock();
529
- const res = FfiClient.instance.request({
530
- message: { case: "publishTrack", value: req }
531
- });
532
- try {
533
- const cb = await FfiClient.instance.waitFor(
534
- (ev) => ev.message.case == "publishTrack" && ev.message.value.asyncId == res.asyncId,
535
- { signal: this.disconnectSignal }
536
- );
537
- switch (cb.message.case) {
538
- case "publication":
539
- const track_publication = new LocalTrackPublication(cb.message.value);
540
- track_publication.track = track;
541
- if (track.info && track_publication.sid) {
542
- track.info.sid = track_publication.sid;
543
- }
544
- this.trackPublications.set(track_publication.sid, track_publication);
545
- return track_publication;
546
- case "error":
547
- default:
548
- throw new Error(cb.message.value);
549
- }
550
- } finally {
551
- unlock();
552
- }
553
- }
554
- async unpublishTrack(trackSid, stopOnUnpublish) {
555
- const unlock = await this.ffiEventLock.lock();
556
- try {
557
- const req = new UnpublishTrackRequest({
558
- localParticipantHandle: this.ffi_handle.handle,
559
- trackSid,
560
- stopOnUnpublish: stopOnUnpublish ?? true
561
- });
562
- const res = FfiClient.instance.request({
563
- message: { case: "unpublishTrack", value: req }
564
- });
565
- const cb = await FfiClient.instance.waitFor(
566
- (ev) => ev.message.case == "unpublishTrack" && ev.message.value.asyncId == res.asyncId,
567
- { signal: this.disconnectSignal }
568
- );
569
- if (cb.error) {
570
- throw new Error(cb.error);
571
- }
572
- const pub = this.trackPublications.get(trackSid);
573
- if (pub) {
574
- if (pub.track) {
575
- pub.track.setRoom(null);
576
- }
577
- pub.track = void 0;
578
- }
579
- this.trackPublications.delete(trackSid);
580
- } finally {
581
- unlock();
582
- }
583
- }
584
- /**
585
- * Initiate an RPC call to a remote participant.
586
- * @param params - Parameters for initiating the RPC call, see {@link PerformRpcParams}
587
- * @returns A promise that resolves with the response payload or rejects with an error.
588
- * @throws Error on failure. Details in `message`.
589
- */
590
- async performRpc({
591
- destinationIdentity,
592
- method,
593
- payload,
594
- responseTimeout
595
- }) {
596
- const req = new PerformRpcRequest({
597
- localParticipantHandle: this.ffi_handle.handle,
598
- destinationIdentity,
599
- method,
600
- payload,
601
- responseTimeoutMs: responseTimeout
602
- });
603
- const res = FfiClient.instance.request({
604
- message: { case: "performRpc", value: req }
605
- });
606
- const cb = await FfiClient.instance.waitFor(
607
- (ev) => ev.message.case === "performRpc" && ev.message.value.asyncId === res.asyncId,
608
- { signal: this.disconnectSignal }
609
- );
610
- if (cb.error) {
611
- throw RpcError.fromProto(cb.error);
612
- }
613
- return cb.payload;
614
- }
615
- /**
616
- * Establishes the participant as a receiver for calls of the specified RPC method.
617
- * Will overwrite any existing callback for the same method.
618
- *
619
- * @param method - The name of the indicated RPC method
620
- * @param handler - Will be invoked when an RPC request for this method is received
621
- * @returns A promise that resolves when the method is successfully registered
622
- *
623
- * @example
624
- * ```typescript
625
- * room.localParticipant?.registerRpcMethod(
626
- * 'greet',
627
- * async (data: RpcInvocationData) => {
628
- * console.log(`Received greeting from ${data.callerIdentity}: ${data.payload}`);
629
- * return `Hello, ${data.callerIdentity}!`;
630
- * }
631
- * );
632
- * ```
633
- *
634
- * See {@link RpcInvocationData} for more details on invocation params.
635
- *
636
- * The handler should return a Promise that resolves to a string.
637
- * If unable to respond within `responseTimeout`, the request will result in an error on the caller's side.
638
- *
639
- * You may throw errors of type `RpcError` with a string `message` in the handler,
640
- * and they will be received on the caller's side with the message intact.
641
- * Other errors thrown in your handler will not be transmitted as-is, and will instead arrive to the caller as `1500` ("Application Error").
642
- */
643
- registerRpcMethod(method, handler) {
644
- this.rpcHandlers.set(method, handler);
645
- const req = new RegisterRpcMethodRequest({
646
- localParticipantHandle: this.ffi_handle.handle,
647
- method
648
- });
649
- FfiClient.instance.request({
650
- message: { case: "registerRpcMethod", value: req }
651
- });
652
- }
653
- /**
654
- * Unregisters a previously registered RPC method.
655
- *
656
- * @param method - The name of the RPC method to unregister
657
- */
658
- unregisterRpcMethod(method) {
659
- this.rpcHandlers.delete(method);
660
- const req = new UnregisterRpcMethodRequest({
661
- localParticipantHandle: this.ffi_handle.handle,
662
- method
663
- });
664
- FfiClient.instance.request({
665
- message: { case: "unregisterRpcMethod", value: req }
666
- });
667
- }
668
- /** @internal */
669
- async handleRpcMethodInvocation(invocationId, method, requestId, callerIdentity, payload, responseTimeout) {
670
- let responseError = null;
671
- let responsePayload = null;
672
- const handler = this.rpcHandlers.get(method);
673
- if (!handler) {
674
- responseError = RpcError.builtIn("UNSUPPORTED_METHOD");
675
- } else {
676
- try {
677
- responsePayload = await handler({ requestId, callerIdentity, payload, responseTimeout });
678
- } catch (error) {
679
- if (error instanceof RpcError) {
680
- responseError = error;
681
- } else {
682
- console.warn(
683
- `Uncaught error returned by RPC handler for ${method}. Returning APPLICATION_ERROR instead.`,
684
- error
685
- );
686
- responseError = RpcError.builtIn("APPLICATION_ERROR");
687
- }
688
- }
689
- }
690
- const req = new RpcMethodInvocationResponseRequest({
691
- localParticipantHandle: this.ffi_handle.handle,
692
- invocationId,
693
- error: responseError ? responseError.toProto() : void 0,
694
- payload: responsePayload ?? void 0
695
- });
696
- const res = FfiClient.instance.request({
697
- message: { case: "rpcMethodInvocationResponse", value: req }
698
- });
699
- if (res.error) {
700
- console.warn(`error sending rpc method invocation response: ${res.error}`);
701
- }
702
- }
703
- }
704
- class RemoteParticipant extends Participant {
705
- constructor(owned_info) {
706
- super(owned_info);
707
- this.trackPublications = /* @__PURE__ */ new Map();
708
- }
709
- }
710
- export {
711
- LocalParticipant,
712
- Participant,
713
- RemoteParticipant
714
- };
715
- //# sourceMappingURL=participant.js.map