mediasfu-shared 1.2.6 → 1.3.0

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 (108) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/HEADLESS_GUIDE.md +12 -0
  3. package/README.md +14 -2
  4. package/dist/ProducerClient/producerClientEmits/roomVideoPolicy.d.ts +20 -0
  5. package/dist/ProducerClient/producerClientEmits/roomVideoPolicy.d.ts.map +1 -0
  6. package/dist/ProducerClient/producerClientEmits/updateRoomParametersClient.d.ts +11 -1
  7. package/dist/ProducerClient/producerClientEmits/updateRoomParametersClient.d.ts.map +1 -1
  8. package/dist/audioProcessing-Ca5wm1nV.js +150 -0
  9. package/dist/audioProcessing-Ca5wm1nV.js.map +1 -0
  10. package/dist/audioProcessing-VCbu70Jt.cjs +149 -0
  11. package/dist/audioProcessing-VCbu70Jt.cjs.map +1 -0
  12. package/dist/consumers/closeAndResize.d.ts +3 -0
  13. package/dist/consumers/closeAndResize.d.ts.map +1 -1
  14. package/dist/consumers/connectIps.d.ts +6 -0
  15. package/dist/consumers/connectIps.d.ts.map +1 -1
  16. package/dist/consumers/connectSendTransportScreenAudio.d.ts +65 -0
  17. package/dist/consumers/connectSendTransportScreenAudio.d.ts.map +1 -0
  18. package/dist/consumers/consumerBackupPreference.d.ts +14 -0
  19. package/dist/consumers/consumerBackupPreference.d.ts.map +1 -0
  20. package/dist/consumers/disconnectSendTransportScreen.d.ts.map +1 -1
  21. package/dist/consumers/getPipedProducersAlt.d.ts.map +1 -1
  22. package/dist/consumers/index.cjs +23 -1
  23. package/dist/consumers/index.cjs.map +1 -1
  24. package/dist/consumers/index.d.ts +3 -0
  25. package/dist/consumers/index.d.ts.map +1 -1
  26. package/dist/consumers/index.js +61 -39
  27. package/dist/consumers/index.js.map +1 -1
  28. package/dist/consumers/screenAudio.d.ts +64 -0
  29. package/dist/consumers/screenAudio.d.ts.map +1 -0
  30. package/dist/consumers/socketReceiveMethods/producerClosed.d.ts.map +1 -1
  31. package/dist/consumers/startShareScreen.d.ts +14 -0
  32. package/dist/consumers/startShareScreen.d.ts.map +1 -1
  33. package/dist/consumers/streamSuccessScreen.d.ts.map +1 -1
  34. package/dist/{getParticipantMedia-B6LsMxmS.cjs → getParticipantMedia-1okyF4H7.cjs} +4 -4
  35. package/dist/{getParticipantMedia-B6LsMxmS.cjs.map → getParticipantMedia-1okyF4H7.cjs.map} +1 -1
  36. package/dist/{getParticipantMedia-B8MFkrT1.js → getParticipantMedia-DEJwXXhU.js} +4 -4
  37. package/dist/{getParticipantMedia-B8MFkrT1.js.map → getParticipantMedia-DEJwXXhU.js.map} +1 -1
  38. package/dist/index.cjs +36 -6
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.d.ts +4 -0
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +1523 -1493
  43. package/dist/index.native.cjs +36 -6
  44. package/dist/index.native.cjs.map +1 -1
  45. package/dist/index.native.d.ts +4 -0
  46. package/dist/index.native.d.ts.map +1 -1
  47. package/dist/index.native.js +105 -75
  48. package/dist/{joinLocalRoom-X3NXzGmE.js → joinLocalRoom-DS6_6lJL.js} +26 -23
  49. package/dist/joinLocalRoom-DS6_6lJL.js.map +1 -0
  50. package/dist/{joinLocalRoom-XjGmL1_k.cjs → joinLocalRoom-Dsn39SwS.cjs} +26 -23
  51. package/dist/joinLocalRoom-Dsn39SwS.cjs.map +1 -0
  52. package/dist/{joinRoomOnMediaSFU-BnAWLciF.js → joinRoomOnMediaSFU-B6tTA0Mx.js} +17 -13
  53. package/dist/joinRoomOnMediaSFU-B6tTA0Mx.js.map +1 -0
  54. package/dist/{joinRoomOnMediaSFU-D2C7q1GK.cjs → joinRoomOnMediaSFU-CxwD9fBz.cjs} +17 -13
  55. package/dist/joinRoomOnMediaSFU-CxwD9fBz.cjs.map +1 -0
  56. package/dist/methods/index.cjs +12 -8
  57. package/dist/methods/index.cjs.map +1 -1
  58. package/dist/methods/index.js +14 -9
  59. package/dist/methods/index.js.map +1 -1
  60. package/dist/methods/socketReceive/getDomains.d.ts.map +1 -1
  61. package/dist/methods/utils/checkLimitsAndMakeRequest.d.ts.map +1 -1
  62. package/dist/methods/utils/createResponseJoinRoom.d.ts.map +1 -1
  63. package/dist/methods/welcome/handleWelcomeRequest.d.ts.map +1 -1
  64. package/dist/sockets/SocketManager.d.ts.map +1 -1
  65. package/dist/sockets/mediaSocketErrors.d.ts +62 -0
  66. package/dist/sockets/mediaSocketErrors.d.ts.map +1 -0
  67. package/dist/types/index.cjs +4 -3
  68. package/dist/types/index.cjs.map +1 -1
  69. package/dist/types/index.js +39 -38
  70. package/dist/types/shared-base-types.d.ts +8 -0
  71. package/dist/types/shared-base-types.d.ts.map +1 -1
  72. package/dist/{updateParticipantAudioDecibels-DiJ_LFfH.js → updateParticipantAudioDecibels-BBfdHWQ0.js} +344 -61
  73. package/dist/updateParticipantAudioDecibels-BBfdHWQ0.js.map +1 -0
  74. package/dist/{updateParticipantAudioDecibels-BJ2PxJJD.cjs → updateParticipantAudioDecibels-Dni8i6AY.cjs} +306 -23
  75. package/dist/updateParticipantAudioDecibels-Dni8i6AY.cjs.map +1 -0
  76. package/package.json +3 -2
  77. package/src/ProducerClient/producerClientEmits/roomVideoPolicy.ts +41 -0
  78. package/src/ProducerClient/producerClientEmits/updateRoomParametersClient.ts +19 -21
  79. package/src/consumers/closeAndResize.ts +14 -0
  80. package/src/consumers/connectIps.ts +81 -8
  81. package/src/consumers/connectSendTransportScreenAudio.ts +184 -0
  82. package/src/consumers/consumerBackupPreference.ts +43 -0
  83. package/src/consumers/disconnectSendTransportScreen.ts +8 -0
  84. package/src/consumers/getPipedProducersAlt.ts +4 -0
  85. package/src/consumers/index.ts +3 -0
  86. package/src/consumers/screenAudio.ts +132 -0
  87. package/src/consumers/socketReceiveMethods/producerClosed.ts +3 -0
  88. package/src/consumers/startShareScreen.ts +44 -8
  89. package/src/consumers/streamSuccessScreen.ts +11 -0
  90. package/src/index.native.ts +4 -0
  91. package/src/index.ts +4 -0
  92. package/src/methods/socketReceive/getDomains.ts +4 -0
  93. package/src/methods/utils/checkLimitsAndMakeRequest.ts +24 -11
  94. package/src/methods/utils/createResponseJoinRoom.ts +2 -1
  95. package/src/methods/welcome/handleWelcomeRequest.ts +15 -6
  96. package/src/sockets/SocketManager.ts +76 -12
  97. package/src/sockets/mediaSocketErrors.ts +156 -0
  98. package/src/types/shared-base-types.ts +8 -0
  99. package/dist/audioProcessing-0z5KlcmO.js +0 -35
  100. package/dist/audioProcessing-0z5KlcmO.js.map +0 -1
  101. package/dist/audioProcessing-BpbrdCk-.cjs +0 -34
  102. package/dist/audioProcessing-BpbrdCk-.cjs.map +0 -1
  103. package/dist/joinLocalRoom-X3NXzGmE.js.map +0 -1
  104. package/dist/joinLocalRoom-XjGmL1_k.cjs.map +0 -1
  105. package/dist/joinRoomOnMediaSFU-BnAWLciF.js.map +0 -1
  106. package/dist/joinRoomOnMediaSFU-D2C7q1GK.cjs.map +0 -1
  107. package/dist/updateParticipantAudioDecibels-BJ2PxJJD.cjs.map +0 -1
  108. package/dist/updateParticipantAudioDecibels-DiJ_LFfH.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.3.0 — 2026-10-09
