mediasfu-shared 1.2.7 → 1.3.1
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/CHANGELOG.md +17 -0
- package/dist/ProducerClient/producerClientEmits/updateRoomParametersClient.d.ts +2 -0
- package/dist/ProducerClient/producerClientEmits/updateRoomParametersClient.d.ts.map +1 -1
- package/dist/audioProcessing-Ca5wm1nV.js +150 -0
- package/dist/audioProcessing-Ca5wm1nV.js.map +1 -0
- package/dist/audioProcessing-VCbu70Jt.cjs +149 -0
- package/dist/audioProcessing-VCbu70Jt.cjs.map +1 -0
- package/dist/consumers/closeAndResize.d.ts +3 -0
- package/dist/consumers/closeAndResize.d.ts.map +1 -1
- package/dist/consumers/connectIps.d.ts +6 -0
- package/dist/consumers/connectIps.d.ts.map +1 -1
- package/dist/consumers/connectSendTransportAudio.d.ts.map +1 -1
- package/dist/consumers/connectSendTransportScreen.d.ts.map +1 -1
- package/dist/consumers/connectSendTransportScreenAudio.d.ts +65 -0
- package/dist/consumers/connectSendTransportScreenAudio.d.ts.map +1 -0
- package/dist/consumers/connectSendTransportVideo.d.ts.map +1 -1
- package/dist/consumers/consumerBackupPreference.d.ts +14 -0
- package/dist/consumers/consumerBackupPreference.d.ts.map +1 -0
- package/dist/consumers/createSendTransport.d.ts +4 -48
- package/dist/consumers/createSendTransport.d.ts.map +1 -1
- package/dist/consumers/disconnectSendTransportScreen.d.ts.map +1 -1
- package/dist/consumers/getPipedProducersAlt.d.ts.map +1 -1
- package/dist/consumers/index.cjs +23 -1
- package/dist/consumers/index.cjs.map +1 -1
- package/dist/consumers/index.d.ts +3 -0
- package/dist/consumers/index.d.ts.map +1 -1
- package/dist/consumers/index.js +61 -39
- package/dist/consumers/index.js.map +1 -1
- package/dist/consumers/screenAudio.d.ts +64 -0
- package/dist/consumers/screenAudio.d.ts.map +1 -0
- package/dist/consumers/sendTransportGuard.d.ts +30 -0
- package/dist/consumers/sendTransportGuard.d.ts.map +1 -0
- package/dist/consumers/socketReceiveMethods/producerClosed.d.ts.map +1 -1
- package/dist/consumers/startShareScreen.d.ts +14 -0
- package/dist/consumers/startShareScreen.d.ts.map +1 -1
- package/dist/consumers/streamSuccessScreen.d.ts.map +1 -1
- package/dist/{getParticipantMedia-DTZg8n5U.js → getParticipantMedia-CZbsFBth.js} +4 -4
- package/dist/{getParticipantMedia-DTZg8n5U.js.map → getParticipantMedia-CZbsFBth.js.map} +1 -1
- package/dist/{getParticipantMedia-c2bbdT5f.cjs → getParticipantMedia-Dli4dOLp.cjs} +4 -4
- package/dist/{getParticipantMedia-c2bbdT5f.cjs.map → getParticipantMedia-Dli4dOLp.cjs.map} +1 -1
- package/dist/index.cjs +37 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1525 -1494
- package/dist/index.native.cjs +37 -6
- package/dist/index.native.cjs.map +1 -1
- package/dist/index.native.d.ts +4 -0
- package/dist/index.native.d.ts.map +1 -1
- package/dist/index.native.js +107 -76
- package/dist/{joinLocalRoom-1dRd2PCN.js → joinLocalRoom-BWoS-8wt.js} +6 -4
- package/dist/joinLocalRoom-BWoS-8wt.js.map +1 -0
- package/dist/{joinLocalRoom-DwY-3ZsH.cjs → joinLocalRoom-DQvud99t.cjs} +6 -4
- package/dist/joinLocalRoom-DQvud99t.cjs.map +1 -0
- package/dist/{joinRoomOnMediaSFU-BnAWLciF.js → joinRoomOnMediaSFU-B6tTA0Mx.js} +17 -13
- package/dist/joinRoomOnMediaSFU-B6tTA0Mx.js.map +1 -0
- package/dist/{joinRoomOnMediaSFU-D2C7q1GK.cjs → joinRoomOnMediaSFU-CxwD9fBz.cjs} +17 -13
- package/dist/joinRoomOnMediaSFU-CxwD9fBz.cjs.map +1 -0
- package/dist/methods/index.cjs +11 -8
- package/dist/methods/index.cjs.map +1 -1
- package/dist/methods/index.js +13 -9
- package/dist/methods/index.js.map +1 -1
- package/dist/methods/socketReceive/getDomains.d.ts.map +1 -1
- package/dist/methods/utils/checkLimitsAndMakeRequest.d.ts.map +1 -1
- package/dist/methods/welcome/handleWelcomeRequest.d.ts.map +1 -1
- package/dist/sockets/SocketManager.d.ts +7 -0
- package/dist/sockets/SocketManager.d.ts.map +1 -1
- package/dist/sockets/mediaSocketErrors.d.ts +62 -0
- package/dist/sockets/mediaSocketErrors.d.ts.map +1 -0
- package/dist/types/index.cjs +4 -3
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.js +39 -38
- package/dist/types/shared-base-types.d.ts +4 -0
- package/dist/types/shared-base-types.d.ts.map +1 -1
- package/dist/{updateParticipantAudioDecibels-BJ2PxJJD.cjs → updateParticipantAudioDecibels-CbCP1PDs.cjs} +467 -89
- package/dist/updateParticipantAudioDecibels-CbCP1PDs.cjs.map +1 -0
- package/dist/{updateParticipantAudioDecibels-DiJ_LFfH.js → updateParticipantAudioDecibels-xKKq7Zp5.js} +505 -127
- package/dist/updateParticipantAudioDecibels-xKKq7Zp5.js.map +1 -0
- package/package.json +3 -2
- package/src/ProducerClient/producerClientEmits/updateRoomParametersClient.ts +4 -0
- package/src/consumers/closeAndResize.ts +14 -0
- package/src/consumers/connectIps.ts +81 -8
- package/src/consumers/connectSendTransportAudio.ts +7 -4
- package/src/consumers/connectSendTransportScreen.ts +6 -4
- package/src/consumers/connectSendTransportScreenAudio.ts +184 -0
- package/src/consumers/connectSendTransportVideo.ts +4 -2
- package/src/consumers/consumerBackupPreference.ts +43 -0
- package/src/consumers/createSendTransport.ts +62 -4
- package/src/consumers/disconnectSendTransportScreen.ts +8 -0
- package/src/consumers/getPipedProducersAlt.ts +4 -0
- package/src/consumers/index.ts +3 -0
- package/src/consumers/screenAudio.ts +132 -0
- package/src/consumers/sendTransportGuard.ts +65 -0
- package/src/consumers/socketReceiveMethods/producerClosed.ts +3 -0
- package/src/consumers/startShareScreen.ts +44 -8
- package/src/consumers/streamSuccessScreen.ts +11 -0
- package/src/index.native.ts +4 -0
- package/src/index.ts +4 -0
- package/src/methods/socketReceive/getDomains.ts +4 -0
- package/src/methods/utils/checkLimitsAndMakeRequest.ts +24 -11
- package/src/methods/welcome/handleWelcomeRequest.ts +15 -6
- package/src/sockets/SocketManager.ts +107 -13
- package/src/sockets/mediaSocketErrors.ts +156 -0
- package/src/types/shared-base-types.ts +4 -0
- package/dist/audioProcessing-0z5KlcmO.js +0 -35
- package/dist/audioProcessing-0z5KlcmO.js.map +0 -1
- package/dist/audioProcessing-BpbrdCk-.cjs +0 -34
- package/dist/audioProcessing-BpbrdCk-.cjs.map +0 -1
- package/dist/joinLocalRoom-1dRd2PCN.js.map +0 -1
- package/dist/joinLocalRoom-DwY-3ZsH.cjs.map +0 -1
- package/dist/joinRoomOnMediaSFU-BnAWLciF.js.map +0 -1
- package/dist/joinRoomOnMediaSFU-D2C7q1GK.cjs.map +0 -1
- package/dist/updateParticipantAudioDecibels-BJ2PxJJD.cjs.map +0 -1
- package/dist/updateParticipantAudioDecibels-DiJ_LFfH.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import io from "socket.io-client";
|
|
2
|
-
import { v as validateAlphanumeric,
|
|
2
|
+
import { a as MediaSocketConnectError, b as currentOnlineState, n as normalizeRejectionReason, v as validateAlphanumeric, c as consumerBackupPreferDelay, i as isMediaSocketConnectError, k as audioProcessingConstraints } from "./audioProcessing-Ca5wm1nV.js";
|
|
3
3
|
const createFrameworkConsumerContractError = (consumerName) => {
|
|
4
4
|
return new Error(
|
|
5
5
|
`${consumerName} is a render-coupled consumer helper and has no shared runtime implementation. Inject the framework-specific ${consumerName} implementation instead of calling the shared fallback export.`
|
|
@@ -506,6 +506,7 @@ const closeAndResize = async ({ producerId, kind, parameters }) => {
|
|
|
506
506
|
parameters = getUpdatedAllParams();
|
|
507
507
|
let {
|
|
508
508
|
allAudioStreams,
|
|
509
|
+
audioOnlyStreams = [],
|
|
509
510
|
allVideoStreams,
|
|
510
511
|
activeNames,
|
|
511
512
|
participants,
|
|
@@ -530,6 +531,7 @@ const closeAndResize = async ({ producerId, kind, parameters }) => {
|
|
|
530
531
|
updateMainWindow,
|
|
531
532
|
updateActiveNames,
|
|
532
533
|
updateAllAudioStreams,
|
|
534
|
+
updateAudioOnlyStreams,
|
|
533
535
|
updateAllVideoStreams,
|
|
534
536
|
updateShareScreenStarted,
|
|
535
537
|
updateUpdateMainWindow,
|
|
@@ -553,6 +555,11 @@ const closeAndResize = async ({ producerId, kind, parameters }) => {
|
|
|
553
555
|
return audioStream.producerId !== producerId;
|
|
554
556
|
});
|
|
555
557
|
updateAllAudioStreams(allAudioStreams);
|
|
558
|
+
const playerProducerId = (element) => String(element?.props?.remoteProducerId ?? element?.inputs?.remoteProducerId ?? element?.key ?? "");
|
|
559
|
+
if (audioOnlyStreams.some((element) => playerProducerId(element) === producerId)) {
|
|
560
|
+
audioOnlyStreams = audioOnlyStreams.filter((element) => playerProducerId(element) !== producerId);
|
|
561
|
+
updateAudioOnlyStreams?.(audioOnlyStreams);
|
|
562
|
+
}
|
|
556
563
|
if (recordingDisplayType == "video" && recordingVideoOptimized == true) ;
|
|
557
564
|
else {
|
|
558
565
|
participant = participants.find(
|
|
@@ -759,6 +766,24 @@ async function compareScreenStates({
|
|
|
759
766
|
console.log("compareScreenStates error", error);
|
|
760
767
|
}
|
|
761
768
|
}
|
|
769
|
+
function stopReconnectingWhenRefused(socket) {
|
|
770
|
+
const onRejected = (payload) => {
|
|
771
|
+
const refusal = new MediaSocketConnectError({
|
|
772
|
+
phase: "rejected",
|
|
773
|
+
reason: normalizeRejectionReason(payload?.reason),
|
|
774
|
+
stage: typeof payload?.stage === "string" ? payload.stage : void 0,
|
|
775
|
+
elapsedMs: 0
|
|
776
|
+
});
|
|
777
|
+
if (refusal.retryable) return;
|
|
778
|
+
socket.off("connection-rejected", onRejected);
|
|
779
|
+
console.warn(`MediaSFU media socket: reconnect refused (${refusal.reason}); not retrying.`);
|
|
780
|
+
try {
|
|
781
|
+
socket.disconnect();
|
|
782
|
+
} catch {
|
|
783
|
+
}
|
|
784
|
+
};
|
|
785
|
+
socket.on("connection-rejected", onRejected);
|
|
786
|
+
}
|
|
762
787
|
async function validateApiKeyToken(value) {
|
|
763
788
|
if (!/^[a-z0-9]{64}$/i.test(value)) {
|
|
764
789
|
throw new Error("Invalid API key or token.");
|
|
@@ -811,12 +836,26 @@ async function connectSocket({ apiUserName, apiKey, apiToken, link }) {
|
|
|
811
836
|
}
|
|
812
837
|
let settled = false;
|
|
813
838
|
let timeoutHandle;
|
|
839
|
+
const startedAt = Date.now();
|
|
840
|
+
let transportOpened = false;
|
|
841
|
+
let rejection = null;
|
|
814
842
|
const cleanupHandshake = () => {
|
|
815
843
|
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
816
844
|
socket.off("connection-success", handleConnectionSuccess);
|
|
817
845
|
socket.off("connect_error", handleConnectError);
|
|
818
846
|
socket.off("disconnect", handleDisconnectBeforeReady);
|
|
847
|
+
socket.off("connect", handleTransportOpen);
|
|
848
|
+
socket.off("connection-rejected", handleConnectionRejected);
|
|
819
849
|
};
|
|
850
|
+
const failure = (phase, transportError) => new MediaSocketConnectError({
|
|
851
|
+
phase: rejection ? "rejected" : phase,
|
|
852
|
+
reason: rejection?.reason,
|
|
853
|
+
stage: rejection?.stage,
|
|
854
|
+
elapsedMs: Date.now() - startedAt,
|
|
855
|
+
online: currentOnlineState(),
|
|
856
|
+
transportError,
|
|
857
|
+
link
|
|
858
|
+
});
|
|
820
859
|
const settle = (action) => {
|
|
821
860
|
if (settled) return;
|
|
822
861
|
settled = true;
|
|
@@ -832,33 +871,48 @@ async function connectSocket({ apiUserName, apiKey, apiToken, link }) {
|
|
|
832
871
|
} catch {
|
|
833
872
|
}
|
|
834
873
|
console.log(`Connected to ${conn} socket with ID: ${socketId}`);
|
|
835
|
-
settle(() =>
|
|
874
|
+
settle(() => {
|
|
875
|
+
stopReconnectingWhenRefused(socket);
|
|
876
|
+
resolve(socket);
|
|
877
|
+
});
|
|
836
878
|
};
|
|
837
879
|
const handleConnectError = (error) => {
|
|
838
880
|
settle(() => {
|
|
839
881
|
socket.disconnect();
|
|
840
|
-
reject(
|
|
882
|
+
reject(failure(transportOpened ? "after-open" : "before-open", error?.message));
|
|
883
|
+
});
|
|
884
|
+
};
|
|
885
|
+
const handleTransportOpen = () => {
|
|
886
|
+
transportOpened = true;
|
|
887
|
+
};
|
|
888
|
+
const handleConnectionRejected = (payload) => {
|
|
889
|
+
rejection = {
|
|
890
|
+
reason: normalizeRejectionReason(payload?.reason),
|
|
891
|
+
stage: typeof payload?.stage === "string" ? payload.stage : void 0
|
|
892
|
+
};
|
|
893
|
+
settle(() => {
|
|
894
|
+
try {
|
|
895
|
+
socket.disconnect();
|
|
896
|
+
} catch {
|
|
897
|
+
}
|
|
898
|
+
reject(failure("rejected"));
|
|
841
899
|
});
|
|
842
900
|
};
|
|
843
901
|
const handleDisconnectBeforeReady = (reason) => {
|
|
844
|
-
settle(
|
|
845
|
-
() => reject(
|
|
846
|
-
new Error(
|
|
847
|
-
"Media socket closed before the room was ready (" + reason + ")."
|
|
848
|
-
)
|
|
849
|
-
)
|
|
850
|
-
);
|
|
902
|
+
settle(() => reject(failure("after-open", reason)));
|
|
851
903
|
};
|
|
852
904
|
socket.on("connection-success", handleConnectionSuccess);
|
|
853
905
|
socket.on("connect_error", handleConnectError);
|
|
854
906
|
socket.on("disconnect", handleDisconnectBeforeReady);
|
|
907
|
+
socket.on("connect", handleTransportOpen);
|
|
908
|
+
socket.on("connection-rejected", handleConnectionRejected);
|
|
855
909
|
timeoutHandle = setTimeout(() => {
|
|
856
910
|
settle(() => {
|
|
857
911
|
try {
|
|
858
912
|
socket.disconnect();
|
|
859
913
|
} catch {
|
|
860
914
|
}
|
|
861
|
-
reject(
|
|
915
|
+
reject(failure("timeout"));
|
|
862
916
|
});
|
|
863
917
|
}, CONNECT_TIMEOUT_MS);
|
|
864
918
|
});
|
|
@@ -872,11 +926,24 @@ async function connectLocalSocket({ link }) {
|
|
|
872
926
|
socket = io(`${link}/media`, {
|
|
873
927
|
transports: ["websocket"]
|
|
874
928
|
});
|
|
929
|
+
const startedAt = Date.now();
|
|
930
|
+
let transportOpened = false;
|
|
931
|
+
socket.on("connect", () => {
|
|
932
|
+
transportOpened = true;
|
|
933
|
+
});
|
|
875
934
|
socket.on("connection-success", (data) => {
|
|
876
935
|
resolve({ socket, data });
|
|
877
936
|
});
|
|
878
937
|
socket.on("connect_error", (error) => {
|
|
879
|
-
reject(
|
|
938
|
+
reject(
|
|
939
|
+
new MediaSocketConnectError({
|
|
940
|
+
phase: transportOpened ? "after-open" : "before-open",
|
|
941
|
+
elapsedMs: Date.now() - startedAt,
|
|
942
|
+
online: currentOnlineState(),
|
|
943
|
+
transportError: error?.message,
|
|
944
|
+
link
|
|
945
|
+
})
|
|
946
|
+
);
|
|
880
947
|
});
|
|
881
948
|
});
|
|
882
949
|
}
|
|
@@ -1245,11 +1312,72 @@ const newPipeProducer = async ({
|
|
|
1245
1312
|
updateFirst_round(updatedFirstRound);
|
|
1246
1313
|
}
|
|
1247
1314
|
};
|
|
1315
|
+
const SCREEN_AUDIO_MEDIA_TAG = "screen-audio";
|
|
1316
|
+
const SCREEN_AUDIO_CODEC_OPTIONS = {
|
|
1317
|
+
opusStereo: true,
|
|
1318
|
+
opusDtx: false,
|
|
1319
|
+
opusFec: true,
|
|
1320
|
+
opusMaxAverageBitrate: 128e3
|
|
1321
|
+
};
|
|
1322
|
+
const screenAudioProducerIds = /* @__PURE__ */ new Set();
|
|
1323
|
+
const markScreenAudioProducer = (producerId, mediaTag) => {
|
|
1324
|
+
if (producerId && mediaTag === SCREEN_AUDIO_MEDIA_TAG) screenAudioProducerIds.add(producerId);
|
|
1325
|
+
};
|
|
1326
|
+
const forgetScreenAudioProducer = (producerId) => {
|
|
1327
|
+
if (producerId) screenAudioProducerIds.delete(producerId);
|
|
1328
|
+
};
|
|
1329
|
+
const isScreenAudioProducer = ({ producerId, participants = [], appData }) => {
|
|
1330
|
+
if (!producerId) return false;
|
|
1331
|
+
if (screenAudioProducerIds.has(producerId)) return true;
|
|
1332
|
+
if (appData?.mediaTag === SCREEN_AUDIO_MEDIA_TAG) return true;
|
|
1333
|
+
return participants.some((participant) => participant?.ScreenAudioID === producerId);
|
|
1334
|
+
};
|
|
1335
|
+
const shouldShareScreenAudio = ({ supportsScreenAudio, screenAudioEnabled, screenAudioMode }) => supportsScreenAudio === true && screenAudioEnabled !== false && screenAudioMode !== "never";
|
|
1336
|
+
const canCaptureDisplayAudio = (nav = typeof navigator !== "undefined" ? navigator : void 0) => {
|
|
1337
|
+
if (!nav) return false;
|
|
1338
|
+
const ua = String(nav.userAgent || "");
|
|
1339
|
+
if (/Mobi|Android|iPhone|iPad|iPod/i.test(ua)) return false;
|
|
1340
|
+
const brands = (nav.userAgentData?.brands || []).map((entry) => String(entry?.brand || ""));
|
|
1341
|
+
if (brands.some((brand) => /Chromium|Google Chrome|Microsoft Edge|Opera|Brave/i.test(brand))) return true;
|
|
1342
|
+
return /(Chrome|Chromium|Edg)\//.test(ua) && !/Firefox|FxiOS|OPiOS/.test(ua);
|
|
1343
|
+
};
|
|
1344
|
+
const setScreenAudioPaused = (producer, paused) => {
|
|
1345
|
+
if (!producer || producer.closed) return false;
|
|
1346
|
+
if (paused && !producer.paused) producer.pause();
|
|
1347
|
+
if (!paused && producer.paused) producer.resume();
|
|
1348
|
+
return producer.paused;
|
|
1349
|
+
};
|
|
1350
|
+
const buildDisplayMediaOptions = ({ targetWidth, targetHeight, withAudio }) => {
|
|
1351
|
+
const options = {
|
|
1352
|
+
video: { width: targetWidth, height: targetHeight, frameRate: 30 },
|
|
1353
|
+
audio: withAudio ? { echoCancellation: false, noiseSuppression: false, autoGainControl: false } : false
|
|
1354
|
+
};
|
|
1355
|
+
if (withAudio) {
|
|
1356
|
+
options.systemAudio = "include";
|
|
1357
|
+
options.suppressLocalAudioPlayback = false;
|
|
1358
|
+
}
|
|
1359
|
+
return options;
|
|
1360
|
+
};
|
|
1361
|
+
const producersBySocket = /* @__PURE__ */ new WeakMap();
|
|
1362
|
+
const rememberScreenAudioProducer = (socket, producer) => {
|
|
1363
|
+
if (!socket) return;
|
|
1364
|
+
if (producer) producersBySocket.set(socket, producer);
|
|
1365
|
+
else producersBySocket.delete(socket);
|
|
1366
|
+
};
|
|
1367
|
+
const recallScreenAudioProducer = (socket) => socket && producersBySocket.get(socket) || null;
|
|
1368
|
+
const setScreenAudioVolume = (volume, root = typeof document !== "undefined" ? document : null) => {
|
|
1369
|
+
if (!root) return;
|
|
1370
|
+
const value = Math.min(1, Math.max(0, Number.isFinite(volume) ? volume : 1));
|
|
1371
|
+
root.querySelectorAll('audio[data-screen-audio="true"]').forEach((element) => {
|
|
1372
|
+
element.volume = value;
|
|
1373
|
+
});
|
|
1374
|
+
};
|
|
1248
1375
|
const producerClosed = async ({
|
|
1249
1376
|
remoteProducerId,
|
|
1250
1377
|
parameters
|
|
1251
1378
|
}) => {
|
|
1252
1379
|
let { consumerTransports, closeAndResize: closeAndResize2, screenId, updateConsumerTransports } = parameters;
|
|
1380
|
+
forgetScreenAudioProducer(remoteProducerId);
|
|
1253
1381
|
const activeTranslationProducerIds = parameters.activeTranslationProducerIds;
|
|
1254
1382
|
const isTranslationProducer = activeTranslationProducerIds?.has?.(remoteProducerId);
|
|
1255
1383
|
if (isTranslationProducer) {
|
|
@@ -1400,6 +1528,20 @@ const joinConsumeRoom = async ({
|
|
|
1400
1528
|
};
|
|
1401
1529
|
const pendingConsumeConnections = /* @__PURE__ */ new WeakMap();
|
|
1402
1530
|
const normalizeConsumeEndpoint = (ip) => ip.trim().toLowerCase().replace(/\.$/, "");
|
|
1531
|
+
const CONSUME_REJECTION_COOLDOWN_MS = 6e4;
|
|
1532
|
+
const rejectedConsumeEndpoints = /* @__PURE__ */ new WeakMap();
|
|
1533
|
+
const consumeEndpointRecentlyRejected = (owner, endpoint) => {
|
|
1534
|
+
const at = rejectedConsumeEndpoints.get(owner)?.get(endpoint);
|
|
1535
|
+
return at !== void 0 && Date.now() - at < CONSUME_REJECTION_COOLDOWN_MS;
|
|
1536
|
+
};
|
|
1537
|
+
const rememberConsumeEndpointRejection = (owner, endpoint) => {
|
|
1538
|
+
let byEndpoint = rejectedConsumeEndpoints.get(owner);
|
|
1539
|
+
if (!byEndpoint) {
|
|
1540
|
+
byEndpoint = /* @__PURE__ */ new Map();
|
|
1541
|
+
rejectedConsumeEndpoints.set(owner, byEndpoint);
|
|
1542
|
+
}
|
|
1543
|
+
byEndpoint.set(endpoint, Date.now());
|
|
1544
|
+
};
|
|
1403
1545
|
const hasConsumeEndpoint = (consumeSockets, endpoint) => {
|
|
1404
1546
|
for (let index = consumeSockets.length - 1; index >= 0; index -= 1) {
|
|
1405
1547
|
const socketObj = consumeSockets[index];
|
|
@@ -1467,7 +1609,9 @@ const connectIps = async ({
|
|
|
1467
1609
|
});
|
|
1468
1610
|
return [consume_sockets, roomRecvIPs];
|
|
1469
1611
|
}
|
|
1612
|
+
const rejectionOwner = parameters?.socket || consume_sockets;
|
|
1470
1613
|
for (const ip of remIP) {
|
|
1614
|
+
if (consumeEndpointRecentlyRejected(rejectionOwner, normalizeConsumeEndpoint(ip))) continue;
|
|
1471
1615
|
const releaseReservation = await reserveConsumeEndpoint(
|
|
1472
1616
|
consume_sockets,
|
|
1473
1617
|
ip,
|
|
@@ -1479,11 +1623,25 @@ const connectIps = async ({
|
|
|
1479
1623
|
try {
|
|
1480
1624
|
remote_sock = await connectSocket({ apiUserName, apiKey, apiToken, link: `https://${ip}.mediasfu.com` });
|
|
1481
1625
|
if (remote_sock.id) {
|
|
1626
|
+
let consumeRoomReady = false;
|
|
1627
|
+
const pendingProducers = [];
|
|
1482
1628
|
if (!roomRecvIPs.includes(ip)) {
|
|
1483
1629
|
roomRecvIPs.push(ip);
|
|
1484
1630
|
updateRoomRecvIPs(roomRecvIPs);
|
|
1485
1631
|
}
|
|
1486
|
-
|
|
1632
|
+
const consumeProducer = async ({ producerId, islevel, isTranslation, translationMeta, mediaTag }) => {
|
|
1633
|
+
markScreenAudioProducer(producerId, mediaTag);
|
|
1634
|
+
if (!consumeRoomReady) {
|
|
1635
|
+
pendingProducers.push({ producerId, islevel, isTranslation, translationMeta });
|
|
1636
|
+
return;
|
|
1637
|
+
}
|
|
1638
|
+
const preferDelay = isTranslation ? 0 : consumerBackupPreferDelay(
|
|
1639
|
+
ip,
|
|
1640
|
+
parameters.getUpdatedAllParams?.()?.consume_sockets
|
|
1641
|
+
);
|
|
1642
|
+
if (preferDelay > 0) {
|
|
1643
|
+
await new Promise((resolve) => setTimeout(resolve, preferDelay));
|
|
1644
|
+
}
|
|
1487
1645
|
if (newProducerMethod) {
|
|
1488
1646
|
await newProducerMethod({
|
|
1489
1647
|
producerId,
|
|
@@ -1494,7 +1652,8 @@ const connectIps = async ({
|
|
|
1494
1652
|
translationMeta
|
|
1495
1653
|
});
|
|
1496
1654
|
}
|
|
1497
|
-
}
|
|
1655
|
+
};
|
|
1656
|
+
remote_sock.on("new-pipe-producer", consumeProducer);
|
|
1498
1657
|
remote_sock.on("producer-closed", async ({ remoteProducerId }) => {
|
|
1499
1658
|
if (closedProducerMethod) {
|
|
1500
1659
|
await closedProducerMethod({ remoteProducerId, parameters });
|
|
@@ -1511,6 +1670,11 @@ const connectIps = async ({
|
|
|
1511
1670
|
throw new Error(`Consume room ${ip} did not return RTP capabilities.`);
|
|
1512
1671
|
}
|
|
1513
1672
|
}
|
|
1673
|
+
const queuedProducers = pendingProducers.splice(0);
|
|
1674
|
+
consumeRoomReady = true;
|
|
1675
|
+
for (const producer of queuedProducers) {
|
|
1676
|
+
await consumeProducer(producer);
|
|
1677
|
+
}
|
|
1514
1678
|
consume_sockets.push({ [ip]: remote_sock });
|
|
1515
1679
|
updateConsume_sockets(consume_sockets);
|
|
1516
1680
|
connected = true;
|
|
@@ -1532,7 +1696,12 @@ const connectIps = async ({
|
|
|
1532
1696
|
});
|
|
1533
1697
|
}
|
|
1534
1698
|
} catch (error) {
|
|
1535
|
-
|
|
1699
|
+
if (isMediaSocketConnectError(error) && !error.retryable) {
|
|
1700
|
+
rememberConsumeEndpointRejection(rejectionOwner, normalizeConsumeEndpoint(ip));
|
|
1701
|
+
console.warn(`connectIps: ${ip} refused this room (${error.reason}); not retrying for ${CONSUME_REJECTION_COOLDOWN_MS / 1e3} s.`, error.message);
|
|
1702
|
+
} else {
|
|
1703
|
+
console.log("connectIps error", error);
|
|
1704
|
+
}
|
|
1536
1705
|
} finally {
|
|
1537
1706
|
if (!connected && remote_sock) {
|
|
1538
1707
|
remote_sock.removeAllListeners?.();
|
|
@@ -1766,6 +1935,36 @@ const connectSendTransport = async ({ option, targetOption = "all", parameters }
|
|
|
1766
1935
|
console.log("connectSendTransport error", error);
|
|
1767
1936
|
}
|
|
1768
1937
|
};
|
|
1938
|
+
const pendingCreations = /* @__PURE__ */ new WeakMap();
|
|
1939
|
+
const pendingSendTransportCreation = (socket) => socket ? pendingCreations.get(socket) : void 0;
|
|
1940
|
+
const trackSendTransportCreation = (socket, create) => {
|
|
1941
|
+
if (!socket) return create();
|
|
1942
|
+
const running = create();
|
|
1943
|
+
pendingCreations.set(socket, running);
|
|
1944
|
+
const release = () => {
|
|
1945
|
+
if (pendingCreations.get(socket) === running) pendingCreations.delete(socket);
|
|
1946
|
+
};
|
|
1947
|
+
running.then(release, release);
|
|
1948
|
+
return running;
|
|
1949
|
+
};
|
|
1950
|
+
const isOpen = (item) => Boolean(item && !item.closed);
|
|
1951
|
+
const pendingProduces = /* @__PURE__ */ new WeakMap();
|
|
1952
|
+
const produceOnce$1 = async (transport, key, produce) => {
|
|
1953
|
+
let byKey = pendingProduces.get(transport);
|
|
1954
|
+
if (!byKey) {
|
|
1955
|
+
byKey = /* @__PURE__ */ new Map();
|
|
1956
|
+
pendingProduces.set(transport, byKey);
|
|
1957
|
+
}
|
|
1958
|
+
const inFlight = byKey.get(key);
|
|
1959
|
+
if (inFlight) return { producer: await inFlight, joined: true };
|
|
1960
|
+
const running = produce();
|
|
1961
|
+
byKey.set(key, running);
|
|
1962
|
+
try {
|
|
1963
|
+
return { producer: await running, joined: false };
|
|
1964
|
+
} finally {
|
|
1965
|
+
if (byKey.get(key) === running) byKey.delete(key);
|
|
1966
|
+
}
|
|
1967
|
+
};
|
|
1769
1968
|
const connectLocalSendTransportAudio = async ({
|
|
1770
1969
|
parameters,
|
|
1771
1970
|
audioParams
|
|
@@ -1778,7 +1977,7 @@ const connectLocalSendTransportAudio = async ({
|
|
|
1778
1977
|
updateLocalProducerTransport
|
|
1779
1978
|
} = parameters;
|
|
1780
1979
|
if (localProducerTransport) {
|
|
1781
|
-
localAudioProducer = await localProducerTransport.produce(audioParams);
|
|
1980
|
+
localAudioProducer = (await produceOnce$1(localProducerTransport, "audio", () => localProducerTransport.produce(audioParams))).producer;
|
|
1782
1981
|
updateLocalAudioProducer?.(localAudioProducer);
|
|
1783
1982
|
updateLocalProducerTransport?.(localProducerTransport);
|
|
1784
1983
|
}
|
|
@@ -1816,8 +2015,9 @@ const connectSendTransportAudio = async ({
|
|
|
1816
2015
|
updateProducerTransport
|
|
1817
2016
|
} = parameters;
|
|
1818
2017
|
if (targetOption === "all" || targetOption === "remote") {
|
|
1819
|
-
|
|
1820
|
-
|
|
2018
|
+
const produced = await produceOnce$1(producerTransport, "audio", () => producerTransport.produce(audioParams));
|
|
2019
|
+
audioProducer = produced.producer;
|
|
2020
|
+
if (!produced.joined) updateMicLevel(audioProducer, parameters.updateAudioLevel);
|
|
1821
2021
|
updateAudioProducer(audioProducer);
|
|
1822
2022
|
updateProducerTransport(producerTransport);
|
|
1823
2023
|
}
|
|
@@ -1855,11 +2055,11 @@ const connectLocalSendTransportScreen = async ({
|
|
|
1855
2055
|
(codec2) => codec2.mimeType.toLowerCase() === "video/vp9"
|
|
1856
2056
|
);
|
|
1857
2057
|
if (localProducerTransport) {
|
|
1858
|
-
localScreenProducer = await localProducerTransport.produce({
|
|
2058
|
+
localScreenProducer = (await produceOnce$1(localProducerTransport, "screen", () => localProducerTransport.produce({
|
|
1859
2059
|
track: stream.getVideoTracks()[0],
|
|
1860
2060
|
codec,
|
|
1861
2061
|
appData: { mediaTag: "screen-video" }
|
|
1862
|
-
});
|
|
2062
|
+
}))).producer;
|
|
1863
2063
|
updateLocalScreenProducer?.(localScreenProducer);
|
|
1864
2064
|
updateLocalProducerTransport?.(localProducerTransport);
|
|
1865
2065
|
}
|
|
@@ -1889,12 +2089,12 @@ const connectSendTransportScreen = async ({
|
|
|
1889
2089
|
(codec2) => codec2.mimeType.toLowerCase() === "video/vp9"
|
|
1890
2090
|
);
|
|
1891
2091
|
if (targetOption === "remote" || targetOption === "all") {
|
|
1892
|
-
screenProducer = await producerTransport.produce({
|
|
2092
|
+
screenProducer = (await produceOnce$1(producerTransport, "screen", () => producerTransport.produce({
|
|
1893
2093
|
track: stream.getVideoTracks()[0],
|
|
1894
2094
|
...params,
|
|
1895
2095
|
codec,
|
|
1896
2096
|
appData: { mediaTag: "screen-video" }
|
|
1897
|
-
});
|
|
2097
|
+
}))).producer;
|
|
1898
2098
|
updateScreenProducer(screenProducer);
|
|
1899
2099
|
updateProducerTransport(producerTransport);
|
|
1900
2100
|
}
|
|
@@ -1922,7 +2122,7 @@ const connectLocalSendTransportVideo = async ({
|
|
|
1922
2122
|
updateLocalProducerTransport
|
|
1923
2123
|
} = parameters;
|
|
1924
2124
|
if (localProducerTransport) {
|
|
1925
|
-
localVideoProducer = await localProducerTransport.produce(videoParams);
|
|
2125
|
+
localVideoProducer = (await produceOnce$1(localProducerTransport, "video", () => localProducerTransport.produce(videoParams))).producer;
|
|
1926
2126
|
updateLocalVideoProducer?.(localVideoProducer);
|
|
1927
2127
|
updateLocalProducerTransport?.(localProducerTransport);
|
|
1928
2128
|
}
|
|
@@ -1947,7 +2147,7 @@ const connectSendTransportVideo = async ({
|
|
|
1947
2147
|
updateUpdateMainWindow
|
|
1948
2148
|
} = parameters;
|
|
1949
2149
|
if (targetOption === "all" || targetOption === "remote") {
|
|
1950
|
-
videoProducer = await producerTransport.produce(videoParams);
|
|
2150
|
+
videoProducer = (await produceOnce$1(producerTransport, "video", () => producerTransport.produce(videoParams))).producer;
|
|
1951
2151
|
if (islevel === "2") {
|
|
1952
2152
|
updateMainWindow = true;
|
|
1953
2153
|
}
|
|
@@ -2067,7 +2267,7 @@ const createLocalSendTransport = async ({
|
|
|
2067
2267
|
console.error("Error creating local send transport:", error);
|
|
2068
2268
|
}
|
|
2069
2269
|
};
|
|
2070
|
-
const
|
|
2270
|
+
const createSendTransportNow = async ({
|
|
2071
2271
|
option,
|
|
2072
2272
|
parameters
|
|
2073
2273
|
}) => {
|
|
@@ -2097,67 +2297,109 @@ const createSendTransport = async ({
|
|
|
2097
2297
|
} catch (error) {
|
|
2098
2298
|
console.log("Error creating local send transport:", error);
|
|
2099
2299
|
}
|
|
2100
|
-
socket.emit(
|
|
2300
|
+
await new Promise((resolve, reject) => socket.emit(
|
|
2101
2301
|
"createWebRtcTransport",
|
|
2102
2302
|
{ consumer: false, islevel },
|
|
2103
2303
|
async ({ params }) => {
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
if (!resolvedDevice) {
|
|
2110
|
-
return;
|
|
2111
|
-
}
|
|
2112
|
-
const createdProducerTransport = await resolvedDevice.createSendTransport(params);
|
|
2113
|
-
updateProducerTransport(createdProducerTransport);
|
|
2114
|
-
createdProducerTransport.on(
|
|
2115
|
-
"connect",
|
|
2116
|
-
async ({ dtlsParameters }, callback, errback) => {
|
|
2117
|
-
try {
|
|
2118
|
-
socket.emit("transport-connect", { dtlsParameters });
|
|
2119
|
-
callback();
|
|
2120
|
-
} catch (error) {
|
|
2121
|
-
errback(error);
|
|
2122
|
-
}
|
|
2123
|
-
}
|
|
2124
|
-
);
|
|
2125
|
-
createdProducerTransport.on(
|
|
2126
|
-
"produce",
|
|
2127
|
-
async (parameters2, callback, errback) => {
|
|
2128
|
-
try {
|
|
2129
|
-
socket.emit(
|
|
2130
|
-
"transport-produce",
|
|
2131
|
-
{
|
|
2132
|
-
kind: parameters2.kind,
|
|
2133
|
-
rtpParameters: parameters2.rtpParameters,
|
|
2134
|
-
appData: parameters2.appData,
|
|
2135
|
-
islevel,
|
|
2136
|
-
name: member
|
|
2137
|
-
},
|
|
2138
|
-
async ({ id }) => {
|
|
2139
|
-
callback({ id });
|
|
2140
|
-
}
|
|
2141
|
-
);
|
|
2142
|
-
} catch (error) {
|
|
2143
|
-
errback(error);
|
|
2144
|
-
}
|
|
2304
|
+
try {
|
|
2305
|
+
if (params && params.error) {
|
|
2306
|
+
console.error("Error in createWebRtcTransport:", params.error);
|
|
2307
|
+
reject(new Error(String(params.error)));
|
|
2308
|
+
return;
|
|
2145
2309
|
}
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
await connectSendTransport2({
|
|
2151
|
-
targetOption: "remote",
|
|
2152
|
-
option,
|
|
2153
|
-
parameters: {
|
|
2154
|
-
...parameters,
|
|
2155
|
-
producerTransport: createdProducerTransport
|
|
2310
|
+
const resolvedDevice = parameters.getCurrentParams ? parameters.getCurrentParams().device : device ?? null;
|
|
2311
|
+
if (!resolvedDevice) {
|
|
2312
|
+
resolve();
|
|
2313
|
+
return;
|
|
2156
2314
|
}
|
|
2157
|
-
|
|
2158
|
-
|
|
2315
|
+
const createdProducerTransport = await resolvedDevice.createSendTransport(params);
|
|
2316
|
+
updateProducerTransport(createdProducerTransport);
|
|
2317
|
+
createdProducerTransport.on(
|
|
2318
|
+
"connect",
|
|
2319
|
+
async ({ dtlsParameters }, callback, errback) => {
|
|
2320
|
+
try {
|
|
2321
|
+
socket.emit("transport-connect", { dtlsParameters });
|
|
2322
|
+
callback();
|
|
2323
|
+
} catch (error) {
|
|
2324
|
+
errback(error);
|
|
2325
|
+
}
|
|
2326
|
+
}
|
|
2327
|
+
);
|
|
2328
|
+
createdProducerTransport.on(
|
|
2329
|
+
"produce",
|
|
2330
|
+
async (parameters2, callback, errback) => {
|
|
2331
|
+
try {
|
|
2332
|
+
socket.emit(
|
|
2333
|
+
"transport-produce",
|
|
2334
|
+
{
|
|
2335
|
+
kind: parameters2.kind,
|
|
2336
|
+
rtpParameters: parameters2.rtpParameters,
|
|
2337
|
+
appData: parameters2.appData,
|
|
2338
|
+
islevel,
|
|
2339
|
+
name: member
|
|
2340
|
+
},
|
|
2341
|
+
async ({ id }) => {
|
|
2342
|
+
callback({ id });
|
|
2343
|
+
}
|
|
2344
|
+
);
|
|
2345
|
+
} catch (error) {
|
|
2346
|
+
errback(error);
|
|
2347
|
+
}
|
|
2348
|
+
}
|
|
2349
|
+
);
|
|
2350
|
+
attachTransportRecovery(createdProducerTransport, socket, () => clearFailedSendState(parameters, createdProducerTransport));
|
|
2351
|
+
transportCreated = true;
|
|
2352
|
+
parameters = parameters.getCurrentParams?.() ?? parameters;
|
|
2353
|
+
await connectSendTransport2({
|
|
2354
|
+
targetOption: "remote",
|
|
2355
|
+
option,
|
|
2356
|
+
parameters: {
|
|
2357
|
+
...parameters,
|
|
2358
|
+
producerTransport: createdProducerTransport
|
|
2359
|
+
}
|
|
2360
|
+
});
|
|
2361
|
+
updateTransportCreated(transportCreated);
|
|
2362
|
+
resolve();
|
|
2363
|
+
} catch (error) {
|
|
2364
|
+
reject(error);
|
|
2365
|
+
}
|
|
2159
2366
|
}
|
|
2160
|
-
);
|
|
2367
|
+
));
|
|
2368
|
+
} catch (error) {
|
|
2369
|
+
console.log("Error creating send transport:", error);
|
|
2370
|
+
}
|
|
2371
|
+
};
|
|
2372
|
+
const producerFor = (params, option) => {
|
|
2373
|
+
if (option === "audio") return isOpen(params.audioProducer);
|
|
2374
|
+
if (option === "video") return isOpen(params.videoProducer);
|
|
2375
|
+
if (option === "screen") return isOpen(params.screenProducer);
|
|
2376
|
+
return isOpen(params.audioProducer) && isOpen(params.videoProducer);
|
|
2377
|
+
};
|
|
2378
|
+
const createSendTransport = async ({
|
|
2379
|
+
option,
|
|
2380
|
+
parameters
|
|
2381
|
+
}) => {
|
|
2382
|
+
try {
|
|
2383
|
+
const current = parameters.getCurrentParams?.() ?? parameters.getUpdatedAllParams?.() ?? parameters;
|
|
2384
|
+
const socket = current.socket;
|
|
2385
|
+
const pending = pendingSendTransportCreation(socket);
|
|
2386
|
+
if (!pending && !(current.transportCreated && isOpen(current.producerTransport))) {
|
|
2387
|
+
await trackSendTransportCreation(socket, () => createSendTransportNow({ option, parameters }));
|
|
2388
|
+
return;
|
|
2389
|
+
}
|
|
2390
|
+
if (pending) await pending.catch(() => void 0);
|
|
2391
|
+
const latest = parameters.getCurrentParams?.() ?? parameters.getUpdatedAllParams?.() ?? parameters;
|
|
2392
|
+
if (!isOpen(latest.producerTransport)) {
|
|
2393
|
+
await createSendTransport({ option, parameters });
|
|
2394
|
+
return;
|
|
2395
|
+
}
|
|
2396
|
+
if (producerFor(latest, option)) return;
|
|
2397
|
+
const connectSendTransport2 = latest.connectSendTransport ?? parameters.connectSendTransport;
|
|
2398
|
+
await connectSendTransport2({
|
|
2399
|
+
targetOption: "all",
|
|
2400
|
+
option,
|
|
2401
|
+
parameters: { ...latest, producerTransport: latest.producerTransport }
|
|
2402
|
+
});
|
|
2161
2403
|
} catch (error) {
|
|
2162
2404
|
console.log("Error creating send transport:", error);
|
|
2163
2405
|
}
|
|
@@ -2231,6 +2473,99 @@ const disconnectSendTransportAudio = async ({
|
|
|
2231
2473
|
console.log("Error disconnecting primary audio send transport:", error);
|
|
2232
2474
|
}
|
|
2233
2475
|
};
|
|
2476
|
+
const currentScreenAudioProducer = (parameters) => parameters.screenAudioProducer || recallScreenAudioProducer(parameters.socket);
|
|
2477
|
+
const storeScreenAudioProducer = (parameters, producer) => {
|
|
2478
|
+
rememberScreenAudioProducer(parameters.socket, producer);
|
|
2479
|
+
parameters.updateScreenAudioProducer?.(producer);
|
|
2480
|
+
};
|
|
2481
|
+
const disconnectSendTransportScreenAudio = async ({
|
|
2482
|
+
parameters,
|
|
2483
|
+
notifyServer = false
|
|
2484
|
+
}) => {
|
|
2485
|
+
const params = parameters.getUpdatedAllParams ? parameters.getUpdatedAllParams() : parameters;
|
|
2486
|
+
const producer = currentScreenAudioProducer(params);
|
|
2487
|
+
if (!producer) return;
|
|
2488
|
+
try {
|
|
2489
|
+
if (!producer.closed) producer.close();
|
|
2490
|
+
} catch {
|
|
2491
|
+
}
|
|
2492
|
+
storeScreenAudioProducer(params, null);
|
|
2493
|
+
if (notifyServer) {
|
|
2494
|
+
try {
|
|
2495
|
+
params.socket?.emit("closeScreenAudioProducer");
|
|
2496
|
+
} catch {
|
|
2497
|
+
}
|
|
2498
|
+
}
|
|
2499
|
+
};
|
|
2500
|
+
const toggleScreenAudio = ({ parameters, paused }) => {
|
|
2501
|
+
const params = parameters.getUpdatedAllParams ? parameters.getUpdatedAllParams() : parameters;
|
|
2502
|
+
const producer = currentScreenAudioProducer(params);
|
|
2503
|
+
if (!producer || producer.closed) return null;
|
|
2504
|
+
const next = paused ?? !producer.paused;
|
|
2505
|
+
if (next && !producer.paused) producer.pause();
|
|
2506
|
+
if (!next && producer.paused) producer.resume();
|
|
2507
|
+
params.updateScreenAudioProducer?.(producer);
|
|
2508
|
+
return producer.paused;
|
|
2509
|
+
};
|
|
2510
|
+
const produceOnce = async (transport, track) => {
|
|
2511
|
+
const producer = await transport.produce({
|
|
2512
|
+
track,
|
|
2513
|
+
codecOptions: SCREEN_AUDIO_CODEC_OPTIONS,
|
|
2514
|
+
appData: { mediaTag: SCREEN_AUDIO_MEDIA_TAG },
|
|
2515
|
+
// The track belongs to the screen share stream, which stops it with the share.
|
|
2516
|
+
stopTracks: false
|
|
2517
|
+
});
|
|
2518
|
+
if (!producer?.id) {
|
|
2519
|
+
try {
|
|
2520
|
+
producer?.close();
|
|
2521
|
+
} catch {
|
|
2522
|
+
}
|
|
2523
|
+
return null;
|
|
2524
|
+
}
|
|
2525
|
+
return producer;
|
|
2526
|
+
};
|
|
2527
|
+
const connectSendTransportScreenAudio = async ({
|
|
2528
|
+
stream,
|
|
2529
|
+
parameters,
|
|
2530
|
+
retryDelayMs = 600
|
|
2531
|
+
}) => {
|
|
2532
|
+
const params = parameters.getUpdatedAllParams ? parameters.getUpdatedAllParams() : parameters;
|
|
2533
|
+
const track = stream?.getAudioTracks?.()[0];
|
|
2534
|
+
if (!track || track.readyState === "ended") return null;
|
|
2535
|
+
if (!shouldShareScreenAudio(params)) return null;
|
|
2536
|
+
const transport = params.producerTransport;
|
|
2537
|
+
if (!transport || transport.closed) return null;
|
|
2538
|
+
const existing = currentScreenAudioProducer(params);
|
|
2539
|
+
if (existing && !existing.closed) return existing;
|
|
2540
|
+
try {
|
|
2541
|
+
let producer = await produceOnce(transport, track);
|
|
2542
|
+
const trackEnded = () => track.readyState === "ended";
|
|
2543
|
+
if (!producer && retryDelayMs > 0 && !trackEnded()) {
|
|
2544
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
2545
|
+
producer = await produceOnce(transport, track);
|
|
2546
|
+
}
|
|
2547
|
+
if (!producer) return null;
|
|
2548
|
+
storeScreenAudioProducer(params, producer);
|
|
2549
|
+
const screenProducer = params.screenProducer;
|
|
2550
|
+
if (screenProducer?.paused) producer.pause();
|
|
2551
|
+
screenProducer?.observer?.on("pause", () => {
|
|
2552
|
+
if (!producer.closed) producer.pause();
|
|
2553
|
+
});
|
|
2554
|
+
screenProducer?.observer?.on("resume", () => {
|
|
2555
|
+
if (!producer.closed) producer.resume();
|
|
2556
|
+
});
|
|
2557
|
+
screenProducer?.observer?.on("close", () => {
|
|
2558
|
+
void disconnectSendTransportScreenAudio({ parameters: params });
|
|
2559
|
+
});
|
|
2560
|
+
track.addEventListener("ended", () => {
|
|
2561
|
+
void disconnectSendTransportScreenAudio({ parameters: params, notifyServer: true });
|
|
2562
|
+
});
|
|
2563
|
+
return producer;
|
|
2564
|
+
} catch (error) {
|
|
2565
|
+
console.log("connectSendTransportScreenAudio error", error);
|
|
2566
|
+
return null;
|
|
2567
|
+
}
|
|
2568
|
+
};
|
|
2234
2569
|
const disconnectLocalSendTransportScreen = async ({ parameters }) => {
|
|
2235
2570
|
try {
|
|
2236
2571
|
let {
|
|
@@ -2252,6 +2587,10 @@ const disconnectLocalSendTransportScreen = async ({ parameters }) => {
|
|
|
2252
2587
|
const disconnectSendTransportScreen = async ({ parameters }) => {
|
|
2253
2588
|
let { getUpdatedAllParams } = parameters;
|
|
2254
2589
|
parameters = getUpdatedAllParams();
|
|
2590
|
+
try {
|
|
2591
|
+
await disconnectSendTransportScreenAudio({ parameters });
|
|
2592
|
+
} catch {
|
|
2593
|
+
}
|
|
2255
2594
|
try {
|
|
2256
2595
|
let {
|
|
2257
2596
|
screenProducer,
|
|
@@ -3653,6 +3992,11 @@ async function startShareScreen({ parameters }) {
|
|
|
3653
3992
|
onWeb,
|
|
3654
3993
|
targetWidth = 1280,
|
|
3655
3994
|
targetHeight = 720,
|
|
3995
|
+
supportsScreenAudio,
|
|
3996
|
+
screenAudioEnabled,
|
|
3997
|
+
screenAudioMode = "ask",
|
|
3998
|
+
screenAudioPrompt,
|
|
3999
|
+
displayAudioCapable,
|
|
3656
4000
|
streamSuccessScreen: streamSuccessScreen2
|
|
3657
4001
|
} = parameters;
|
|
3658
4002
|
try {
|
|
@@ -3665,15 +4009,23 @@ async function startShareScreen({ parameters }) {
|
|
|
3665
4009
|
return;
|
|
3666
4010
|
}
|
|
3667
4011
|
if (mediaDevices && mediaDevices.getDisplayMedia) {
|
|
4012
|
+
let withAudio = shouldShareScreenAudio({ supportsScreenAudio, screenAudioEnabled, screenAudioMode }) && (displayAudioCapable ?? canCaptureDisplayAudio());
|
|
4013
|
+
if (withAudio && screenAudioMode === "ask" && screenAudioPrompt) {
|
|
4014
|
+
const choice = await screenAudioPrompt();
|
|
4015
|
+
if (choice === null) {
|
|
4016
|
+
updateShared(false);
|
|
4017
|
+
return;
|
|
4018
|
+
}
|
|
4019
|
+
withAudio = choice === "audio";
|
|
4020
|
+
}
|
|
3668
4021
|
shared = true;
|
|
3669
|
-
await mediaDevices.getDisplayMedia(
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
}
|
|
3675
|
-
|
|
3676
|
-
}).then(async (stream) => {
|
|
4022
|
+
await mediaDevices.getDisplayMedia(
|
|
4023
|
+
buildDisplayMediaOptions({
|
|
4024
|
+
targetWidth,
|
|
4025
|
+
targetHeight,
|
|
4026
|
+
withAudio
|
|
4027
|
+
})
|
|
4028
|
+
).then(async (stream) => {
|
|
3677
4029
|
await streamSuccessScreen2({ stream, parameters });
|
|
3678
4030
|
}).catch(async () => {
|
|
3679
4031
|
shared = false;
|
|
@@ -4101,6 +4453,14 @@ const streamSuccessScreen = async ({
|
|
|
4101
4453
|
});
|
|
4102
4454
|
}
|
|
4103
4455
|
socket.emit("startScreenShare");
|
|
4456
|
+
try {
|
|
4457
|
+
await connectSendTransportScreenAudio({
|
|
4458
|
+
stream: localStreamScreen,
|
|
4459
|
+
parameters: getUpdatedAllParams()
|
|
4460
|
+
});
|
|
4461
|
+
} catch (error) {
|
|
4462
|
+
console.log("Screen audio not shared:", error);
|
|
4463
|
+
}
|
|
4104
4464
|
} catch (error) {
|
|
4105
4465
|
showAlert?.({
|
|
4106
4466
|
message: error.message,
|
|
@@ -5372,6 +5732,7 @@ const getPipedProducersAlt = async ({
|
|
|
5372
5732
|
} else {
|
|
5373
5733
|
producerId = producer.id;
|
|
5374
5734
|
translationMeta = producer.translationMeta || null;
|
|
5735
|
+
markScreenAudioProducer(producerId, producer.mediaTag);
|
|
5375
5736
|
}
|
|
5376
5737
|
if (translationMeta) {
|
|
5377
5738
|
const shouldConsume = shouldConsumeTranslationProducer(
|
|
@@ -5591,47 +5952,64 @@ function updateParticipantAudioDecibels({
|
|
|
5591
5952
|
updateAudioDecibels(audioDecibels);
|
|
5592
5953
|
}
|
|
5593
5954
|
export {
|
|
5594
|
-
|
|
5955
|
+
checkGrid as $,
|
|
5595
5956
|
receiveAllPipedTransports as A,
|
|
5596
5957
|
reorderStreams as B,
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5958
|
+
CONSUME_REJECTION_COOLDOWN_MS as C,
|
|
5959
|
+
rePort as D,
|
|
5960
|
+
requestScreenShare as E,
|
|
5961
|
+
resumePauseAudioStreams as F,
|
|
5962
|
+
resumePauseStreams as G,
|
|
5963
|
+
reUpdateInter as H,
|
|
5964
|
+
signalNewConsumerTransport as I,
|
|
5965
|
+
startShareScreen as J,
|
|
5966
|
+
stopShareScreen as K,
|
|
5967
|
+
streamSuccessAudio as L,
|
|
5968
|
+
streamSuccessAudioSwitch as M,
|
|
5969
|
+
streamSuccessScreen as N,
|
|
5970
|
+
selectVideoProducerCodec as O,
|
|
5971
|
+
streamSuccessVideo as P,
|
|
5972
|
+
switchUserAudio as Q,
|
|
5973
|
+
switchUserVideo as R,
|
|
5974
|
+
switchUserVideoAlt as S,
|
|
5975
|
+
trigger as T,
|
|
5976
|
+
joinConsumeRoom as U,
|
|
5977
|
+
newPipeProducer as V,
|
|
5978
|
+
producerClosed as W,
|
|
5979
|
+
clickVideo as X,
|
|
5980
|
+
joinConRoom as Y,
|
|
5981
|
+
autoAdjust as Z,
|
|
5982
|
+
calculateRowsAndColumns as _,
|
|
5622
5983
|
changeVids as a,
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5984
|
+
checkPermission as a0,
|
|
5985
|
+
controlMedia as a1,
|
|
5986
|
+
getEstimate as a2,
|
|
5987
|
+
getPipedProducersAlt as a3,
|
|
5988
|
+
getProducersPiped as a4,
|
|
5989
|
+
receiveRoomMessages as a5,
|
|
5990
|
+
resumeSendTransportAudio as a6,
|
|
5991
|
+
updateMiniCardsGrid as a7,
|
|
5992
|
+
updateParticipantAudioDecibels as a8,
|
|
5993
|
+
disconnectSendTransportScreenAudio as a9,
|
|
5994
|
+
toggleScreenAudio as aa,
|
|
5995
|
+
connectSendTransportScreenAudio as ab,
|
|
5996
|
+
SCREEN_AUDIO_MEDIA_TAG as ac,
|
|
5997
|
+
SCREEN_AUDIO_CODEC_OPTIONS as ad,
|
|
5998
|
+
markScreenAudioProducer as ae,
|
|
5999
|
+
forgetScreenAudioProducer as af,
|
|
6000
|
+
isScreenAudioProducer as ag,
|
|
6001
|
+
shouldShareScreenAudio as ah,
|
|
6002
|
+
canCaptureDisplayAudio as ai,
|
|
6003
|
+
setScreenAudioPaused as aj,
|
|
6004
|
+
buildDisplayMediaOptions as ak,
|
|
6005
|
+
rememberScreenAudioProducer as al,
|
|
6006
|
+
recallScreenAudioProducer as am,
|
|
6007
|
+
setScreenAudioVolume as an,
|
|
6008
|
+
stopReconnectingWhenRefused as ao,
|
|
6009
|
+
connectSocket as ap,
|
|
6010
|
+
disconnectSocket as aq,
|
|
6011
|
+
connectLocalSocket as ar,
|
|
6012
|
+
createFrameworkConsumerContractError as as,
|
|
5635
6013
|
checkScreenShare as b,
|
|
5636
6014
|
consumerResume as c,
|
|
5637
6015
|
closeAndResize as d,
|
|
@@ -5658,4 +6036,4 @@ export {
|
|
|
5658
6036
|
processConsumerTransportsAudio as y,
|
|
5659
6037
|
readjust as z
|
|
5660
6038
|
};
|
|
5661
|
-
//# sourceMappingURL=updateParticipantAudioDecibels-
|
|
6039
|
+
//# sourceMappingURL=updateParticipantAudioDecibels-xKKq7Zp5.js.map
|