@signalwire/js 4.0.0-dev-20260911195739 → 4.0.0-dev-20260914173015
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/dist/browser.mjs +89 -39
- package/dist/browser.mjs.map +1 -1
- package/dist/browser.umd.js +89 -39
- package/dist/browser.umd.js.map +1 -1
- package/dist/index.cjs +84 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +13 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +84 -40
- package/dist/index.mjs.map +1 -1
- package/dist/operators/index.cjs +1 -1
- package/dist/operators/index.mjs +1 -1
- package/dist/{operators-Cgz7QUVJ.cjs → operators-BJ6QW1VP.cjs} +13 -1
- package/dist/operators-BJ6QW1VP.cjs.map +1 -0
- package/dist/{operators-B0xqG7Eu.mjs → operators-BVxi3KpN.mjs} +8 -2
- package/dist/operators-BVxi3KpN.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/operators-B0xqG7Eu.mjs.map +0 -1
- package/dist/operators-Cgz7QUVJ.cjs.map +0 -1
package/dist/browser.mjs
CHANGED
|
@@ -9094,6 +9094,8 @@ const MEDIA_ACCESS_DENIAL_NAMES = [
|
|
|
9094
9094
|
"SecurityError",
|
|
9095
9095
|
"PermissionDeniedError"
|
|
9096
9096
|
];
|
|
9097
|
+
/** Error names browsers use when the capture hardware is already held exclusively. */
|
|
9098
|
+
const MEDIA_DEVICE_IN_USE_NAMES = ["NotReadableError", "TrackStartError"];
|
|
9097
9099
|
/** Default polling interval for RTCPeerConnection.getStats() in milliseconds. */
|
|
9098
9100
|
const DEFAULT_STATS_POLLING_INTERVAL_MS = 1e3;
|
|
9099
9101
|
/** Number of initial samples used to build a baseline for spike detection. */
|
|
@@ -9432,6 +9434,10 @@ var MediaTrackError = class extends Error {
|
|
|
9432
9434
|
function isMediaAccessDenial(originalError) {
|
|
9433
9435
|
return originalError instanceof Error && MEDIA_ACCESS_DENIAL_NAMES.includes(originalError.name);
|
|
9434
9436
|
}
|
|
9437
|
+
/** True when a `getUserMedia` rejection means the hardware is already held exclusively. */
|
|
9438
|
+
function isMediaDeviceInUse(originalError) {
|
|
9439
|
+
return originalError instanceof Error && MEDIA_DEVICE_IN_USE_NAMES.includes(originalError.name);
|
|
9440
|
+
}
|
|
9435
9441
|
/**
|
|
9436
9442
|
* Failure to acquire local media (camera, microphone, or screen capture)
|
|
9437
9443
|
* via `getUserMedia`/`getDisplayMedia`.
|
|
@@ -16050,38 +16056,32 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16050
16056
|
this.negotiationNeeded$.next();
|
|
16051
16057
|
};
|
|
16052
16058
|
this.updateSelectedInputDevice = async (kind, deviceInfo) => {
|
|
16059
|
+
const { localStream } = this;
|
|
16060
|
+
if (!localStream) {
|
|
16061
|
+
logger$17.warn("[RTCPeerConnectionController] No local stream available to update input device.");
|
|
16062
|
+
return;
|
|
16063
|
+
}
|
|
16064
|
+
const currentTrack = localStream.getTracks().find((track) => track.kind === kind);
|
|
16065
|
+
if (!currentTrack) {
|
|
16066
|
+
logger$17.debug(`[RTCPeerConnectionController] No ${kind} track to switch.`);
|
|
16067
|
+
return;
|
|
16068
|
+
}
|
|
16069
|
+
if (!deviceInfo) {
|
|
16070
|
+
logger$17.debug(`[RTCPeerConnectionController] ${kind} input device selected: none`);
|
|
16071
|
+
this.stopTrackSender(kind);
|
|
16072
|
+
return;
|
|
16073
|
+
}
|
|
16074
|
+
const constraints = {
|
|
16075
|
+
...currentTrack.getConstraints(),
|
|
16076
|
+
...this.deviceController.deviceInfoToConstraints(deviceInfo)
|
|
16077
|
+
};
|
|
16053
16078
|
try {
|
|
16054
|
-
const
|
|
16055
|
-
|
|
16056
|
-
|
|
16057
|
-
return;
|
|
16058
|
-
}
|
|
16059
|
-
logger$17.debug(`[RTCPeerConnectionController] Updating selected ${kind} input device:`, localStream.getTracks());
|
|
16060
|
-
const track = localStream.getTracks().find((track$1) => track$1.kind === kind);
|
|
16061
|
-
if (track) {
|
|
16062
|
-
this.transceiverController?.stopTrackSender(kind);
|
|
16063
|
-
this.localStreamController.removeTrack(track.id);
|
|
16064
|
-
logger$17.debug(`[RTCPeerConnectionController] Stopped existing ${kind} track: ${track.id}`, localStream.getTracks());
|
|
16065
|
-
if (!deviceInfo) {
|
|
16066
|
-
logger$17.debug(`[RTCPeerConnectionController] ${kind} input device selected: none`);
|
|
16067
|
-
return;
|
|
16068
|
-
}
|
|
16069
|
-
const streamTrack = (await this.getUserMedia({ [kind]: {
|
|
16070
|
-
...track.getConstraints(),
|
|
16071
|
-
...this.deviceController.deviceInfoToConstraints(deviceInfo)
|
|
16072
|
-
} })).getTracks().find((t) => t.kind === kind);
|
|
16073
|
-
if (streamTrack) {
|
|
16074
|
-
logger$17.debug(`[RTCPeerConnectionController] Adding new ${kind} track: ${streamTrack.id}`);
|
|
16075
|
-
this.localStreamController.addTrack(streamTrack);
|
|
16076
|
-
await this.transceiverController?.replaceSenderTrack(kind, streamTrack);
|
|
16077
|
-
logger$17.debug(`[RTCPeerConnectionController] Added new ${kind} track: ${streamTrack.id}`, this.localStream?.getTracks());
|
|
16078
|
-
}
|
|
16079
|
-
}
|
|
16080
|
-
logger$17.debug(`[RTCPeerConnectionController] ${kind} input device selected:`, deviceInfo?.label);
|
|
16079
|
+
const newTrack = await this.acquireInputTrack(kind, constraints, deviceInfo, currentTrack);
|
|
16080
|
+
await this.attachInputTrack(kind, newTrack, currentTrack);
|
|
16081
|
+
logger$17.debug(`[RTCPeerConnectionController] ${kind} input device selected:`, deviceInfo.label, newTrack.id);
|
|
16081
16082
|
} catch (error) {
|
|
16082
16083
|
logger$17.error(`[RTCPeerConnectionController] Failed to select ${kind} input device:`, error);
|
|
16083
16084
|
this._errors$.next(new MediaTrackError("updateSelectedInputDevice", kind, error));
|
|
16084
|
-
throw error;
|
|
16085
16085
|
}
|
|
16086
16086
|
};
|
|
16087
16087
|
this._isNegotiating$ = this.createBehaviorSubject(false);
|
|
@@ -16784,6 +16784,61 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16784
16784
|
this._localAudioPipeline.setInputTrack(newTrack);
|
|
16785
16785
|
}
|
|
16786
16786
|
/**
|
|
16787
|
+
* Capture the newly selected device, leaving the current capture running.
|
|
16788
|
+
*
|
|
16789
|
+
* A rejection must leave the current track sending, so nothing is released
|
|
16790
|
+
* until the replacement is in hand. The one exception is hardware that admits
|
|
16791
|
+
* a single opener — a phone's front and back cameras, typically — which
|
|
16792
|
+
* rejects the second capture until the first is closed.
|
|
16793
|
+
*/
|
|
16794
|
+
async acquireInputTrack(kind, constraints, deviceInfo, currentTrack) {
|
|
16795
|
+
try {
|
|
16796
|
+
return await this.captureTrack(kind, constraints, deviceInfo.deviceId);
|
|
16797
|
+
} catch (error) {
|
|
16798
|
+
if (!isMediaDeviceInUse(error)) throw error;
|
|
16799
|
+
logger$17.warn(`[RTCPeerConnectionController] ${kind} device is held exclusively; releasing the current capture to retry:`, error);
|
|
16800
|
+
const previousDeviceId = currentTrack.getSettings().deviceId;
|
|
16801
|
+
this.stopTrackSender(kind);
|
|
16802
|
+
try {
|
|
16803
|
+
return await this.captureTrack(kind, constraints, deviceInfo.deviceId);
|
|
16804
|
+
} catch (retryError) {
|
|
16805
|
+
await this.restorePreviousInputTrack(kind, constraints, previousDeviceId, currentTrack);
|
|
16806
|
+
throw retryError;
|
|
16807
|
+
}
|
|
16808
|
+
}
|
|
16809
|
+
}
|
|
16810
|
+
async captureTrack(kind, constraints, deviceId) {
|
|
16811
|
+
const { stream, fallbackLevel } = await getUserMediaWithFallback({ getUserMedia: async (c) => this.getUserMedia(c) }, { [kind]: constraints }, kind, deviceId);
|
|
16812
|
+
const track = stream.getTracks().find((t) => t.kind === kind);
|
|
16813
|
+
if (!track) {
|
|
16814
|
+
stream.getTracks().forEach((t) => t.stop());
|
|
16815
|
+
throw new MediaTrackError("updateSelectedInputDevice", kind, /* @__PURE__ */ new Error("getUserMedia returned no track of the requested kind"));
|
|
16816
|
+
}
|
|
16817
|
+
if (fallbackLevel !== "exact") logger$17.warn(`[RTCPeerConnectionController] ${kind} device acquired at fallback level '${fallbackLevel}'; the capture may not be the requested device.`);
|
|
16818
|
+
return track;
|
|
16819
|
+
}
|
|
16820
|
+
/** Best-effort return to the device that was released for an exclusive retry. */
|
|
16821
|
+
async restorePreviousInputTrack(kind, constraints, previousDeviceId, releasedTrack) {
|
|
16822
|
+
try {
|
|
16823
|
+
const restored = await this.captureTrack(kind, constraints, previousDeviceId);
|
|
16824
|
+
await this.attachInputTrack(kind, restored, releasedTrack);
|
|
16825
|
+
} catch (error) {
|
|
16826
|
+
logger$17.error(`[RTCPeerConnectionController] Failed to restore the previous ${kind} device:`, error);
|
|
16827
|
+
}
|
|
16828
|
+
}
|
|
16829
|
+
async attachInputTrack(kind, newTrack, oldTrack) {
|
|
16830
|
+
const pipelineOwnsAudio = kind === "audio" && this._localAudioPipeline;
|
|
16831
|
+
if (!pipelineOwnsAudio) try {
|
|
16832
|
+
await this.transceiverController?.replaceSenderTrack(kind, newTrack);
|
|
16833
|
+
} catch (error) {
|
|
16834
|
+
newTrack.stop();
|
|
16835
|
+
throw error;
|
|
16836
|
+
}
|
|
16837
|
+
this.localStreamController.removeTrack(oldTrack.id);
|
|
16838
|
+
this.localStreamController.addTrack(newTrack);
|
|
16839
|
+
if (pipelineOwnsAudio) this._localAudioPipeline?.setInputTrack(newTrack);
|
|
16840
|
+
}
|
|
16841
|
+
/**
|
|
16787
16842
|
* Return the lazily-created {@link LocalAudioPipeline}, constructing it on
|
|
16788
16843
|
* first access. On creation the current audio sender's track is routed
|
|
16789
16844
|
* through the pipeline (input → gain → analyser → destination) and the
|
|
@@ -17519,16 +17574,12 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17519
17574
|
const webrtcVertoMessage = WebrtcVerto(params);
|
|
17520
17575
|
const response = await this.webRtcCallSession.execute(webrtcVertoMessage);
|
|
17521
17576
|
const nonFatal = message.method === "verto.info" ? { fatal: false } : void 0;
|
|
17522
|
-
if (response.error) {
|
|
17523
|
-
const error = new JSONRPCError(response.error.code, response.error.message, response.error.data);
|
|
17524
|
-
this.reportLegError(error, this._rtcPeerConnectionsMap.get(params.callID), nonFatal);
|
|
17525
|
-
return response;
|
|
17526
|
-
}
|
|
17527
17577
|
const innerResult = getValueFrom(response, "result.result");
|
|
17528
|
-
|
|
17529
|
-
|
|
17578
|
+
const failure = response.error ?? innerResult?.error;
|
|
17579
|
+
if (failure) {
|
|
17580
|
+
const error = new JSONRPCError(failure.code, failure.message, failure.data);
|
|
17581
|
+
if (message.method === "verto.invite") throw error;
|
|
17530
17582
|
this.reportLegError(error, this._rtcPeerConnectionsMap.get(params.callID), nonFatal);
|
|
17531
|
-
return response;
|
|
17532
17583
|
}
|
|
17533
17584
|
return response;
|
|
17534
17585
|
}
|
|
@@ -17583,7 +17634,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17583
17634
|
if (rtcPeerConnController.isMainDevice) this._signalingStatus$.next(status);
|
|
17584
17635
|
}
|
|
17585
17636
|
processInviteResponse(response, rtcPeerConnController) {
|
|
17586
|
-
if (
|
|
17637
|
+
if (getValueFrom(response, "result.result.result.message") === "CALL CREATED") {
|
|
17587
17638
|
this.emitMainSignalingStatus(rtcPeerConnController.id, "trying");
|
|
17588
17639
|
const nodeId = getValueFrom(response, "result.node_id") ?? null;
|
|
17589
17640
|
const memberId = getValueFrom(response, "result.result.result.memberID") ?? null;
|
|
@@ -17610,8 +17661,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17610
17661
|
logger$16.debug(`[WebRTCManager] nodeid: ${this._nodeId$.value}, selfId: ${this._selfId$.value}`);
|
|
17611
17662
|
} else {
|
|
17612
17663
|
logger$16.error("[WebRTCManager] Verto invite failed:", response);
|
|
17613
|
-
|
|
17614
|
-
this.reportLegError(inviteError, rtcPeerConnController);
|
|
17664
|
+
this.reportLegError(/* @__PURE__ */ new Error("Verto invite failed: unexpected response"), rtcPeerConnController);
|
|
17615
17665
|
}
|
|
17616
17666
|
}
|
|
17617
17667
|
get RTCPeerConnectionConfig() {
|