4
+
5
+ - **Screen-share audio.** When the media server supports it (`supportsScreenAudio` in the join response), the audio of a shared tab or screen is published as its own producer (`appData.mediaTag: "screen-audio"`) next to the screen video. It pauses, resumes and stops with the screen share, never replaces or mixes into the microphone, and never marks the sharer as speaking. New: `connectSendTransportScreenAudio`, `disconnectSendTransportScreenAudio`, `toggleScreenAudio`, `isScreenAudioProducer`, `canCaptureDisplayAudio`, `buildDisplayMediaOptions`, `setScreenAudioVolume`. `startShareScreen` accepts `supportsScreenAudio`, `screenAudioEnabled`, `screenAudioMode` (`ask` | `always` | `never`) and a `screenAudioPrompt` callback for the SDK's own "share audio too?" dialog. Capture works in Chromium desktop browsers; elsewhere screen sharing stays video-only. On servers without support nothing changes.
6
+ - **Listeners recognise screen audio** from `new-pipe-producer` and `getProducersPipedAlt` (`mediaTag`) and from the participant's `ScreenAudioID`, and forget it on `producer-closed`.
7
+ - **Consumer backup preference.** When a busy consuming node has a connected backup (`alt_domains`), a new stream announced by the busy node waits 1.5 s so the backup's own announcement can be used instead. Requests are never sent to a backup that has not announced the stream.
8
+ - **Clear connection errors.** `connectSocket` now rejects with a `MediaSocketConnectError` that carries the failure `phase` (`before-open`, `after-open`, `rejected`, `timeout`), elapsed time, the browser's online state, and the server's `connection-rejected` `reason` and `stage` (`invalid-credentials`, `meeting-minutes-unavailable`, `api-check-failed`, `invalid-request`, `rejected-before-connection-success`). `describeMediaSocketError` turns it into a sentence for end users, and `retryable` is false when the same credentials cannot succeed. Consume endpoints that refuse a room's credentials are not retried for 60 seconds.
9
+ - Events that arrive before a consume socket has joined its consuming room are queued and replayed after the join instead of being dropped.
10
+ - Join requests (`checkLimitsAndMakeRequest`, `checkLimitsAndMakeRequestWithStorage`, `handleWelcomeRequest`) no longer count network-only failures (offline, or the media server never reached) toward the 10-attempt limit; `isNetworkOnlyMediaSocketError` tells them apart.
11
+ - `closeAndResize` removes the closed producer's audio-only player (microphone or screen audio) from `audioOnlyStreams`, so a rejoin never leaves a second player behind.
12
+
13
+ ## 1.2.7 — 2026-09-30
14
+
15
+ - Disable camera simulcast automatically for chat and capacity-two rooms, with an explicit `simulcastOff` opt-out for larger rooms and an optional `roomCapacity` hint.
16
+ - Preserve full-resolution encoder limits in single-encoding mode and restore the original preset for later room updates.
17
+ - Remove the recording-only 20% camera bitrate and initial-bitrate uplift; screen-sharing and audio presets are unchanged.
18
+
19
+
3
20
  ## 1.2.6 — 2026-09-30
4
21
 
5
22
  - Prevent repeated room updates and resolution changes from compounding video bitrates. Each update now uses an isolated copy of the original host or participant preset, including custom encoding and codec options.
