mediasfu-shared 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,103 +1,108 @@
1
- # mediasfu-shared
2
-
3
- `mediasfu-shared` is the framework-agnostic MediaSFU runtime package. It exposes the shared room helpers, mediasoup/socket flows, state utilities, and TypeScript types used by the MediaSFU SDK family.
4
-
5
- ## When To Use This Package
6
-
7
- Use `mediasfu-shared` when you want to:
8
-
9
- - build your own browser client on top of MediaSFU primitives without adopting a framework-specific UI package
10
- - share MediaSFU room, media, and participant logic across React, Vue, Angular, Svelte, or plain TypeScript codebases
11
- - import low-level helpers such as `createRoomOnMediaSFU`, `joinRoomOnMediaSFU`, `connectSocket`, `SocketManager`, and the exported consumers, methods, and types entry points
12
-
13
- ## Installation
14
-
15
- ```bash
16
- npm install mediasfu-shared mediasoup-client socket.io-client
17
- ```
18
-
19
- `mediasoup-client` and `socket.io-client` are peer dependencies, so install them in the host app.
20
-
21
- ## Backend Requirement
22
-
23
- The cloud room helpers in this package target `https://mediasfu.com/v1/rooms/` by default.
24
-
25
- - Use MediaSFU Cloud when you want managed room creation, signaling, and media routing. Pass `apiUserName` and `apiKey`.
26
- - Use MediaSFU Open / Community Edition when you self-host. Pass a non-MediaSFU `localLink` such as `http://localhost:3000`.
27
-
28
- ## Quick Example
29
-
30
- ```ts
31
- import {
32
- SocketManager,
33
- connectSocket,
34
- createRoomOnMediaSFU,
35
- joinRoomOnMediaSFU,
36
- } from 'mediasfu-shared';
37
-
38
- const createResult = await createRoomOnMediaSFU({
39
- payload: {
40
- action: 'create',
41
- userName: 'Ada',
42
- duration: 60,
43
- capacity: 10,
44
- },
45
- apiUserName: 'your-api-username',
46
- apiKey: 'your-64-character-api-key',
47
- });
48
-
49
- const joinResult = await joinRoomOnMediaSFU({
50
- payload: {
51
- action: 'join',
52
- meetingID: 'room123',
53
- userName: 'Ben',
54
- },
55
- apiUserName: 'your-api-username',
56
- apiKey: 'your-64-character-api-key',
57
- });
58
-
59
- const socket = await connectSocket({
60
- apiUserName: 'your-api-username',
61
- apiKey: 'your-64-character-api-key',
62
- apiToken: 'your-api-token',
63
- link: 'https://mediasfu.com/socket',
64
- });
65
-
66
- const socketManager = new SocketManager({ socket });
67
-
68
- console.log(createResult.success, joinResult.success, socketManager.socket.connected);
69
- ```
70
-
71
- ## Import Paths
72
-
73
- - `mediasfu-shared` exposes the full public runtime surface.
74
- - `mediasfu-shared/consumers` is useful when you want consumer/grid helpers only.
75
- - `mediasfu-shared/methods` is useful when you want action utilities and room helpers.
76
- - `mediasfu-shared/types` is useful when you only need TypeScript contracts.
77
-
78
- ## Documentation
79
-
80
- - Main docs: [https://mediasfu.com/documentation](https://mediasfu.com/documentation)
81
- - User guide: [https://mediasfu.com/user-guide](https://mediasfu.com/user-guide)
82
- - MediaSFU Open / CE: [https://github.com/MediaSFU/MediaSFUOpen](https://github.com/MediaSFU/MediaSFUOpen)
83
-
84
- Generate package-local API docs with:
85
-
86
- ```bash
87
- npm run build-docs
88
- ```
89
-
90
- ## Related Packages
91
-
92
- - [mediasfu-reactjs](https://www.npmjs.com/package/mediasfu-reactjs)
93
- - [mediasfu-vue](https://www.npmjs.com/package/mediasfu-vue)
94
- - [mediasfu-angular](https://www.npmjs.com/package/mediasfu-angular)
95
-
96
- ## Support
97
-
98
- - GitHub issues: [https://github.com/MediaSFU/MediaSFU-Shared/issues](https://github.com/MediaSFU/MediaSFU-Shared/issues)
99
- - Email: info@mediasfu.com
100
-
101
- ## License
102
-
103
- MIT. See [LICENSE](LICENSE).
1
+ # mediasfu-shared · [mediasfu-shared on npm](https://www.npmjs.com/package/mediasfu-shared)
2
+
3
+ **mediasfu-shared** is the framework-agnostic WebRTC runtime at the core of the MediaSFU SDK family. It provides shared room helpers, mediasoup signaling, socket management, media state utilities, and TypeScript types for React, Vue, Angular, Svelte, and plain TypeScript. Install with `npm install mediasfu-shared`.
4
+
5
+ `mediasfu-shared` is the framework-agnostic MediaSFU runtime package. It exposes the shared room helpers, mediasoup/socket flows, state utilities, and TypeScript types used by the MediaSFU SDK family.
6
+
7
+ ## When To Use This Package
8
+
9
+ Use `mediasfu-shared` when you want to:
10
+
11
+ - build your own browser client on top of MediaSFU primitives without adopting a framework-specific UI package
12
+ - share MediaSFU room, media, and participant logic across React, Vue, Angular, Svelte, or plain TypeScript codebases
13
+ - import low-level helpers such as `createRoomOnMediaSFU`, `joinRoomOnMediaSFU`, `connectSocket`, `SocketManager`, and the exported consumers, methods, and types entry points
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install mediasfu-shared mediasoup-client socket.io-client
19
+ ```
20
+
21
+ `mediasoup-client` and `socket.io-client` are peer dependencies, so install them in the host app.
22
+
23
+ ## Backend Requirement
24
+
25
+ The cloud room helpers in this package target `https://mediasfu.com/v1/rooms/` by default.
26
+
27
+ - Use MediaSFU Cloud when you want managed room creation, signaling, and media routing. Pass `apiUserName` and `apiKey`.
28
+ - Use MediaSFU Open / Community Edition when you self-host. Pass a non-MediaSFU `localLink` such as `http://localhost:3000`.
29
+
30
+ ## Quick Example
31
+
32
+ ```ts
33
+ import {
34
+ SocketManager,
35
+ connectSocket,
36
+ createRoomOnMediaSFU,
37
+ joinRoomOnMediaSFU,
38
+ } from 'mediasfu-shared';
39
+
40
+ const createResult = await createRoomOnMediaSFU({
41
+ payload: {
42
+ action: 'create',
43
+ userName: 'Ada',
44
+ duration: 60,
45
+ capacity: 10,
46
+ },
47
+ apiUserName: 'your-api-username',
48
+ apiKey: 'your-64-character-api-key',
49
+ });
50
+
51
+ const joinResult = await joinRoomOnMediaSFU({
52
+ payload: {
53
+ action: 'join',
54
+ meetingID: 'room123',
55
+ userName: 'Ben',
56
+ },
57
+ apiUserName: 'your-api-username',
58
+ apiKey: 'your-64-character-api-key',
59
+ });
60
+
61
+ const socket = await connectSocket({
62
+ apiUserName: 'your-api-username',
63
+ apiKey: 'your-64-character-api-key',
64
+ apiToken: 'your-api-token',
65
+ link: 'https://mediasfu.com/socket',
66
+ });
67
+
68
+ const socketManager = new SocketManager({ socket });
69
+
70
+ console.log(createResult.success, joinResult.success, socketManager.socket.connected);
71
+ ```
72
+
73
+ ## Import Paths
74
+
75
+ - `mediasfu-shared` exposes the full public runtime surface.
76
+ - `mediasfu-shared/consumers` is useful when you want consumer/grid helpers only.
77
+ - `mediasfu-shared/methods` is useful when you want action utilities and room helpers.
78
+ - `mediasfu-shared/types` is useful when you only need TypeScript contracts.
79
+
80
+ ## Documentation
81
+
82
+ - Main docs: [https://mediasfu.com/documentation](https://mediasfu.com/documentation)
83
+ - User guide: [https://mediasfu.com/user-guide](https://mediasfu.com/user-guide)
84
+ - MediaSFU Open / CE: [https://github.com/MediaSFU/MediaSFUOpen](https://github.com/MediaSFU/MediaSFUOpen)
85
+
86
+ Generate package-local API docs with:
87
+
88
+ ```bash
89
+ npm run build-docs
90
+ ```
91
+
92
+ ## Related Packages
93
+
94
+ | Package | Framework | npm |
95
+ |---------|-----------|-----|
96
+ | [mediasfu-reactjs](https://github.com/MediaSFU/MediaSFU-ReactJS) | React 18/19 | [`npm install mediasfu-reactjs`](https://www.npmjs.com/package/mediasfu-reactjs) |
97
+ | [mediasfu-vue](https://github.com/MediaSFU/MediaSFU-Vue) | Vue 3 / Composition API | [`npm install mediasfu-vue`](https://www.npmjs.com/package/mediasfu-vue) |
98
+ | [mediasfu-angular](https://github.com/MediaSFU/MediaSFU-Angular) | Angular 17/18/19 | [`npm install mediasfu-angular`](https://www.npmjs.com/package/mediasfu-angular) |
99
+ | [mediasfu-reactnative](https://www.npmjs.com/package/mediasfu-reactnative) | React Native | [`npm install mediasfu-reactnative`](https://www.npmjs.com/package/mediasfu-reactnative) |
100
+
101
+ ## Support
102
+
103
+ - GitHub issues: [https://github.com/MediaSFU/MediaSFU-Shared/issues](https://github.com/MediaSFU/MediaSFU-Shared/issues)
104
+ - Email: info@mediasfu.com
105
+
106
+ ## License
107
+
108
+ MIT. See [LICENSE](LICENSE).
package/dist/index.cjs CHANGED
@@ -1260,13 +1260,15 @@ const connectIps = async ({
1260
1260
  roomRecvIPs.push(ip);
1261
1261
  updateRoomRecvIPs(roomRecvIPs);
1262
1262
  }
1263
- remote_sock.on("new-pipe-producer", async ({ producerId, islevel }) => {
1263
+ remote_sock.on("new-pipe-producer", async ({ producerId, islevel, isTranslation, translationMeta }) => {
1264
1264
  if (newProducerMethod) {
1265
1265
  await newProducerMethod({
1266
1266
  producerId,
1267
1267
  islevel,
1268
1268
  nsock: remote_sock,
1269
- parameters
1269
+ parameters,
1270
+ isTranslation,
1271
+ translationMeta
1270
1272
  });
1271
1273
  }
1272
1274
  });
@@ -1307,13 +1309,15 @@ const connectLocalIps = async ({
1307
1309
  parameters
1308
1310
  }) => {
1309
1311
  try {
1310
- socket.on("new-producer", async ({ producerId, islevel }) => {
1312
+ socket.on("new-producer", async ({ producerId, islevel, isTranslation, translationMeta }) => {
1311
1313
  if (newProducerMethod) {
1312
1314
  await newProducerMethod({
1313
1315
  producerId,
1314
1316
  islevel,
1315
1317
  nsock: socket,
1316
- parameters
1318
+ parameters,
1319
+ isTranslation,
1320
+ translationMeta
1317
1321
  });
1318
1322
  }
1319
1323
  });
@@ -1327,6 +1331,47 @@ const connectLocalIps = async ({
1327
1331
  console.log("ConnectLocalIps error", error);
1328
1332
  }
1329
1333
  };
1334
+ const getSpeakerNameForProducerId$1 = (producerId, parameters) => {
1335
+ const participants = parameters.participants;
1336
+ const participant = participants?.find((candidate) => candidate.audioID === producerId);
1337
+ if (participant?.name) {
1338
+ return participant.name;
1339
+ }
1340
+ const audStreamName = parameters.audStreamNames?.find((stream) => stream.producerId === producerId && typeof stream.name === "string");
1341
+ if (audStreamName?.name) {
1342
+ return audStreamName.name;
1343
+ }
1344
+ return parameters.allAudioStreams?.find((stream) => stream.producerId === producerId && typeof stream.name === "string")?.name;
1345
+ };
1346
+ const isOriginalAudioSuppressedByTranslation$1 = (producerId, parameters) => {
1347
+ const activeTranslationProducerIds = parameters.activeTranslationProducerIds;
1348
+ if (activeTranslationProducerIds?.has(producerId)) {
1349
+ return false;
1350
+ }
1351
+ const speakerTranslationStates = parameters.speakerTranslationStates;
1352
+ if (!speakerTranslationStates?.size) {
1353
+ return false;
1354
+ }
1355
+ const speakerName = getSpeakerNameForProducerId$1(producerId, parameters);
1356
+ if (speakerName) {
1357
+ const speakerState = speakerTranslationStates.get(speakerName);
1358
+ if (speakerState?.enabled) {
1359
+ return true;
1360
+ }
1361
+ }
1362
+ return Array.from(speakerTranslationStates.values()).some((speakerState) => {
1363
+ if (!speakerState?.enabled) {
1364
+ return false;
1365
+ }
1366
+ if (speakerState.originalProducerId === producerId) {
1367
+ return true;
1368
+ }
1369
+ if (!speakerName) {
1370
+ return false;
1371
+ }
1372
+ return speakerState.speakerId === speakerName || speakerState.speakerName === speakerName;
1373
+ });
1374
+ };
1330
1375
  const connectRecvTransport = async ({
1331
1376
  consumerTransport,
1332
1377
  remoteProducerId,
@@ -1388,24 +1433,15 @@ const connectRecvTransport = async ({
1388
1433
  if (params.kind === "audio") {
1389
1434
  try {
1390
1435
  const updatedParams = parameters.getUpdatedAllParams();
1391
- const speakerTranslationStates = updatedParams.speakerTranslationStates;
1392
- const participants = updatedParams.participants;
1393
- if (speakerTranslationStates && speakerTranslationStates.size > 0 && participants?.length) {
1394
- const participant = participants.find(
1395
- (candidate) => candidate.audioID === remoteProducerId
1396
- );
1397
- if (participant?.name) {
1398
- const speakerState = speakerTranslationStates.get(participant.name);
1399
- if (speakerState?.enabled && speakerState.originalProducerId === remoteProducerId) {
1400
- consumer.pause();
1401
- nsock.emit(
1402
- "consumer-pause",
1403
- { serverConsumerId: params.serverConsumerId },
1404
- () => {
1405
- }
1406
- );
1436
+ if (isOriginalAudioSuppressedByTranslation$1(remoteProducerId, updatedParams)) {
1437
+ consumer.pause();
1438
+ nsock.emit(
1439
+ "consumer-pause",
1440
+ { serverConsumerId: params.serverConsumerId },
1441
+ () => {
1407
1442
  }
1408
- }
1443
+ );
1444
+ return;
1409
1445
  }
1410
1446
  } catch {
1411
1447
  }
@@ -2666,6 +2702,50 @@ async function processConsumerTransports({
2666
2702
  const getProducerId$1 = (value) => {
2667
2703
  return value?.producerId;
2668
2704
  };
2705
+ const getSpeakerNameForProducerId = (producerId, parameters) => {
2706
+ const participants = parameters.participants;
2707
+ const participant = participants?.find((candidate) => candidate.audioID === producerId);
2708
+ if (participant?.name) {
2709
+ return participant.name;
2710
+ }
2711
+ const audStreamName = parameters.audStreamNames?.find((stream) => stream.producerId === producerId && typeof stream.name === "string");
2712
+ if (audStreamName?.name) {
2713
+ return audStreamName.name;
2714
+ }
2715
+ return parameters.allAudioStreams?.find((stream) => stream.producerId === producerId && typeof stream.name === "string")?.name;
2716
+ };
2717
+ const isOriginalAudioSuppressedByTranslation = (producerId, parameters) => {
2718
+ if (!producerId) {
2719
+ return false;
2720
+ }
2721
+ const activeTranslationProducerIds = parameters.activeTranslationProducerIds;
2722
+ if (activeTranslationProducerIds?.has(producerId)) {
2723
+ return false;
2724
+ }
2725
+ const speakerTranslationStates = parameters.speakerTranslationStates;
2726
+ if (!speakerTranslationStates?.size) {
2727
+ return false;
2728
+ }
2729
+ const speakerName = getSpeakerNameForProducerId(producerId, parameters);
2730
+ if (speakerName) {
2731
+ const speakerState = speakerTranslationStates.get(speakerName);
2732
+ if (speakerState?.enabled) {
2733
+ return true;
2734
+ }
2735
+ }
2736
+ return Array.from(speakerTranslationStates.values()).some((speakerState) => {
2737
+ if (!speakerState?.enabled) {
2738
+ return false;
2739
+ }
2740
+ if (speakerState.originalProducerId === producerId) {
2741
+ return true;
2742
+ }
2743
+ if (!speakerName) {
2744
+ return false;
2745
+ }
2746
+ return speakerState.speakerId === speakerName || speakerState.speakerName === speakerName;
2747
+ });
2748
+ };
2669
2749
  const processConsumerTransportsAudio = async ({
2670
2750
  consumerTransports,
2671
2751
  lStreams,
@@ -2679,12 +2759,12 @@ const processConsumerTransportsAudio = async ({
2679
2759
  });
2680
2760
  };
2681
2761
  const consumerTransportsToResume = consumerTransports.filter(
2682
- (transport) => isValidProducerId(transport.producerId, lStreams) && transport.consumer?.paused === true && transport.consumer?.kind === "audio"
2762
+ (transport) => isValidProducerId(transport.producerId, lStreams) && !isOriginalAudioSuppressedByTranslation(transport.producerId, parameters) && transport.consumer?.paused === true && transport.consumer?.kind === "audio"
2683
2763
  );
2684
2764
  const consumerTransportsToPause = consumerTransports.filter(
2685
- (transport) => transport.producerId && transport.producerId !== null && transport.producerId !== "" && !lStreams.some(
2765
+ (transport) => transport.producerId && transport.producerId !== null && transport.producerId !== "" && (isOriginalAudioSuppressedByTranslation(transport.producerId, parameters) || !lStreams.some(
2686
2766
  (stream) => getProducerId$1(stream) === transport.producerId
2687
- ) && transport.consumer && transport.consumer?.kind && transport.consumer.paused !== true && transport.consumer.kind === "audio"
2767
+ )) && transport.consumer && transport.consumer?.kind && transport.consumer.paused !== true && transport.consumer.kind === "audio"
2688
2768
  );
2689
2769
  await sleep2({ ms: 100 });
2690
2770
  for (const transport of consumerTransportsToPause) {
@@ -2697,6 +2777,9 @@ const processConsumerTransportsAudio = async ({
2697
2777
  );
2698
2778
  }
2699
2779
  for (const transport of consumerTransportsToResume) {
2780
+ if (isOriginalAudioSuppressedByTranslation(transport.producerId, parameters)) {
2781
+ continue;
2782
+ }
2700
2783
  transport.socket_.emit(
2701
2784
  "consumer-resume",
2702
2785
  { serverConsumerId: transport.serverConsumerTransportId },
@@ -4152,7 +4235,9 @@ const clickVideo = async ({ parameters }) => {
4152
4235
  audioSetting,
4153
4236
  videoSetting,
4154
4237
  screenshareSetting,
4155
- chatSetting
4238
+ chatSetting,
4239
+ permissionConfig: parameters.permissionConfig,
4240
+ participantLevel: islevel
4156
4241
  });
4157
4242
  } else {
4158
4243
  response = 0;
@@ -5307,11 +5392,17 @@ const hostRequestResponse = async ({
5307
5392
  updateChatRequestTime,
5308
5393
  updateRequestIntervalSeconds
5309
5394
  }) => {
5395
+ const requestType = requestResponse.type ?? requestResponse.icon;
5310
5396
  const filteredRequests = requestList.filter(
5311
- (request) => request.id !== requestResponse.id && request.icon !== requestResponse.type && request.name !== requestResponse.name && request.username !== requestResponse.username
5397
+ (request) => {
5398
+ const matchesId = request.id === requestResponse.id;
5399
+ const matchesType = requestType == null || request.icon === requestType;
5400
+ const matchesName = requestResponse.name == null || request.name === requestResponse.name;
5401
+ const matchesUsername = requestResponse.username == null || request.username === requestResponse.username;
5402
+ return !(matchesId && matchesType && matchesName && matchesUsername);
5403
+ }
5312
5404
  );
5313
5405
  updateRequestList(filteredRequests);
5314
- const requestType = requestResponse.type;
5315
5406
  if (requestResponse.action === "accepted") {
5316
5407
  switch (requestType) {
5317
5408
  case "fa-microphone":
@@ -6277,11 +6368,20 @@ const updateRoomParametersClient = ({ parameters }) => {
6277
6368
  }
6278
6369
  };
6279
6370
  const DEFAULT_MEDIA_SFU_ROOM_API_URL = "https://mediasfu.com/v1/rooms/";
6371
+ const normalizeManagedRoomApi = (normalizedLink) => {
6372
+ if (normalizedLink.includes("/v1/rooms")) {
6373
+ return `${normalizedLink.replace(/\/$/, "")}/`;
6374
+ }
6375
+ return `${normalizedLink.replace(/\/$/, "")}/v1/rooms/`;
6376
+ };
6280
6377
  const resolveMediaSFURoomApi = (localLink, action) => {
6281
6378
  const normalizedLink = localLink?.trim();
6282
- if (!normalizedLink || normalizedLink.includes("mediasfu.com")) {
6379
+ if (!normalizedLink) {
6283
6380
  return DEFAULT_MEDIA_SFU_ROOM_API_URL;
6284
6381
  }
6382
+ if (normalizedLink.includes("mediasfu.com")) {
6383
+ return normalizeManagedRoomApi(normalizedLink);
6384
+ }
6285
6385
  return `${normalizedLink.replace(/\/$/, "")}/${action}`;
6286
6386
  };
6287
6387
  const readResponseError$1 = async (response) => {
@@ -7355,15 +7455,22 @@ const pauseOriginalProducer = async ({
7355
7455
  const transport = consumerTransports.find(
7356
7456
  (t) => t.producerId === originalProducerId && t.consumer?.kind === "audio"
7357
7457
  );
7358
- if (transport && transport.consumer && !transport.consumer.paused) {
7359
- transport.consumer.pause();
7360
- transport.socket_?.emit(
7361
- "consumer-pause",
7362
- { serverConsumerId: transport.serverConsumerTransportId },
7363
- async () => {
7364
- }
7365
- );
7458
+ if (!transport?.consumer) {
7459
+ return;
7460
+ }
7461
+ if (transport.consumer.track) {
7462
+ transport.consumer.track.enabled = false;
7463
+ }
7464
+ if (transport.consumer.paused) {
7465
+ return;
7366
7466
  }
7467
+ transport.consumer.pause();
7468
+ transport.socket_?.emit(
7469
+ "consumer-pause",
7470
+ { serverConsumerId: transport.serverConsumerTransportId },
7471
+ async () => {
7472
+ }
7473
+ );
7367
7474
  } catch (error) {
7368
7475
  console.error("[TranslationSwitch] Error pausing original producer:", error);
7369
7476
  }
@@ -7381,17 +7488,27 @@ const resumeOriginalProducer = async ({
7381
7488
  const transport = consumerTransports.find(
7382
7489
  (t) => t.producerId === originalProducerId && t.consumer?.kind === "audio"
7383
7490
  );
7384
- if (transport && transport.consumer && transport.consumer.paused) {
7385
- transport.socket_?.emit(
7386
- "consumer-resume",
7387
- { serverConsumerId: transport.serverConsumerTransportId },
7388
- async ({ resumed }) => {
7389
- if (resumed) {
7390
- transport.consumer.resume();
7491
+ if (!transport?.consumer) {
7492
+ return;
7493
+ }
7494
+ if (!transport.consumer.paused) {
7495
+ if (transport.consumer.track) {
7496
+ transport.consumer.track.enabled = true;
7497
+ }
7498
+ return;
7499
+ }
7500
+ transport.socket_?.emit(
7501
+ "consumer-resume",
7502
+ { serverConsumerId: transport.serverConsumerTransportId },
7503
+ async ({ resumed }) => {
7504
+ if (resumed) {
7505
+ if (transport.consumer.track) {
7506
+ transport.consumer.track.enabled = true;
7391
7507
  }
7508
+ transport.consumer.resume();
7392
7509
  }
7393
- );
7394
- }
7510
+ }
7511
+ );
7395
7512
  } catch (error) {
7396
7513
  console.error("[TranslationSwitch] Error resuming original producer:", error);
7397
7514
  }
@@ -12238,7 +12355,7 @@ const translationSubscribed = async ({
12238
12355
  }));
12239
12356
  }
12240
12357
  if (producerId && startConsumingTranslation) {
12241
- await startConsumingTranslation(producerId, speakerId, language);
12358
+ await startConsumingTranslation(producerId, speakerId, language, originalProducerId);
12242
12359
  }
12243
12360
  if (showAlert && channelCreated) {
12244
12361
  showAlert({