package/HEADLESS_GUIDE.md CHANGED
@@ -154,3 +154,15 @@ Use a real two-participant room for media acceptance. Seeded or mocked UI proves
154
154
  - [Secure backend proxy](https://mediasfu.com/docs/usage/secure-backend-proxy/)
155
155
  - [MediaSFU Open](https://github.com/MediaSFU/MediaSFUOpen)
156
156
  - [MediaSFU Sandbox](https://mediasfu.com/sandbox)
157
+
158
+ ## Camera simulcast and recording bitrate
159
+
160
+ Camera simulcast is disabled automatically for `chat` rooms and rooms with a configured capacity of exactly two. This uses the room's configured capacity, not the number of participants currently connected. Larger rooms retain simulcast unless `simulcastOff: true` is supplied.
161
+
162
+ Single-encoding mode uses the full-resolution camera layer and preserves its bitrate and frame-rate limits. Screen-sharing and audio encodings are unchanged. Enabling recording no longer adds a 20% camera bitrate or initial-bitrate uplift.
163
+
164
+ The server's join-response `capacity` takes precedence. For servers that omit it, supply `roomCapacity: 2` as a client-side hint. Programmatic room creation also uses `noUIPreJoinOptions.capacity` as the hint. This option does not change server-side capacity or authorization.
165
+
166
+ ```ts
167
+ updateRoomParametersClient({ parameters, simulcastOff: true, roomCapacity: 2 });
168
+ ```
package/README.md CHANGED
@@ -186,5 +186,17 @@ await leaveRoom({ parameters, endRoomOnHostExit: false });
186
186
  The host can later rejoin with the normal room credentials. Never expose production API credentials in a client application; use your backend room proxy outside local development.
187
187
 
188
188
  ## License
189
-
190
- MIT. See [LICENSE](LICENSE).
189
+
190
+ MIT. See [LICENSE](LICENSE).
191
+
192
+ ## Camera simulcast and recording bitrate
193
+
194
+ Camera simulcast is disabled automatically for `chat` rooms and rooms with a configured capacity of exactly two. This uses the room's configured capacity, not the number of participants currently connected. Larger rooms retain simulcast unless `simulcastOff: true` is supplied.
195
+
196
+ Single-encoding mode uses the full-resolution camera layer and preserves its bitrate and frame-rate limits. Screen-sharing and audio encodings are unchanged. Enabling recording no longer adds a 20% camera bitrate or initial-bitrate uplift.
197
+
198
+ The server's join-response `capacity` takes precedence. For servers that omit it, supply `roomCapacity: 2` as a client-side hint. Programmatic room creation also uses `noUIPreJoinOptions.capacity` as the hint. This option does not change server-side capacity or authorization.
199
+
200
+ ```ts
201
+ updateRoomParametersClient({ parameters, simulcastOff: true, roomCapacity: 2 });
202
+ ```
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Camera-only policy. Screen-sharing and audio encodings are unchanged.
3
+ * Server capacity wins over a hint; recording does not increase camera bitrate.
4
+ */
5
+ export interface CameraEncodingPolicy {
6
+ simulcastOff?: boolean;
7
+ roomCapacity?: number;
8
+ }
9
+ export declare function cameraSimulcastOff(eventType: string, capacity: number | undefined, options?: CameraEncodingPolicy): boolean;
10
+ type CameraEncoding = {
11
+ rid?: string;
12
+ scaleResolutionDownBy?: number;
13
+ scalabilityMode?: string;
14
+ };
15
+ /** Mutate only the fresh room preset, preserving its original-preset lineage. */
16
+ export declare function applyCameraEncodingPolicy<T extends {
17
+ encodings: CameraEncoding[];
18
+ }>(params: T, singleEncoding: boolean): T;
19
+ export {};
20
+ //# sourceMappingURL=roomVideoPolicy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roomVideoPolicy.d.ts","sourceRoot":"","sources":["../../../src/ProducerClient/producerClientEmits/roomVideoPolicy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAGT;AAED,KAAK,cAAc,GAAG;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,iFAAiF;AACjF,wBAAgB,yBAAyB,CAAC,CAAC,SAAS;IAAE,SAAS,EAAE,cAAc,EAAE,CAAA;CAAE,EACjF,MAAM,EAAE,CAAC,EACT,cAAc,EAAE,OAAO,GACtB,CAAC,CAYH"}
@@ -31,6 +31,10 @@ export interface UpdateRoomParametersClientParameters {
31
31
  islevel: string;
32
32
  showAlert?: ShowAlert;
33
33
  data: ResponseJoinRoom;
34
+ /** Disable camera simulcast even in larger rooms. */
35
+ simulcastOff?: boolean;
36
+ /** Capacity hint used only when the server does not return capacity. */
37
+ roomCapacity?: number;
34
38
  updateRtpCapabilities: (rtpCapabilities: RtpCapabilities | null) => void;
35
39
  updateRoomRecvIPs: (roomRecvIPs: string[]) => void;
36
40
  updateMeetingRoomParams: (meetingRoomParams: MeetingRoomParams | null) => void;
@@ -74,12 +78,18 @@ export interface UpdateRoomParametersClientParameters {
74
78
  updateRecordingPreferredOrientation: (orientation: string) => void;
75
79
  updateRecordingSupportForOtherOrientation: (support: boolean) => void;
76
80
  updateRecordingMultiFormatsSupport: (support: boolean) => void;
81
+ /** Records whether the media server accepts screen-share audio (join response `supportsScreenAudio`). */
82
+ updateSupportsScreenAudio?: (supported: boolean) => void;
77
83
  updateRecordingVideoOptions: (options: string) => void;
78
84
  updateRecordingAudioOptions: (options: string) => void;
79
85
  }
80
86
  export type UpdateRoomParametersClientOptions = {
81
87
  parameters: UpdateRoomParametersClientParameters;
88
+ /** Disable camera simulcast even in larger rooms. */
89
+ simulcastOff?: boolean;
90
+ /** Capacity hint used only when the server does not return capacity. */
91
+ roomCapacity?: number;
82
92
  };
83
93
  export type UpdateRoomParametersClientType = (options: UpdateRoomParametersClientOptions) => void;
84
- export declare const updateRoomParametersClient: ({ parameters }: UpdateRoomParametersClientOptions) => void;
94
+ export declare const updateRoomParametersClient: ({ parameters, simulcastOff, roomCapacity }: UpdateRoomParametersClientOptions) => void;
85
95
  //# sourceMappingURL=updateRoomParametersClient.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"updateRoomParametersClient.d.ts","sourceRoot":"","sources":["../../../src/ProducerClient/producerClientEmits/updateRoomParametersClient.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"updateRoomParametersClient.d.ts","sourceRoot":"","sources":["../../../src/ProducerClient/producerClientEmits/updateRoomParametersClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,150 @@
1
+ const MEDIA_CONNECTION_REJECTION_REASONS = [
2
+ "invalid-credentials",
3
+ "meeting-minutes-unavailable",
4
+ "api-check-failed",
5
+ "invalid-request",
6
+ "rejected-before-connection-success"
7
+ ];
8
+ const PERMANENT_REJECTIONS = /* @__PURE__ */ new Set(["invalid-credentials", "meeting-minutes-unavailable", "invalid-request"]);
9
+ class MediaSocketConnectError extends Error {
10
+ phase;
11
+ reason;
12
+ stage;
13
+ elapsedMs;
14
+ online;
15
+ transportError;
16
+ link;
17
+ /** False when retrying with the same credentials cannot succeed (bad credentials, no minutes, bad request). */
18
+ retryable;
19
+ constructor(details) {
20
+ super(formatMediaSocketError(details));
21
+ Object.setPrototypeOf(this, MediaSocketConnectError.prototype);
22
+ this.name = "MediaSocketConnectError";
23
+ this.phase = details.phase;
24
+ this.reason = details.reason;
25
+ this.stage = details.stage;
26
+ this.elapsedMs = details.elapsedMs;
27
+ this.online = details.online;
28
+ this.transportError = details.transportError;
29
+ this.link = details.link;
30
+ this.retryable = !(details.phase === "rejected" && details.reason && PERMANENT_REJECTIONS.has(details.reason));
31
+ }
32
+ }
33
+ const normalizeRejectionReason = (reason) => MEDIA_CONNECTION_REJECTION_REASONS.includes(String(reason)) ? reason : "rejected-before-connection-success";
34
+ const currentOnlineState = () => {
35
+ try {
36
+ const nav = globalThis.navigator;
37
+ return typeof nav?.onLine === "boolean" ? nav.onLine : void 0;
38
+ } catch {
39
+ return void 0;
40
+ }
41
+ };
42
+ function formatMediaSocketError(details) {
43
+ const facts = [`phase: ${details.phase}`, `after ${Math.max(0, Math.round(details.elapsedMs))} ms`];
44
+ if (details.online !== void 0) facts.push(`online: ${details.online}`);
45
+ if (details.stage) facts.push(`stage: ${details.stage}`);
46
+ const tail = ` (${facts.join(", ")})`;
47
+ switch (details.phase) {
48
+ case "rejected":
49
+ return `Media server rejected the connection: ${details.reason || "rejected-before-connection-success"}${tail}`;
50
+ case "timeout":
51
+ return `Timed out connecting to media socket${tail}`;
52
+ case "after-open":
53
+ return `Media socket closed before the room was ready: ${details.transportError || "unknown"}${tail}`;
54
+ default:
55
+ return `Error connecting to media socket: ${details.transportError || "unknown"}${tail}`;
56
+ }
57
+ }
58
+ const isMediaSocketConnectError = (error) => error instanceof MediaSocketConnectError || typeof error === "object" && error !== null && error.name === "MediaSocketConnectError";
59
+ const isNetworkOnlyMediaSocketError = (error) => isMediaSocketConnectError(error) && error.phase !== "rejected" && (error.online === false || error.phase === "before-open");
60
+ const isRetryableMediaSocketError = (error) => !isMediaSocketConnectError(error) || error.retryable;
61
+ function describeMediaSocketError(error, fallback = "Unable to connect. Check your credentials and try again.") {
62
+ if (!isMediaSocketConnectError(error)) return fallback;
63
+ if (error.phase === "rejected") {
64
+ switch (error.reason) {
65
+ case "invalid-credentials":
66
+ return "The room did not accept these credentials. Check the room ID and your access, or rejoin the room.";
67
+ case "meeting-minutes-unavailable":
68
+ return "This room cannot start because its account has no meeting minutes left. Contact the room host.";
69
+ case "invalid-request":
70
+ return "The connection request was incomplete or invalid. Check the room details and try again.";
71
+ case "api-check-failed":
72
+ return "The media server could not verify this room right now. Please try again shortly.";
73
+ default:
74
+ return "The media server closed the connection before the room was ready. Please try again.";
75
+ }
76
+ }
77
+ if (error.online === false) return "You appear to be offline. Check your internet connection and try again.";
78
+ if (error.phase === "before-open") {
79
+ return "Could not reach the media server. Check your network or firewall and try again.";
80
+ }
81
+ if (error.phase === "timeout") return "Connecting to the media server timed out. Please try again.";
82
+ return "The media server closed the connection before the room was ready. Please try again.";
83
+ }
84
+ const validateAlphanumeric = async ({ str }) => {
85
+ let code, i, len;
86
+ for (i = 0, len = str.length; i < len; i++) {
87
+ code = str.charCodeAt(i);
88
+ if (!(code > 47 && code < 58) && // numeric (0-9)
89
+ !(code > 64 && code < 91) && // upper alpha (A-Z)
90
+ !(code > 96 && code < 123)) {
91
+ return false;
92
+ }
93
+ }
94
+ return true;
95
+ };
96
+ const backupByParent = /* @__PURE__ */ new Map();
97
+ const CONSUMER_BACKUP_PREFER_DELAY_MS = 1500;
98
+ const rememberConsumerBackups = (altDomains) => {
99
+ for (const [parent, backup] of Object.entries(altDomains || {})) {
100
+ if (parent && backup && parent !== backup) backupByParent.set(parent, backup);
101
+ }
102
+ };
103
+ const forgetConsumerBackups = () => backupByParent.clear();
104
+ const preferredConsumerBackup = (ip, consumeSockets) => {
105
+ const backup = backupByParent.get(ip);
106
+ if (!backup) return null;
107
+ const connected = (consumeSockets || []).some((entry) => {
108
+ const socket = entry?.[backup];
109
+ return Boolean(socket) && socket.connected !== false;
110
+ });
111
+ return connected ? backup : null;
112
+ };
113
+ const consumerBackupPreferDelay = (ip, consumeSockets) => preferredConsumerBackup(ip, consumeSockets) ? CONSUMER_BACKUP_PREFER_DELAY_MS : 0;
114
+ function audioProcessingConstraints(options) {
115
+ const result = {};
116
+ if (options === void 0) return result;
117
+ if (!options || typeof options !== "object" || Array.isArray(options)) throw new TypeError("Invalid audioProcessing");
118
+ for (const key of Object.keys(options)) {
119
+ if (!["echoCancellation", "noiseSuppression", "autoGainControl"].includes(key)) throw new TypeError("Unsupported audioProcessing option");
120
+ const value = options[key];
121
+ if (value !== void 0 && typeof value !== "boolean") throw new TypeError("Audio processing options must be boolean");
122
+ if (value !== void 0) result[key] = value;
123
+ }
124
+ return result;
125
+ }
126
+ async function applyAudioProcessing(track, options) {
127
+ const selected = audioProcessingConstraints(options);
128
+ if (!Object.keys(selected).length) return;
129
+ await track.applyConstraints({ ...track.getConstraints(), ...selected });
130
+ }
131
+ export {
132
+ CONSUMER_BACKUP_PREFER_DELAY_MS as C,
133
+ MEDIA_CONNECTION_REJECTION_REASONS as M,
134
+ MediaSocketConnectError as a,
135
+ currentOnlineState as b,
136
+ consumerBackupPreferDelay as c,
137
+ formatMediaSocketError as d,
138
+ isNetworkOnlyMediaSocketError as e,
139
+ forgetConsumerBackups as f,
140
+ isRetryableMediaSocketError as g,
141
+ describeMediaSocketError as h,
142
+ isMediaSocketConnectError as i,
143
+ applyAudioProcessing as j,
144
+ audioProcessingConstraints as k,
145
+ normalizeRejectionReason as n,
146
+ preferredConsumerBackup as p,
147
+ rememberConsumerBackups as r,
148
+ validateAlphanumeric as v
149
+ };
150
+ //# sourceMappingURL=audioProcessing-Ca5wm1nV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audioProcessing-Ca5wm1nV.js","sources":["../src/sockets/mediaSocketErrors.ts","../src/methods/utils/validateAlphanumeric.ts","../src/consumers/consumerBackupPreference.ts","../src/consumers/audioProcessing.ts"],"sourcesContent":["/**\n * Media socket connection errors.\n *\n * A media node that refuses a handshake emits `connection-rejected { reason, stage }` just before it closes the socket\n * (media admission v2). `connectSocket` turns that, and every other way a connection can fail, into a\n * `MediaSocketConnectError` that says what happened, when and whether trying again can help.\n */\n\n/** Reasons a media node sends with `connection-rejected`. */\nexport type MediaConnectionRejectionReason =\n | 'invalid-credentials'\n | 'meeting-minutes-unavailable'\n | 'api-check-failed'\n | 'invalid-request'\n | 'rejected-before-connection-success';\n\n/**\n * Where the attempt stopped:\n * - `before-open`: the transport never opened (offline, DNS, TLS, firewall, server down);\n * - `after-open`: the transport opened but closed or errored before `connection-success`;\n * - `rejected`: the server refused the handshake and said why (`reason`);\n * - `timeout`: nothing settled in time.\n */\nexport type MediaSocketConnectPhase = 'before-open' | 'after-open' | 'rejected' | 'timeout';\n\nexport const MEDIA_CONNECTION_REJECTION_REASONS: readonly MediaConnectionRejectionReason[] = [\n 'invalid-credentials',\n 'meeting-minutes-unavailable',\n 'api-check-failed',\n 'invalid-request',\n 'rejected-before-connection-success',\n];\n\n/** Rejections that will fail the same way if retried with the same credentials. */\nconst PERMANENT_REJECTIONS = new Set<string>(['invalid-credentials', 'meeting-minutes-unavailable', 'invalid-request']);\n\nexport interface MediaSocketConnectErrorDetails {\n phase: MediaSocketConnectPhase;\n /** Rejection reason from the server (phase `rejected`), else undefined. */\n reason?: MediaConnectionRejectionReason;\n /** Server-side admission stage from `connection-rejected`, e.g. `api-check-rejected`. */\n stage?: string;\n /** Milliseconds from the start of the attempt to the failure. */\n elapsedMs: number;\n /** `navigator.onLine` when available. `false` points at the device's network, not the server. */\n online?: boolean;\n /** Underlying transport error or disconnect reason, e.g. `websocket error`, `io server disconnect`. */\n transportError?: string;\n /** Socket link the attempt targeted. */\n link?: string;\n}\n\nexport class MediaSocketConnectError extends Error implements MediaSocketConnectErrorDetails {\n readonly phase: MediaSocketConnectPhase;\n readonly reason?: MediaConnectionRejectionReason;\n readonly stage?: string;\n readonly elapsedMs: number;\n readonly online?: boolean;\n readonly transportError?: string;\n readonly link?: string;\n /** False when retrying with the same credentials cannot succeed (bad credentials, no minutes, bad request). */\n readonly retryable: boolean;\n\n constructor(details: MediaSocketConnectErrorDetails) {\n super(formatMediaSocketError(details));\n Object.setPrototypeOf(this, MediaSocketConnectError.prototype);\n this.name = 'MediaSocketConnectError';\n this.phase = details.phase;\n this.reason = details.reason;\n this.stage = details.stage;\n this.elapsedMs = details.elapsedMs;\n this.online = details.online;\n this.transportError = details.transportError;\n this.link = details.link;\n this.retryable = !(details.phase === 'rejected' && details.reason && PERMANENT_REJECTIONS.has(details.reason));\n }\n}\n\n/** Maps any reason string from the server onto a known reason (unknown values become `rejected-before-connection-success`). */\nexport const normalizeRejectionReason = (reason: unknown): MediaConnectionRejectionReason =>\n (MEDIA_CONNECTION_REJECTION_REASONS as readonly string[]).includes(String(reason))\n ? (reason as MediaConnectionRejectionReason)\n : 'rejected-before-connection-success';\n\n/** `navigator.onLine` where it exists (browsers, some React Native runtimes), else undefined. */\nexport const currentOnlineState = (): boolean | undefined => {\n try {\n const nav = (globalThis as { navigator?: { onLine?: unknown } }).navigator;\n return typeof nav?.onLine === 'boolean' ? nav.onLine : undefined;\n } catch {\n return undefined;\n }\n};\n\n/** Technical one-liner for logs; keeps the historic \"Error connecting to media socket:\" prefix for transport failures. */\nexport function formatMediaSocketError(details: MediaSocketConnectErrorDetails): string {\n const facts = [`phase: ${details.phase}`, `after ${Math.max(0, Math.round(details.elapsedMs))} ms`];\n if (details.online !== undefined) facts.push(`online: ${details.online}`);\n if (details.stage) facts.push(`stage: ${details.stage}`);\n const tail = ` (${facts.join(', ')})`;\n switch (details.phase) {\n case 'rejected':\n return `Media server rejected the connection: ${details.reason || 'rejected-before-connection-success'}${tail}`;\n case 'timeout':\n return `Timed out connecting to media socket${tail}`;\n case 'after-open':\n return `Media socket closed before the room was ready: ${details.transportError || 'unknown'}${tail}`;\n default:\n return `Error connecting to media socket: ${details.transportError || 'unknown'}${tail}`;\n }\n}\n\nexport const isMediaSocketConnectError = (error: unknown): error is MediaSocketConnectError =>\n error instanceof MediaSocketConnectError ||\n (typeof error === 'object' && error !== null && (error as { name?: unknown }).name === 'MediaSocketConnectError');\n\n/**\n * True when the attempt failed because of the device's network (offline, or the transport never opened) rather than\n * a server refusal. Join pages do not count these toward the attempt limit: they are not credential guesses.\n */\nexport const isNetworkOnlyMediaSocketError = (error: unknown): boolean =>\n isMediaSocketConnectError(error) &&\n error.phase !== 'rejected' &&\n (error.online === false || error.phase === 'before-open');\n\n/** False only for rejections that cannot succeed on retry with the same credentials. */\nexport const isRetryableMediaSocketError = (error: unknown): boolean =>\n !isMediaSocketConnectError(error) || error.retryable;\n\n/** A sentence suitable for an end user (alert/toast). Falls back to `fallback` for unknown errors. */\nexport function describeMediaSocketError(\n error: unknown,\n fallback = 'Unable to connect. Check your credentials and try again.',\n): string {\n if (!isMediaSocketConnectError(error)) return fallback;\n if (error.phase === 'rejected') {\n switch (error.reason) {\n case 'invalid-credentials':\n return 'The room did not accept these credentials. Check the room ID and your access, or rejoin the room.';\n case 'meeting-minutes-unavailable':\n return 'This room cannot start because its account has no meeting minutes left. Contact the room host.';\n case 'invalid-request':\n return 'The connection request was incomplete or invalid. Check the room details and try again.';\n case 'api-check-failed':\n return 'The media server could not verify this room right now. Please try again shortly.';\n default:\n return 'The media server closed the connection before the room was ready. Please try again.';\n }\n }\n if (error.online === false) return 'You appear to be offline. Check your internet connection and try again.';\n if (error.phase === 'before-open') {\n return 'Could not reach the media server. Check your network or firewall and try again.';\n }\n if (error.phase === 'timeout') return 'Connecting to the media server timed out. Please try again.';\n return 'The media server closed the connection before the room was ready. Please try again.';\n}\n","\nexport interface ValidateAlphanumericOptions {\n str: string;\n}\n\n// Export the type definition for the function\nexport type ValidateAlphanumericType = (options: ValidateAlphanumericOptions) => Promise<boolean>;\n\n/**\n * Validates if the given string contains only alphanumeric characters.\n *\n * @param {ValidateAlphanumericOptions} options - The options containing the string to validate.\n * @param {string} options.str - The string to be validated.\n * @returns {Promise<boolean>} - A promise that resolves to `true` if the string is alphanumeric, otherwise `false`.\n * \n * @example\n * ```typescript \n * const isValid = await validateAlphanumeric({ str: \"abc123\" });\n * console.log(isValid);\n * // Output: true\n * ```\n */\n\n\nconst validateAlphanumeric = async ({ str }: ValidateAlphanumericOptions): Promise<boolean> => {\n let code: number, i: number, len: number;\n\n for (i = 0, len = str.length; i < len; i++) {\n code = str.charCodeAt(i);\n if (\n !(code > 47 && code < 58) && // numeric (0-9)\n !(code > 64 && code < 91) && // upper alpha (A-Z)\n !(code > 96 && code < 123) // lower alpha (a-z)\n ) {\n return false;\n }\n }\n return true;\n};\n\nexport { validateAlphanumeric };\n","/**\n * Consumer backup preference (server feature consumer-backup-v1).\n *\n * When a consuming node gets busy, the server attaches a backup node and tells every listener\n * `alt_domains: { <busy node>: <backup node> }`. Listeners stay on the busy node for what they already receive, but a\n * stream announced after that is taken from the backup: when the busy node announces it and the backup is connected,\n * the client waits briefly for the backup's own announcement (the backup gets each new stream a moment later) and only\n * falls back to the busy node if it does not come. Consumption is de-duplicated by producer id, so whichever node is\n * used first wins and the other announcement is ignored.\n *\n * The request is never sent to the backup for a stream the backup has not announced: a consume the backup cannot serve\n * fails without an error and the de-duplication would then skip the busy node's copy (staging test, Oct 9 2026).\n */\nconst backupByParent = new Map<string, string>();\n\n/** How long a busy node's announcement waits for the backup's (ms). */\nexport const CONSUMER_BACKUP_PREFER_DELAY_MS = 1500;\n\n/** Records the server's `{ busy node: backup node }` map (from `updateConsumingDomains` / `getDomains`). */\nexport const rememberConsumerBackups = (altDomains?: Record<string, string> | null): void => {\n for (const [parent, backup] of Object.entries(altDomains || {})) {\n if (parent && backup && parent !== backup) backupByParent.set(parent, backup);\n }\n};\n\nexport const forgetConsumerBackups = (): void => backupByParent.clear();\n\ntype SocketEntry = Record<string, { connected?: boolean } | undefined>;\n\n/** The connected backup to prefer over `ip`, or null. */\nexport const preferredConsumerBackup = (ip: string, consumeSockets?: SocketEntry[] | null): string | null => {\n const backup = backupByParent.get(ip);\n if (!backup) return null;\n const connected = (consumeSockets || []).some((entry) => {\n const socket = entry?.[backup];\n return Boolean(socket) && socket!.connected !== false;\n });\n return connected ? backup : null;\n};\n\n/** Delay (ms) before consuming a stream announced by `ip`: non-zero only when a connected backup should win. */\nexport const consumerBackupPreferDelay = (ip: string, consumeSockets?: SocketEntry[] | null): number =>\n preferredConsumerBackup(ip, consumeSockets) ? CONSUMER_BACKUP_PREFER_DELAY_MS : 0;\n","export type AudioProcessingOptions = {\n echoCancellation?: boolean;\n noiseSuppression?: boolean;\n autoGainControl?: boolean;\n};\n\nexport function audioProcessingConstraints(options?: AudioProcessingOptions): MediaTrackConstraints {\n const result: MediaTrackConstraints = {};\n if (options === undefined) return result;\n if (!options || typeof options !== 'object' || Array.isArray(options)) throw new TypeError('Invalid audioProcessing');\n for (const key of Object.keys(options)) {\n if (!['echoCancellation', 'noiseSuppression', 'autoGainControl'].includes(key)) throw new TypeError('Unsupported audioProcessing option');\n const value = options[key as keyof AudioProcessingOptions];\n if (value !== undefined && typeof value !== 'boolean') throw new TypeError('Audio processing options must be boolean');\n if (value !== undefined) result[key as keyof AudioProcessingOptions] = value;\n }\n return result;\n}\n\n// applyConstraints replaces the constraint set: merge to retain device and\n// capture choices unrelated to the three processing preferences.\nexport async function applyAudioProcessing(track: MediaStreamTrack, options?: AudioProcessingOptions): Promise<void> {\n const selected = audioProcessingConstraints(options);\n if (!Object.keys(selected).length) return;\n await track.applyConstraints({ ...track.getConstraints(), ...selected });\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ const MEDIA_CONNECTION_REJECTION_REASONS = [
3
+ "invalid-credentials",
4
+ "meeting-minutes-unavailable",
5
+ "api-check-failed",
6
+ "invalid-request",
7
+ "rejected-before-connection-success"
8
+ ];
9
+ const PERMANENT_REJECTIONS = /* @__PURE__ */ new Set(["invalid-credentials", "meeting-minutes-unavailable", "invalid-request"]);
10
+ class MediaSocketConnectError extends Error {
11
+ phase;
12
+ reason;
13
+ stage;
14
+ elapsedMs;
15
+ online;
16
+ transportError;
17
+ link;
18
+ /** False when retrying with the same credentials cannot succeed (bad credentials, no minutes, bad request). */
19
+ retryable;
20
+ constructor(details) {
21
+ super(formatMediaSocketError(details));
22
+ Object.setPrototypeOf(this, MediaSocketConnectError.prototype);
23
+ this.name = "MediaSocketConnectError";
24
+ this.phase = details.phase;
25
+ this.reason = details.reason;
26
+ this.stage = details.stage;
27
+ this.elapsedMs = details.elapsedMs;
28
+ this.online = details.online;
29
+ this.transportError = details.transportError;
30
+ this.link = details.link;
31
+ this.retryable = !(details.phase === "rejected" && details.reason && PERMANENT_REJECTIONS.has(details.reason));
32
+ }
33
+ }
34
+ const normalizeRejectionReason = (reason) => MEDIA_CONNECTION_REJECTION_REASONS.includes(String(reason)) ? reason : "rejected-before-connection-success";
35
+ const currentOnlineState = () => {
36
+ try {
37
+ const nav = globalThis.navigator;
38
+ return typeof nav?.onLine === "boolean" ? nav.onLine : void 0;
39
+ } catch {
40
+ return void 0;
41
+ }
42
+ };
43
+ function formatMediaSocketError(details) {
44
+ const facts = [`phase: ${details.phase}`, `after ${Math.max(0, Math.round(details.elapsedMs))} ms`];
45
+ if (details.online !== void 0) facts.push(`online: ${details.online}`);
46
+ if (details.stage) facts.push(`stage: ${details.stage}`);
47
+ const tail = ` (${facts.join(", ")})`;
48
+ switch (details.phase) {
49
+ case "rejected":
50
+ return `Media server rejected the connection: ${details.reason || "rejected-before-connection-success"}${tail}`;
51
+ case "timeout":
52
+ return `Timed out connecting to media socket${tail}`;
53
+ case "after-open":
54
+ return `Media socket closed before the room was ready: ${details.transportError || "unknown"}${tail}`;
55
+ default:
56
+ return `Error connecting to media socket: ${details.transportError || "unknown"}${tail}`;
57
+ }
58
+ }
59
+ const isMediaSocketConnectError = (error) => error instanceof MediaSocketConnectError || typeof error === "object" && error !== null && error.name === "MediaSocketConnectError";
60
+ const isNetworkOnlyMediaSocketError = (error) => isMediaSocketConnectError(error) && error.phase !== "rejected" && (error.online === false || error.phase === "before-open");
61
+ const isRetryableMediaSocketError = (error) => !isMediaSocketConnectError(error) || error.retryable;
62
+ function describeMediaSocketError(error, fallback = "Unable to connect. Check your credentials and try again.") {
63
+ if (!isMediaSocketConnectError(error)) return fallback;
64
+ if (error.phase === "rejected") {
65
+ switch (error.reason) {
66
+ case "invalid-credentials":
67
+ return "The room did not accept these credentials. Check the room ID and your access, or rejoin the room.";
68
+ case "meeting-minutes-unavailable":
69
+ return "This room cannot start because its account has no meeting minutes left. Contact the room host.";
70
+ case "invalid-request":
71
+ return "The connection request was incomplete or invalid. Check the room details and try again.";
72
+ case "api-check-failed":
73
+ return "The media server could not verify this room right now. Please try again shortly.";
74
+ default:
75
+ return "The media server closed the connection before the room was ready. Please try again.";
76
+ }
77
+ }
78
+ if (error.online === false) return "You appear to be offline. Check your internet connection and try again.";
79
+ if (error.phase === "before-open") {
80
+ return "Could not reach the media server. Check your network or firewall and try again.";
81
+ }
82
+ if (error.phase === "timeout") return "Connecting to the media server timed out. Please try again.";
83
+ return "The media server closed the connection before the room was ready. Please try again.";
84
+ }
85
+ const validateAlphanumeric = async ({ str }) => {
86
+ let code, i, len;
87
+ for (i = 0, len = str.length; i < len; i++) {
88
+ code = str.charCodeAt(i);
89
+ if (!(code > 47 && code < 58) && // numeric (0-9)
90
+ !(code > 64 && code < 91) && // upper alpha (A-Z)
91
+ !(code > 96 && code < 123)) {
92
+ return false;
93
+ }
94
+ }
95
+ return true;
96
+ };
97
+ const backupByParent = /* @__PURE__ */ new Map();
98
+ const CONSUMER_BACKUP_PREFER_DELAY_MS = 1500;
99
+ const rememberConsumerBackups = (altDomains) => {
100
+ for (const [parent, backup] of Object.entries(altDomains || {})) {
101
+ if (parent && backup && parent !== backup) backupByParent.set(parent, backup);
102
+ }
103
+ };
104
+ const forgetConsumerBackups = () => backupByParent.clear();
105
+ const preferredConsumerBackup = (ip, consumeSockets) => {
106
+ const backup = backupByParent.get(ip);
107
+ if (!backup) return null;
108
+ const connected = (consumeSockets || []).some((entry) => {
109
+ const socket = entry?.[backup];
110
+ return Boolean(socket) && socket.connected !== false;
111
+ });
112
+ return connected ? backup : null;
113
+ };
114
+ const consumerBackupPreferDelay = (ip, consumeSockets) => preferredConsumerBackup(ip, consumeSockets) ? CONSUMER_BACKUP_PREFER_DELAY_MS : 0;
115
+ function audioProcessingConstraints(options) {
116
+ const result = {};
117
+ if (options === void 0) return result;
118
+ if (!options || typeof options !== "object" || Array.isArray(options)) throw new TypeError("Invalid audioProcessing");
119
+ for (const key of Object.keys(options)) {
120
+ if (!["echoCancellation", "noiseSuppression", "autoGainControl"].includes(key)) throw new TypeError("Unsupported audioProcessing option");
121
+ const value = options[key];
122
+ if (value !== void 0 && typeof value !== "boolean") throw new TypeError("Audio processing options must be boolean");
123
+ if (value !== void 0) result[key] = value;
124
+ }
125
+ return result;
126
+ }
127
+ async function applyAudioProcessing(track, options) {
128
+ const selected = audioProcessingConstraints(options);
129
+ if (!Object.keys(selected).length) return;
130
+ await track.applyConstraints({ ...track.getConstraints(), ...selected });
131
+ }
132
+ exports.CONSUMER_BACKUP_PREFER_DELAY_MS = CONSUMER_BACKUP_PREFER_DELAY_MS;
133
+ exports.MEDIA_CONNECTION_REJECTION_REASONS = MEDIA_CONNECTION_REJECTION_REASONS;
134
+ exports.MediaSocketConnectError = MediaSocketConnectError;
135
+ exports.applyAudioProcessing = applyAudioProcessing;
136
+ exports.audioProcessingConstraints = audioProcessingConstraints;
137
+ exports.consumerBackupPreferDelay = consumerBackupPreferDelay;
138
+ exports.currentOnlineState = currentOnlineState;
139
+ exports.describeMediaSocketError = describeMediaSocketError;
140
+ exports.forgetConsumerBackups = forgetConsumerBackups;
141
+ exports.formatMediaSocketError = formatMediaSocketError;
142
+ exports.isMediaSocketConnectError = isMediaSocketConnectError;
143
+ exports.isNetworkOnlyMediaSocketError = isNetworkOnlyMediaSocketError;
144
+ exports.isRetryableMediaSocketError = isRetryableMediaSocketError;
145
+ exports.normalizeRejectionReason = normalizeRejectionReason;
146
+ exports.preferredConsumerBackup = preferredConsumerBackup;
147
+ exports.rememberConsumerBackups = rememberConsumerBackups;
148
+ exports.validateAlphanumeric = validateAlphanumeric;
149
+ //# sourceMappingURL=audioProcessing-VCbu70Jt.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audioProcessing-VCbu70Jt.cjs","sources":["../src/sockets/mediaSocketErrors.ts","../src/methods/utils/validateAlphanumeric.ts","../src/consumers/consumerBackupPreference.ts","../src/consumers/audioProcessing.ts"],"sourcesContent":["/**\n * Media socket connection errors.\n *\n * A media node that refuses a handshake emits `connection-rejected { reason, stage }` just before it closes the socket\n * (media admission v2). `connectSocket` turns that, and every other way a connection can fail, into a\n * `MediaSocketConnectError` that says what happened, when and whether trying again can help.\n */\n\n/** Reasons a media node sends with `connection-rejected`. */\nexport type MediaConnectionRejectionReason =\n | 'invalid-credentials'\n | 'meeting-minutes-unavailable'\n | 'api-check-failed'\n | 'invalid-request'\n | 'rejected-before-connection-success';\n\n/**\n * Where the attempt stopped:\n * - `before-open`: the transport never opened (offline, DNS, TLS, firewall, server down);\n * - `after-open`: the transport opened but closed or errored before `connection-success`;\n * - `rejected`: the server refused the handshake and said why (`reason`);\n * - `timeout`: nothing settled in time.\n */\nexport type MediaSocketConnectPhase = 'before-open' | 'after-open' | 'rejected' | 'timeout';\n\nexport const MEDIA_CONNECTION_REJECTION_REASONS: readonly MediaConnectionRejectionReason[] = [\n 'invalid-credentials',\n 'meeting-minutes-unavailable',\n 'api-check-failed',\n 'invalid-request',\n 'rejected-before-connection-success',\n];\n\n/** Rejections that will fail the same way if retried with the same credentials. */\nconst PERMANENT_REJECTIONS = new Set<string>(['invalid-credentials', 'meeting-minutes-unavailable', 'invalid-request']);\n\nexport interface MediaSocketConnectErrorDetails {\n phase: MediaSocketConnectPhase;\n /** Rejection reason from the server (phase `rejected`), else undefined. */\n reason?: MediaConnectionRejectionReason;\n /** Server-side admission stage from `connection-rejected`, e.g. `api-check-rejected`. */\n stage?: string;\n /** Milliseconds from the start of the attempt to the failure. */\n elapsedMs: number;\n /** `navigator.onLine` when available. `false` points at the device's network, not the server. */\n online?: boolean;\n /** Underlying transport error or disconnect reason, e.g. `websocket error`, `io server disconnect`. */\n transportError?: string;\n /** Socket link the attempt targeted. */\n link?: string;\n}\n\nexport class MediaSocketConnectError extends Error implements MediaSocketConnectErrorDetails {\n readonly phase: MediaSocketConnectPhase;\n readonly reason?: MediaConnectionRejectionReason;\n readonly stage?: string;\n readonly elapsedMs: number;\n readonly online?: boolean;\n readonly transportError?: string;\n readonly link?: string;\n /** False when retrying with the same credentials cannot succeed (bad credentials, no minutes, bad request). */\n readonly retryable: boolean;\n\n constructor(details: MediaSocketConnectErrorDetails) {\n super(formatMediaSocketError(details));\n Object.setPrototypeOf(this, MediaSocketConnectError.prototype);\n this.name = 'MediaSocketConnectError';\n this.phase = details.phase;\n this.reason = details.reason;\n this.stage = details.stage;\n this.elapsedMs = details.elapsedMs;\n this.online = details.online;\n this.transportError = details.transportError;\n this.link = details.link;\n this.retryable = !(details.phase === 'rejected' && details.reason && PERMANENT_REJECTIONS.has(details.reason));\n }\n}\n\n/** Maps any reason string from the server onto a known reason (unknown values become `rejected-before-connection-success`). */\nexport const normalizeRejectionReason = (reason: unknown): MediaConnectionRejectionReason =>\n (MEDIA_CONNECTION_REJECTION_REASONS as readonly string[]).includes(String(reason))\n ? (reason as MediaConnectionRejectionReason)\n : 'rejected-before-connection-success';\n\n/** `navigator.onLine` where it exists (browsers, some React Native runtimes), else undefined. */\nexport const currentOnlineState = (): boolean | undefined => {\n try {\n const nav = (globalThis as { navigator?: { onLine?: unknown } }).navigator;\n return typeof nav?.onLine === 'boolean' ? nav.onLine : undefined;\n } catch {\n return undefined;\n }\n};\n\n/** Technical one-liner for logs; keeps the historic \"Error connecting to media socket:\" prefix for transport failures. */\nexport function formatMediaSocketError(details: MediaSocketConnectErrorDetails): string {\n const facts = [`phase: ${details.phase}`, `after ${Math.max(0, Math.round(details.elapsedMs))} ms`];\n if (details.online !== undefined) facts.push(`online: ${details.online}`);\n if (details.stage) facts.push(`stage: ${details.stage}`);\n const tail = ` (${facts.join(', ')})`;\n switch (details.phase) {\n case 'rejected':\n return `Media server rejected the connection: ${details.reason || 'rejected-before-connection-success'}${tail}`;\n case 'timeout':\n return `Timed out connecting to media socket${tail}`;\n case 'after-open':\n return `Media socket closed before the room was ready: ${details.transportError || 'unknown'}${tail}`;\n default:\n return `Error connecting to media socket: ${details.transportError || 'unknown'}${tail}`;\n }\n}\n\nexport const isMediaSocketConnectError = (error: unknown): error is MediaSocketConnectError =>\n error instanceof MediaSocketConnectError ||\n (typeof error === 'object' && error !== null && (error as { name?: unknown }).name === 'MediaSocketConnectError');\n\n/**\n * True when the attempt failed because of the device's network (offline, or the transport never opened) rather than\n * a server refusal. Join pages do not count these toward the attempt limit: they are not credential guesses.\n */\nexport const isNetworkOnlyMediaSocketError = (error: unknown): boolean =>\n isMediaSocketConnectError(error) &&\n error.phase !== 'rejected' &&\n (error.online === false || error.phase === 'before-open');\n\n/** False only for rejections that cannot succeed on retry with the same credentials. */\nexport const isRetryableMediaSocketError = (error: unknown): boolean =>\n !isMediaSocketConnectError(error) || error.retryable;\n\n/** A sentence suitable for an end user (alert/toast). Falls back to `fallback` for unknown errors. */\nexport function describeMediaSocketError(\n error: unknown,\n fallback = 'Unable to connect. Check your credentials and try again.',\n): string {\n if (!isMediaSocketConnectError(error)) return fallback;\n if (error.phase === 'rejected') {\n switch (error.reason) {\n case 'invalid-credentials':\n return 'The room did not accept these credentials. Check the room ID and your access, or rejoin the room.';\n case 'meeting-minutes-unavailable':\n return 'This room cannot start because its account has no meeting minutes left. Contact the room host.';\n case 'invalid-request':\n return 'The connection request was incomplete or invalid. Check the room details and try again.';\n case 'api-check-failed':\n return 'The media server could not verify this room right now. Please try again shortly.';\n default:\n return 'The media server closed the connection before the room was ready. Please try again.';\n }\n }\n if (error.online === false) return 'You appear to be offline. Check your internet connection and try again.';\n if (error.phase === 'before-open') {\n return 'Could not reach the media server. Check your network or firewall and try again.';\n }\n if (error.phase === 'timeout') return 'Connecting to the media server timed out. Please try again.';\n return 'The media server closed the connection before the room was ready. Please try again.';\n}\n","\nexport interface ValidateAlphanumericOptions {\n str: string;\n}\n\n// Export the type definition for the function\nexport type ValidateAlphanumericType = (options: ValidateAlphanumericOptions) => Promise<boolean>;\n\n/**\n * Validates if the given string contains only alphanumeric characters.\n *\n * @param {ValidateAlphanumericOptions} options - The options containing the string to validate.\n * @param {string} options.str - The string to be validated.\n * @returns {Promise<boolean>} - A promise that resolves to `true` if the string is alphanumeric, otherwise `false`.\n * \n * @example\n * ```typescript \n * const isValid = await validateAlphanumeric({ str: \"abc123\" });\n * console.log(isValid);\n * // Output: true\n * ```\n */\n\n\nconst validateAlphanumeric = async ({ str }: ValidateAlphanumericOptions): Promise<boolean> => {\n let code: number, i: number, len: number;\n\n for (i = 0, len = str.length; i < len; i++) {\n code = str.charCodeAt(i);\n if (\n !(code > 47 && code < 58) && // numeric (0-9)\n !(code > 64 && code < 91) && // upper alpha (A-Z)\n !(code > 96 && code < 123) // lower alpha (a-z)\n ) {\n return false;\n }\n }\n return true;\n};\n\nexport { validateAlphanumeric };\n","/**\n * Consumer backup preference (server feature consumer-backup-v1).\n *\n * When a consuming node gets busy, the server attaches a backup node and tells every listener\n * `alt_domains: { <busy node>: <backup node> }`. Listeners stay on the busy node for what they already receive, but a\n * stream announced after that is taken from the backup: when the busy node announces it and the backup is connected,\n * the client waits briefly for the backup's own announcement (the backup gets each new stream a moment later) and only\n * falls back to the busy node if it does not come. Consumption is de-duplicated by producer id, so whichever node is\n * used first wins and the other announcement is ignored.\n *\n * The request is never sent to the backup for a stream the backup has not announced: a consume the backup cannot serve\n * fails without an error and the de-duplication would then skip the busy node's copy (staging test, Oct 9 2026).\n */\nconst backupByParent = new Map<string, string>();\n\n/** How long a busy node's announcement waits for the backup's (ms). */\nexport const CONSUMER_BACKUP_PREFER_DELAY_MS = 1500;\n\n/** Records the server's `{ busy node: backup node }` map (from `updateConsumingDomains` / `getDomains`). */\nexport const rememberConsumerBackups = (altDomains?: Record<string, string> | null): void => {\n for (const [parent, backup] of Object.entries(altDomains || {})) {\n if (parent && backup && parent !== backup) backupByParent.set(parent, backup);\n }\n};\n\nexport const forgetConsumerBackups = (): void => backupByParent.clear();\n\ntype SocketEntry = Record<string, { connected?: boolean } | undefined>;\n\n/** The connected backup to prefer over `ip`, or null. */\nexport const preferredConsumerBackup = (ip: string, consumeSockets?: SocketEntry[] | null): string | null => {\n const backup = backupByParent.get(ip);\n if (!backup) return null;\n const connected = (consumeSockets || []).some((entry) => {\n const socket = entry?.[backup];\n return Boolean(socket) && socket!.connected !== false;\n });\n return connected ? backup : null;\n};\n\n/** Delay (ms) before consuming a stream announced by `ip`: non-zero only when a connected backup should win. */\nexport const consumerBackupPreferDelay = (ip: string, consumeSockets?: SocketEntry[] | null): number =>\n preferredConsumerBackup(ip, consumeSockets) ? CONSUMER_BACKUP_PREFER_DELAY_MS : 0;\n","export type AudioProcessingOptions = {\n echoCancellation?: boolean;\n noiseSuppression?: boolean;\n autoGainControl?: boolean;\n};\n\nexport function audioProcessingConstraints(options?: AudioProcessingOptions): MediaTrackConstraints {\n const result: MediaTrackConstraints = {};\n if (options === undefined) return result;\n if (!options || typeof options !== 'object' || Array.isArray(options)) throw new TypeError('Invalid audioProcessing');\n for (const key of Object.keys(options)) {\n if (!['echoCancellation', 'noiseSuppression', 'autoGainControl'].includes(key)) throw new TypeError('Unsupported audioProcessing option');\n const value = options[key as keyof AudioProcessingOptions];\n if (value !== undefined && typeof value !== 'boolean') throw new TypeError('Audio processing options must be boolean');\n if (value !== undefined) result[key as keyof AudioProcessingOptions] = value;\n }\n return result;\n}\n\n// applyConstraints replaces the constraint set: merge to retain device and\n// capture choices unrelated to the three processing preferences.\nexport async function applyAudioProcessing(track: MediaStreamTrack, options?: AudioProcessingOptions): Promise<void> {\n const selected = audioProcessingConstraints(options);\n if (!Object.keys(selected).length) return;\n await track.applyConstraints({ ...track.getConstraints(), ...selected });\n}\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
1
  import { Stream, Participant, ReorderStreamsType, ReorderStreamsParameters, PrepopulateUserMediaParameters, PrepopulateUserMediaType, GetVideosType, RePortType, RePortParameters, EventType } from '../types/types';
2
2
  export interface CloseAndResizeParameters extends ReorderStreamsParameters, PrepopulateUserMediaParameters, RePortParameters {
3
3
  allAudioStreams: (Stream | Participant)[];
4
+ /** Rendered audio-only players (React elements, Vue/Angular component descriptors). */
5
+ audioOnlyStreams?: any[];
4
6
  allVideoStreams: (Stream | Participant)[];
5
7
  activeNames: string[];
6
8
  participants: Participant[];
@@ -25,6 +27,7 @@ export interface CloseAndResizeParameters extends ReorderStreamsParameters, Prep
25
27
  updateMainWindow: boolean;
26
28
  updateActiveNames: (activeNames: string[]) => void;
27
29
  updateAllAudioStreams: (allAudioStreams: (Stream | Participant)[]) => void;
30
+ updateAudioOnlyStreams?: (audioOnlyStreams: any[]) => void;
28
31
  updateShareScreenStarted: (shareScreenStarted: boolean) => void;
29
32
  updateUpdateMainWindow: (updateMainWindow: boolean) => void;
30
33
  updateNewLimitedStreams: (newLimitedStreams: (Stream | Participant)[]) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"closeAndResize.d.ts","sourceRoot":"","sources":["../../src/consumers/closeAndResize.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"closeAndResize.d.ts","sourceRoot":"","sources":["../../src/consumers/closeAndResize.ts"],"names":[],"mappings":"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"}
@@ -21,6 +21,12 @@ export interface ConnectIpsOptions {
21
21
  parameters: ConnectIpsParameters;
22
22
  }
23
23
  export type ConnectIpsType = (options: ConnectIpsOptions) => Promise<[Record<string, any>[], string[]]>;
24
+ /**
25
+ * Consume endpoints that refused these credentials (`connection-rejected` with a permanent reason). Domain updates call
26
+ * connectIps again and again; without this every update would retry the same refusal. Keyed by the caller's socket
27
+ * collection so another room (new credentials) starts clean.
28
+ */
29
+ export declare const CONSUME_REJECTION_COOLDOWN_MS = 60000;
24
30
  /**
25
31
  * Connects to remote IPs and manages socket connections.
26
32
  *
@@ -1 +1 @@
1
- {"version":3,"file":"connectIps.d.ts","sourceRoot":"","sources":["../../src/consumers/connectIps.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EACL,wBAAwB,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,kBAAkB,EAChH,wBAAwB,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,aAAa,EACxF,MAAM,gBAAgB,CAAC;AAExB,MAAM,WAAW,oBAAqB,SAAQ,wBAAwB,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,yBAAyB;IACpJ,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,iBAAiB,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACnD,qBAAqB,EAAE,CAAC,eAAe,EAAE,aAAa,EAAE,KAAK,IAAI,CAAC;IAGlE,cAAc,EAAE,kBAAkB,CAAC;IACnC,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;IAChD,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,aAAa,EAAE,CAAC;IACjC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,mBAAmB,CAAC;IACxC,oBAAoB,CAAC,EAAE,kBAAkB,CAAC;IAC1C,qBAAqB,CAAC,EAAE,mBAAmB,CAAC;IAC5C,UAAU,EAAE,oBAAoB,CAAC;CAClC;AAGD,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;AA0ExG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,eAAO,MAAM,UAAU,GAAU,wIAY9B,iBAAiB,KAAG,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CA+G/D,CAAC"}
1
+ {"version":3,"file":"connectIps.d.ts","sourceRoot":"","sources":["../../src/consumers/connectIps.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EACL,wBAAwB,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,kBAAkB,EAChH,wBAAwB,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,aAAa,EACxF,MAAM,gBAAgB,CAAC;AAExB,MAAM,WAAW,oBAAqB,SAAQ,wBAAwB,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,yBAAyB;IACpJ,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,iBAAiB,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACnD,qBAAqB,EAAE,CAAC,eAAe,EAAE,aAAa,EAAE,KAAK,IAAI,CAAC;IAGlE,cAAc,EAAE,kBAAkB,CAAC;IACnC,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;IAChD,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,aAAa,EAAE,CAAC;IACjC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,mBAAmB,CAAC;IACxC,oBAAoB,CAAC,EAAE,kBAAkB,CAAC;IAC1C,qBAAqB,CAAC,EAAE,mBAAmB,CAAC;IAC5C,UAAU,EAAE,oBAAoB,CAAC;CAClC;AAGD,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;AAaxG;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,QAAQ,CAAC;AA+EnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,eAAO,MAAM,UAAU,GAAU,wIAY9B,iBAAiB,KAAG,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CA8J/D,CAAC"}