@whereby.com/media 9.0.0 → 9.1.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/dist/index.cjs CHANGED
@@ -2573,8 +2573,9 @@ class P2pRtcManager {
2573
2573
  isInitializedWith({ selfId, roomName, isSfu }) {
2574
2574
  return this._selfId === selfId && this._roomName === roomName && !isSfu;
2575
2575
  }
2576
- addCameraStream(stream, { beforeEffectTracks = [] } = { beforeEffectTracks: [] }) {
2576
+ addCameraStream(stream, { videoPaused, beforeEffectTracks = [] } = { beforeEffectTracks: [] }) {
2577
2577
  logger$6.info("addCameraStream: [stream.id: %s]", stream.id);
2578
+ this._webcamPaused = videoPaused;
2578
2579
  if (stream === this._localCameraStream) {
2579
2580
  return;
2580
2581
  }
@@ -3454,6 +3455,7 @@ class P2pRtcManager {
3454
3455
  stopOrResumeVideo(localStream, enable) {
3455
3456
  var _a;
3456
3457
  logger$6.info("stopOrResumeVideo() [enable: %s]", enable);
3458
+ this._webcamPaused = !enable;
3457
3459
  if (!["chrome", "safari"].includes(browserName$1)) {
3458
3460
  return;
3459
3461
  }
@@ -3487,6 +3489,10 @@ class P2pRtcManager {
3487
3489
  .getUserMedia({ video: constraints })
3488
3490
  .then((stream) => {
3489
3491
  const track = stream.getVideoTracks()[0];
3492
+ if (this._webcamPaused) {
3493
+ track.stop();
3494
+ return;
3495
+ }
3490
3496
  localStream.addTrack(track);
3491
3497
  this._monitorVideoTrack(track);
3492
3498
  this._emit(EVENTS.LOCAL_STREAM_TRACK_ADDED, {
@@ -5520,6 +5526,10 @@ class VegaRtcManager {
5520
5526
  .getUserMedia({ video: constraints })
5521
5527
  .then((stream) => {
5522
5528
  const track = stream.getVideoTracks()[0];
5529
+ if (this._webcamPaused) {
5530
+ track.stop();
5531
+ return;
5532
+ }
5523
5533
  localStream.addTrack(track);
5524
5534
  this._monitorVideoTrack(track);
5525
5535
  this._emitToPWA(EVENTS.LOCAL_STREAM_TRACK_ADDED, {
@@ -7149,9 +7159,25 @@ function getStream(constraintOpt_1) {
7149
7159
  let newConstraints;
7150
7160
  let retryConstraintOpt;
7151
7161
  let stream = null;
7162
+ const attempts = [];
7152
7163
  const only = (constraintOpt.audioId === false && "video") || (constraintOpt.videoId === false && "audio");
7153
7164
  const stopTracks = isMobile || only !== "video";
7154
7165
  const constraints = getConstraints(constraintOpt);
7166
+ const attempt = (c) => __awaiter(this, void 0, void 0, function* () {
7167
+ var _a, _b;
7168
+ try {
7169
+ const s = yield getUserMedia(c);
7170
+ attempts.push({ constraints: c, outcome: { ok: true } });
7171
+ return s;
7172
+ }
7173
+ catch (e) {
7174
+ attempts.push({
7175
+ constraints: c,
7176
+ outcome: Object.assign({ ok: false, errorName: (_a = e === null || e === void 0 ? void 0 : e.name) !== null && _a !== void 0 ? _a : "UnknownError", errorMessage: (_b = e === null || e === void 0 ? void 0 : e.message) !== null && _b !== void 0 ? _b : String(e) }, ((e === null || e === void 0 ? void 0 : e.constraint) && { constraint: e.constraint })),
7177
+ });
7178
+ throw e;
7179
+ }
7180
+ });
7155
7181
  const addDetails = (err, orgErr) => {
7156
7182
  if (err) {
7157
7183
  err.details = Object.assign({ constraints, constraint: err.constraint || (orgErr === null || orgErr === void 0 ? void 0 : orgErr.constraint), newConstraints,
@@ -7163,10 +7189,15 @@ function getStream(constraintOpt_1) {
7163
7189
  return new Error("Unknown error");
7164
7190
  }
7165
7191
  };
7192
+ const attachAttempts = (err) => {
7193
+ if (err)
7194
+ err.attempts = attempts;
7195
+ return err;
7196
+ };
7166
7197
  const getSingleStream = (e) => __awaiter(this, void 0, void 0, function* () {
7167
7198
  if (constraints.audio && constraints.video) {
7168
7199
  try {
7169
- stream = yield getUserMedia(getConstraints(Object.assign(Object.assign({}, constraintOpt), { audioId: false })));
7200
+ stream = yield attempt(getConstraints(Object.assign(Object.assign({}, constraintOpt), { audioId: false })));
7170
7201
  }
7171
7202
  catch (e2) {
7172
7203
  if ((e2 === null || e2 === void 0 ? void 0 : e2.name) !== "NotFoundError") {
@@ -7175,7 +7206,7 @@ function getStream(constraintOpt_1) {
7175
7206
  }
7176
7207
  try {
7177
7208
  if (!stream)
7178
- stream = yield getUserMedia(getConstraints(Object.assign(Object.assign({}, constraintOpt), { videoId: false })));
7209
+ stream = yield attempt(getConstraints(Object.assign(Object.assign({}, constraintOpt), { videoId: false })));
7179
7210
  }
7180
7211
  catch (e2) {
7181
7212
  addDetails(e2, e);
@@ -7185,12 +7216,12 @@ function getStream(constraintOpt_1) {
7185
7216
  if (stopTracks && replaceStream)
7186
7217
  stopStreamTracks(replaceStream, only);
7187
7218
  try {
7188
- stream = yield getUserMedia(constraints);
7219
+ stream = yield attempt(constraints);
7189
7220
  }
7190
7221
  catch (e) {
7191
7222
  error = e;
7192
7223
  if (!fallback) {
7193
- throw addDetails(e);
7224
+ throw attachAttempts(addDetails(e));
7194
7225
  }
7195
7226
  if ((e === null || e === void 0 ? void 0 : e.name) === "OverconstrainedError") {
7196
7227
  const laxConstraints = {
@@ -7214,7 +7245,7 @@ function getStream(constraintOpt_1) {
7214
7245
  }
7215
7246
  else if (e.name !== "NotAllowedError") {
7216
7247
  try {
7217
- stream = yield getUserMedia(getConstraints(Object.assign(Object.assign({}, constraintOpt), { options: Object.assign(Object.assign({}, constraintOpt.options), { lax: true }) })));
7248
+ stream = yield attempt(getConstraints(Object.assign(Object.assign({}, constraintOpt), { options: Object.assign(Object.assign({}, constraintOpt.options), { lax: true }) })));
7218
7249
  }
7219
7250
  catch (e2) {
7220
7251
  logger.warn(`Tried getting stream again with laxer constraints, but failed: ${"" + e2}`);
@@ -7223,7 +7254,7 @@ function getStream(constraintOpt_1) {
7223
7254
  const problemWith = { audio: "audioId", video: "videoId" }[((_a = /(video|audio)/.exec(errMsg)) === null || _a === void 0 ? void 0 : _a[0]) || only || ""];
7224
7255
  if (!stream && problemWith) {
7225
7256
  try {
7226
- stream = yield getUserMedia(getConstraints(Object.assign(Object.assign({}, constraintOpt), { [problemWith]: null })));
7257
+ stream = yield attempt(getConstraints(Object.assign(Object.assign({}, constraintOpt), { [problemWith]: null })));
7227
7258
  }
7228
7259
  catch (e2) {
7229
7260
  logger.warn(`Re-tried ${problemWith} with no constraints, but failed: ${"" + e2}`);
@@ -7233,7 +7264,7 @@ function getStream(constraintOpt_1) {
7233
7264
  const tryOnly = problemWith ? [problemWith] : ["videoId", "audioId"];
7234
7265
  for (const kind of tryOnly) {
7235
7266
  try {
7236
- stream = yield getUserMedia(getConstraints(Object.assign(Object.assign({}, constraintOpt), { [kind]: false })));
7267
+ stream = yield attempt(getConstraints(Object.assign(Object.assign({}, constraintOpt), { [kind]: false })));
7237
7268
  }
7238
7269
  catch (e2) {
7239
7270
  logger.warn(`Re-tried without ${kind}, but failed: ${"" + e2}`);
@@ -7250,16 +7281,17 @@ function getStream(constraintOpt_1) {
7250
7281
  }
7251
7282
  if (retryConstraintOpt) {
7252
7283
  const onlyConstraints = only ? { audio: { videoId: false }, video: { audioId: false } }[only] : {};
7253
- newConstraints = getConstraints(Object.assign(Object.assign(Object.assign(Object.assign({}, constraintOpt), retryConstraintOpt), { options: Object.assign(Object.assign({}, constraintOpt.options), { lax: retryConstraintOpt.lax }) }), onlyConstraints));
7284
+ const retryConstraints = getConstraints(Object.assign(Object.assign(Object.assign(Object.assign({}, constraintOpt), retryConstraintOpt), { options: Object.assign(Object.assign({}, constraintOpt.options), { lax: retryConstraintOpt.lax }) }), onlyConstraints));
7285
+ newConstraints = retryConstraints;
7254
7286
  try {
7255
- stream = yield getUserMedia(newConstraints);
7287
+ stream = yield attempt(retryConstraints);
7256
7288
  }
7257
7289
  catch (e) {
7258
- throw addDetails(e, error);
7290
+ throw attachAttempts(addDetails(e, error));
7259
7291
  }
7260
7292
  }
7261
7293
  if (!stream) {
7262
- throw addDetails(error);
7294
+ throw attachAttempts(addDetails(error));
7263
7295
  }
7264
7296
  let replacedTracks;
7265
7297
  if (replaceStream) {
@@ -7268,7 +7300,7 @@ function getStream(constraintOpt_1) {
7268
7300
  replacedTracks = replaceTracksInStream(replaceStream, stream, only);
7269
7301
  stream = replaceStream;
7270
7302
  }
7271
- return { error: error && addDetails(error), stream, replacedTracks };
7303
+ return { error: error && addDetails(error), stream, replacedTracks, attempts };
7272
7304
  });
7273
7305
  }
7274
7306
  function hasGetDisplayMedia() {
package/dist/index.d.cts CHANGED
@@ -604,10 +604,23 @@ interface BuildDeviceListOptions {
604
604
  busyDeviceIds: string[];
605
605
  kind: MediaDeviceKind;
606
606
  }
607
+ type GetUserMediaAttemptOutcome = {
608
+ ok: true;
609
+ } | {
610
+ ok: false;
611
+ errorName: string;
612
+ errorMessage: string;
613
+ constraint?: string;
614
+ };
615
+ type GetUserMediaAttempt = {
616
+ constraints: MediaStreamConstraints;
617
+ outcome: GetUserMediaAttemptOutcome;
618
+ };
607
619
  type GetStreamResult = {
608
620
  error?: unknown;
609
621
  replacedTracks?: MediaStreamTrack[];
610
622
  stream: MediaStream;
623
+ attempts: GetUserMediaAttempt[];
611
624
  };
612
625
  type UpdatedDeviceInfo = {
613
626
  deviceId?: string | null;
@@ -1572,6 +1585,7 @@ declare class P2pRtcManager implements RtcManager {
1572
1585
  _closed: boolean;
1573
1586
  analytics: P2PAnalytics;
1574
1587
  _rtcStatsDisconnectTimeout?: ReturnType<typeof setTimeout>;
1588
+ _webcamPaused?: boolean;
1575
1589
  constructor({ selfId, room, emitter, serverSocket, webrtcProvider, features }: RtcManagerOptions);
1576
1590
  numberOfPeerconnections(): number;
1577
1591
  isInitializedWith({ selfId, roomName, isSfu }: {
@@ -1579,7 +1593,7 @@ declare class P2pRtcManager implements RtcManager {
1579
1593
  roomName: string;
1580
1594
  isSfu: boolean;
1581
1595
  }): boolean;
1582
- addCameraStream(stream: MediaStream, { beforeEffectTracks }?: AddCameraStreamOptions): void;
1596
+ addCameraStream(stream: MediaStream, { videoPaused, beforeEffectTracks }?: AddCameraStreamOptions): void;
1583
1597
  _enableStopResumeVideoForBrowserSDK(stream: MediaStream): void;
1584
1598
  addScreenshareStream(stream: MediaStream): void;
1585
1599
  replaceTrack(oldTrack: MediaStreamTrack | null, newTrack: MediaStreamTrack): Promise<void | any[]>;
@@ -2017,4 +2031,4 @@ declare class VegaRtcManager implements RtcManager {
2017
2031
  }
2018
2032
 
2019
2033
  export { ADDITIONAL_SCREEN_SHARE_SETTINGS, AUDIO_SETTINGS, BandwidthTester, CAMERA_STREAM_ID, EVENTS, KNOCK_MESSAGES, KalmanFilter, Logger, MEDIA_JITTER_BUFFER_TARGET, NoDevicesError, P2pRtcManager, PROTOCOL_ERRORS, PROTOCOL_EVENTS, PROTOCOL_REQUESTS, PROTOCOL_RESPONSES, RELAY_MESSAGES, ReconnectManager, RtcEventNames, RtcManagerDispatcher, SCREEN_SHARE_SETTINGS, SCREEN_SHARE_SIMULCAST_SETTINGS, STREAM_TYPES, ServerSocket, Session, SfuV2Parser, TYPES, VIDEO_SETTINGS_HD, VIDEO_SETTINGS_SD, VIDEO_SETTINGS_VP9, VIDEO_SETTINGS_VP9_LOW_BANDWIDTH, VegaConnection, VegaMediaQualityMonitor, VegaRtcManager, addAbsCaptureTimeExtMap, addExtMap, assert, buildDeviceList, calculateStd, captureAudioSsrcMetrics, captureCandidatePairInfoMetrics, captureCommonSsrcMetrics, captureSsrcInfo, captureVideoSsrcMetrics, cleanSdp, compareLocalDevices, createACFCalculator, createMicAnalyser, createWorker, deprioritizeH264, detectMicrophoneNotWorking, enumerate, external_stun_servers, filterMidExtension, filterMsidSemantic, fromLocation, generateByteString, getConstraints, getCurrentPeerConnections, getDeviceData, getDisplayMedia, getIssuesAndMetrics, getMediaConstraints, getMediaSettings, getMediasoupDeviceAsync, getNumFailedStatsReports, getNumFailedTrackSsrcLookups, getNumMissingTrackSsrcLookups, getPeerConnectionIndex, getStats, getStream, getUpdatedDevices, getUpdatedStats, getUserMedia, hasGetDisplayMedia, ipRegex, isMobile, issueDetectorOrMetricEnabled, maybeTurnOnly, modifyMediaCapabilities, removePeerConnection, replaceTracksInStream, _default as rtcManagerEvents, rtcStats, setClientProvider, setCodecPreferenceSDP, setPeerConnectionsForTests, setVideoBandwidthUsingSetParameters, sortCodecs, standardDeviation, startPerformanceMonitor, stopStreamTracks, subscribeIssues, subscribeStats, trackAnnotations, turnServerOverride, variance };
2020
- export type { AddCameraStreamOptions, AddSpotlightRequest, AudioEnableRequest, AudioEnableRequestedEvent, AudioEnabledEvent, BreakoutConfig, BreakoutGroupJoinedEvent, BreakoutSessionUpdatedEvent, BuildDeviceListOptions, CannotJoinUnclaimedRoomError, ChatMessage, ClearableTimeout, ClientKickedEvent, ClientLeftEvent, ClientMetadataPayload, ClientMetadataReceivedEvent, ClientRole, ClientUnableToJoinEvent, CloudRecordingStartedEvent, Codec, ConnectionStatus, Credentials, ForbiddenError, ForbiddenErrorNames, GetConstraintsOptions, GetDeviceDataResult, GetMediaConstraintsOptions, GetStreamOptions, GetStreamResult, GetUpdatedDevicesResult, HostPresenceControlsError, IdentifyDeviceRequest, InternalServerError, InvalidAssistantKeyError, IssuesAndMetricsByView, JoinRoomRequest, KnockAcceptedEvent, KnockRejectedEvent, KnockRoomRequest, KnockerLeftEvent, LiveTranscriptionStartedEvent, LiveTranscriptionStoppedEvent, MaxViewerLimitReachedError, MediaPrefs, Metric, NewClientEvent, OrganizationAssistantNotEnabledError, OrganizationAssistantNotFoundError, OrganizationPlanExhaustedError, RemoveScreenshareStreamOptions, RemoveSpotlightRequest, RoleName, RoomConcurrencyControlsError, RoomEmptyError, RoomFullError, RoomJoinPermissionDeniedError, RoomJoinedErrors, RoomJoinedEvent, RoomJoinedSuccess, RoomKnockedEvent, RoomLockedError, RoomLockedEvent, RoomMeetingTimeExhaustedError, RoomMode, RoomSessionEndedEvent, RtcClientConnectionStatusChangedPayload, RtcEventEmitter, RtcEvents, RtcLocalStreamTrackAddedPayload, RtcLocalStreamTrackRemovedPayload, RtcManager, RtcManagerCreatedPayload, RtcManagerOptions, RtcStreamAddedPayload, ScreenshareStartedEvent, ScreenshareStoppedEvent, SendClientMetadataRequest, SignalClient, SignalEvents, SignalIceCandidateMessage, SignalIceEndOfCandidatesMessage, SignalIceServer, SignalKnocker, SignalMediaServerConfig, SignalRTCSessionDescription, SignalReadyToReceiveOfferMessage, SignalRequests, SignalRoom, SignalSDPMessage, SignalSFUServer, SignalTurnServer, SocketConf, SocketManager, Spotlight, SpotlightAddedEvent, SpotlightRemovedEvent, StatsMonitorOptions, StatsMonitorState, StatsSubscription, TurnTransportProtocol, UniqueRoleAlreadyInRoomError, UpdatedDeviceInfo, UpdatedDevicesInfo, VegaConnectionOptions, VegaRtcManagerOptions, VideoEnableRequest, VideoEnableRequestedEvent, VideoEnabledEvent, WebRTCProvider };
2034
+ export type { AddCameraStreamOptions, AddSpotlightRequest, AudioEnableRequest, AudioEnableRequestedEvent, AudioEnabledEvent, BreakoutConfig, BreakoutGroupJoinedEvent, BreakoutSessionUpdatedEvent, BuildDeviceListOptions, CannotJoinUnclaimedRoomError, ChatMessage, ClearableTimeout, ClientKickedEvent, ClientLeftEvent, ClientMetadataPayload, ClientMetadataReceivedEvent, ClientRole, ClientUnableToJoinEvent, CloudRecordingStartedEvent, Codec, ConnectionStatus, Credentials, ForbiddenError, ForbiddenErrorNames, GetConstraintsOptions, GetDeviceDataResult, GetMediaConstraintsOptions, GetStreamOptions, GetStreamResult, GetUpdatedDevicesResult, GetUserMediaAttempt, GetUserMediaAttemptOutcome, HostPresenceControlsError, IdentifyDeviceRequest, InternalServerError, InvalidAssistantKeyError, IssuesAndMetricsByView, JoinRoomRequest, KnockAcceptedEvent, KnockRejectedEvent, KnockRoomRequest, KnockerLeftEvent, LiveTranscriptionStartedEvent, LiveTranscriptionStoppedEvent, MaxViewerLimitReachedError, MediaPrefs, Metric, NewClientEvent, OrganizationAssistantNotEnabledError, OrganizationAssistantNotFoundError, OrganizationPlanExhaustedError, RemoveScreenshareStreamOptions, RemoveSpotlightRequest, RoleName, RoomConcurrencyControlsError, RoomEmptyError, RoomFullError, RoomJoinPermissionDeniedError, RoomJoinedErrors, RoomJoinedEvent, RoomJoinedSuccess, RoomKnockedEvent, RoomLockedError, RoomLockedEvent, RoomMeetingTimeExhaustedError, RoomMode, RoomSessionEndedEvent, RtcClientConnectionStatusChangedPayload, RtcEventEmitter, RtcEvents, RtcLocalStreamTrackAddedPayload, RtcLocalStreamTrackRemovedPayload, RtcManager, RtcManagerCreatedPayload, RtcManagerOptions, RtcStreamAddedPayload, ScreenshareStartedEvent, ScreenshareStoppedEvent, SendClientMetadataRequest, SignalClient, SignalEvents, SignalIceCandidateMessage, SignalIceEndOfCandidatesMessage, SignalIceServer, SignalKnocker, SignalMediaServerConfig, SignalRTCSessionDescription, SignalReadyToReceiveOfferMessage, SignalRequests, SignalRoom, SignalSDPMessage, SignalSFUServer, SignalTurnServer, SocketConf, SocketManager, Spotlight, SpotlightAddedEvent, SpotlightRemovedEvent, StatsMonitorOptions, StatsMonitorState, StatsSubscription, TurnTransportProtocol, UniqueRoleAlreadyInRoomError, UpdatedDeviceInfo, UpdatedDevicesInfo, VegaConnectionOptions, VegaRtcManagerOptions, VideoEnableRequest, VideoEnableRequestedEvent, VideoEnabledEvent, WebRTCProvider };
package/dist/index.d.mts CHANGED
@@ -604,10 +604,23 @@ interface BuildDeviceListOptions {
604
604
  busyDeviceIds: string[];
605
605
  kind: MediaDeviceKind;
606
606
  }
607
+ type GetUserMediaAttemptOutcome = {
608
+ ok: true;
609
+ } | {
610
+ ok: false;
611
+ errorName: string;
612
+ errorMessage: string;
613
+ constraint?: string;
614
+ };
615
+ type GetUserMediaAttempt = {
616
+ constraints: MediaStreamConstraints;
617
+ outcome: GetUserMediaAttemptOutcome;
618
+ };
607
619
  type GetStreamResult = {
608
620
  error?: unknown;
609
621
  replacedTracks?: MediaStreamTrack[];
610
622
  stream: MediaStream;
623
+ attempts: GetUserMediaAttempt[];
611
624
  };
612
625
  type UpdatedDeviceInfo = {
613
626
  deviceId?: string | null;
@@ -1572,6 +1585,7 @@ declare class P2pRtcManager implements RtcManager {
1572
1585
  _closed: boolean;
1573
1586
  analytics: P2PAnalytics;
1574
1587
  _rtcStatsDisconnectTimeout?: ReturnType<typeof setTimeout>;
1588
+ _webcamPaused?: boolean;
1575
1589
  constructor({ selfId, room, emitter, serverSocket, webrtcProvider, features }: RtcManagerOptions);
1576
1590
  numberOfPeerconnections(): number;
1577
1591
  isInitializedWith({ selfId, roomName, isSfu }: {
@@ -1579,7 +1593,7 @@ declare class P2pRtcManager implements RtcManager {
1579
1593
  roomName: string;
1580
1594
  isSfu: boolean;
1581
1595
  }): boolean;
1582
- addCameraStream(stream: MediaStream, { beforeEffectTracks }?: AddCameraStreamOptions): void;
1596
+ addCameraStream(stream: MediaStream, { videoPaused, beforeEffectTracks }?: AddCameraStreamOptions): void;
1583
1597
  _enableStopResumeVideoForBrowserSDK(stream: MediaStream): void;
1584
1598
  addScreenshareStream(stream: MediaStream): void;
1585
1599
  replaceTrack(oldTrack: MediaStreamTrack | null, newTrack: MediaStreamTrack): Promise<void | any[]>;
@@ -2017,4 +2031,4 @@ declare class VegaRtcManager implements RtcManager {
2017
2031
  }
2018
2032
 
2019
2033
  export { ADDITIONAL_SCREEN_SHARE_SETTINGS, AUDIO_SETTINGS, BandwidthTester, CAMERA_STREAM_ID, EVENTS, KNOCK_MESSAGES, KalmanFilter, Logger, MEDIA_JITTER_BUFFER_TARGET, NoDevicesError, P2pRtcManager, PROTOCOL_ERRORS, PROTOCOL_EVENTS, PROTOCOL_REQUESTS, PROTOCOL_RESPONSES, RELAY_MESSAGES, ReconnectManager, RtcEventNames, RtcManagerDispatcher, SCREEN_SHARE_SETTINGS, SCREEN_SHARE_SIMULCAST_SETTINGS, STREAM_TYPES, ServerSocket, Session, SfuV2Parser, TYPES, VIDEO_SETTINGS_HD, VIDEO_SETTINGS_SD, VIDEO_SETTINGS_VP9, VIDEO_SETTINGS_VP9_LOW_BANDWIDTH, VegaConnection, VegaMediaQualityMonitor, VegaRtcManager, addAbsCaptureTimeExtMap, addExtMap, assert, buildDeviceList, calculateStd, captureAudioSsrcMetrics, captureCandidatePairInfoMetrics, captureCommonSsrcMetrics, captureSsrcInfo, captureVideoSsrcMetrics, cleanSdp, compareLocalDevices, createACFCalculator, createMicAnalyser, createWorker, deprioritizeH264, detectMicrophoneNotWorking, enumerate, external_stun_servers, filterMidExtension, filterMsidSemantic, fromLocation, generateByteString, getConstraints, getCurrentPeerConnections, getDeviceData, getDisplayMedia, getIssuesAndMetrics, getMediaConstraints, getMediaSettings, getMediasoupDeviceAsync, getNumFailedStatsReports, getNumFailedTrackSsrcLookups, getNumMissingTrackSsrcLookups, getPeerConnectionIndex, getStats, getStream, getUpdatedDevices, getUpdatedStats, getUserMedia, hasGetDisplayMedia, ipRegex, isMobile, issueDetectorOrMetricEnabled, maybeTurnOnly, modifyMediaCapabilities, removePeerConnection, replaceTracksInStream, _default as rtcManagerEvents, rtcStats, setClientProvider, setCodecPreferenceSDP, setPeerConnectionsForTests, setVideoBandwidthUsingSetParameters, sortCodecs, standardDeviation, startPerformanceMonitor, stopStreamTracks, subscribeIssues, subscribeStats, trackAnnotations, turnServerOverride, variance };
2020
- export type { AddCameraStreamOptions, AddSpotlightRequest, AudioEnableRequest, AudioEnableRequestedEvent, AudioEnabledEvent, BreakoutConfig, BreakoutGroupJoinedEvent, BreakoutSessionUpdatedEvent, BuildDeviceListOptions, CannotJoinUnclaimedRoomError, ChatMessage, ClearableTimeout, ClientKickedEvent, ClientLeftEvent, ClientMetadataPayload, ClientMetadataReceivedEvent, ClientRole, ClientUnableToJoinEvent, CloudRecordingStartedEvent, Codec, ConnectionStatus, Credentials, ForbiddenError, ForbiddenErrorNames, GetConstraintsOptions, GetDeviceDataResult, GetMediaConstraintsOptions, GetStreamOptions, GetStreamResult, GetUpdatedDevicesResult, HostPresenceControlsError, IdentifyDeviceRequest, InternalServerError, InvalidAssistantKeyError, IssuesAndMetricsByView, JoinRoomRequest, KnockAcceptedEvent, KnockRejectedEvent, KnockRoomRequest, KnockerLeftEvent, LiveTranscriptionStartedEvent, LiveTranscriptionStoppedEvent, MaxViewerLimitReachedError, MediaPrefs, Metric, NewClientEvent, OrganizationAssistantNotEnabledError, OrganizationAssistantNotFoundError, OrganizationPlanExhaustedError, RemoveScreenshareStreamOptions, RemoveSpotlightRequest, RoleName, RoomConcurrencyControlsError, RoomEmptyError, RoomFullError, RoomJoinPermissionDeniedError, RoomJoinedErrors, RoomJoinedEvent, RoomJoinedSuccess, RoomKnockedEvent, RoomLockedError, RoomLockedEvent, RoomMeetingTimeExhaustedError, RoomMode, RoomSessionEndedEvent, RtcClientConnectionStatusChangedPayload, RtcEventEmitter, RtcEvents, RtcLocalStreamTrackAddedPayload, RtcLocalStreamTrackRemovedPayload, RtcManager, RtcManagerCreatedPayload, RtcManagerOptions, RtcStreamAddedPayload, ScreenshareStartedEvent, ScreenshareStoppedEvent, SendClientMetadataRequest, SignalClient, SignalEvents, SignalIceCandidateMessage, SignalIceEndOfCandidatesMessage, SignalIceServer, SignalKnocker, SignalMediaServerConfig, SignalRTCSessionDescription, SignalReadyToReceiveOfferMessage, SignalRequests, SignalRoom, SignalSDPMessage, SignalSFUServer, SignalTurnServer, SocketConf, SocketManager, Spotlight, SpotlightAddedEvent, SpotlightRemovedEvent, StatsMonitorOptions, StatsMonitorState, StatsSubscription, TurnTransportProtocol, UniqueRoleAlreadyInRoomError, UpdatedDeviceInfo, UpdatedDevicesInfo, VegaConnectionOptions, VegaRtcManagerOptions, VideoEnableRequest, VideoEnableRequestedEvent, VideoEnabledEvent, WebRTCProvider };
2034
+ export type { AddCameraStreamOptions, AddSpotlightRequest, AudioEnableRequest, AudioEnableRequestedEvent, AudioEnabledEvent, BreakoutConfig, BreakoutGroupJoinedEvent, BreakoutSessionUpdatedEvent, BuildDeviceListOptions, CannotJoinUnclaimedRoomError, ChatMessage, ClearableTimeout, ClientKickedEvent, ClientLeftEvent, ClientMetadataPayload, ClientMetadataReceivedEvent, ClientRole, ClientUnableToJoinEvent, CloudRecordingStartedEvent, Codec, ConnectionStatus, Credentials, ForbiddenError, ForbiddenErrorNames, GetConstraintsOptions, GetDeviceDataResult, GetMediaConstraintsOptions, GetStreamOptions, GetStreamResult, GetUpdatedDevicesResult, GetUserMediaAttempt, GetUserMediaAttemptOutcome, HostPresenceControlsError, IdentifyDeviceRequest, InternalServerError, InvalidAssistantKeyError, IssuesAndMetricsByView, JoinRoomRequest, KnockAcceptedEvent, KnockRejectedEvent, KnockRoomRequest, KnockerLeftEvent, LiveTranscriptionStartedEvent, LiveTranscriptionStoppedEvent, MaxViewerLimitReachedError, MediaPrefs, Metric, NewClientEvent, OrganizationAssistantNotEnabledError, OrganizationAssistantNotFoundError, OrganizationPlanExhaustedError, RemoveScreenshareStreamOptions, RemoveSpotlightRequest, RoleName, RoomConcurrencyControlsError, RoomEmptyError, RoomFullError, RoomJoinPermissionDeniedError, RoomJoinedErrors, RoomJoinedEvent, RoomJoinedSuccess, RoomKnockedEvent, RoomLockedError, RoomLockedEvent, RoomMeetingTimeExhaustedError, RoomMode, RoomSessionEndedEvent, RtcClientConnectionStatusChangedPayload, RtcEventEmitter, RtcEvents, RtcLocalStreamTrackAddedPayload, RtcLocalStreamTrackRemovedPayload, RtcManager, RtcManagerCreatedPayload, RtcManagerOptions, RtcStreamAddedPayload, ScreenshareStartedEvent, ScreenshareStoppedEvent, SendClientMetadataRequest, SignalClient, SignalEvents, SignalIceCandidateMessage, SignalIceEndOfCandidatesMessage, SignalIceServer, SignalKnocker, SignalMediaServerConfig, SignalRTCSessionDescription, SignalReadyToReceiveOfferMessage, SignalRequests, SignalRoom, SignalSDPMessage, SignalSFUServer, SignalTurnServer, SocketConf, SocketManager, Spotlight, SpotlightAddedEvent, SpotlightRemovedEvent, StatsMonitorOptions, StatsMonitorState, StatsSubscription, TurnTransportProtocol, UniqueRoleAlreadyInRoomError, UpdatedDeviceInfo, UpdatedDevicesInfo, VegaConnectionOptions, VegaRtcManagerOptions, VideoEnableRequest, VideoEnableRequestedEvent, VideoEnabledEvent, WebRTCProvider };
package/dist/index.d.ts CHANGED
@@ -604,10 +604,23 @@ interface BuildDeviceListOptions {
604
604
  busyDeviceIds: string[];
605
605
  kind: MediaDeviceKind;
606
606
  }
607
+ type GetUserMediaAttemptOutcome = {
608
+ ok: true;
609
+ } | {
610
+ ok: false;
611
+ errorName: string;
612
+ errorMessage: string;
613
+ constraint?: string;
614
+ };
615
+ type GetUserMediaAttempt = {
616
+ constraints: MediaStreamConstraints;
617
+ outcome: GetUserMediaAttemptOutcome;
618
+ };
607
619
  type GetStreamResult = {
608
620
  error?: unknown;
609
621
  replacedTracks?: MediaStreamTrack[];
610
622
  stream: MediaStream;
623
+ attempts: GetUserMediaAttempt[];
611
624
  };
612
625
  type UpdatedDeviceInfo = {
613
626
  deviceId?: string | null;
@@ -1572,6 +1585,7 @@ declare class P2pRtcManager implements RtcManager {
1572
1585
  _closed: boolean;
1573
1586
  analytics: P2PAnalytics;
1574
1587
  _rtcStatsDisconnectTimeout?: ReturnType<typeof setTimeout>;
1588
+ _webcamPaused?: boolean;
1575
1589
  constructor({ selfId, room, emitter, serverSocket, webrtcProvider, features }: RtcManagerOptions);
1576
1590
  numberOfPeerconnections(): number;
1577
1591
  isInitializedWith({ selfId, roomName, isSfu }: {
@@ -1579,7 +1593,7 @@ declare class P2pRtcManager implements RtcManager {
1579
1593
  roomName: string;
1580
1594
  isSfu: boolean;
1581
1595
  }): boolean;
1582
- addCameraStream(stream: MediaStream, { beforeEffectTracks }?: AddCameraStreamOptions): void;
1596
+ addCameraStream(stream: MediaStream, { videoPaused, beforeEffectTracks }?: AddCameraStreamOptions): void;
1583
1597
  _enableStopResumeVideoForBrowserSDK(stream: MediaStream): void;
1584
1598
  addScreenshareStream(stream: MediaStream): void;
1585
1599
  replaceTrack(oldTrack: MediaStreamTrack | null, newTrack: MediaStreamTrack): Promise<void | any[]>;
@@ -2017,4 +2031,4 @@ declare class VegaRtcManager implements RtcManager {
2017
2031
  }
2018
2032
 
2019
2033
  export { ADDITIONAL_SCREEN_SHARE_SETTINGS, AUDIO_SETTINGS, BandwidthTester, CAMERA_STREAM_ID, EVENTS, KNOCK_MESSAGES, KalmanFilter, Logger, MEDIA_JITTER_BUFFER_TARGET, NoDevicesError, P2pRtcManager, PROTOCOL_ERRORS, PROTOCOL_EVENTS, PROTOCOL_REQUESTS, PROTOCOL_RESPONSES, RELAY_MESSAGES, ReconnectManager, RtcEventNames, RtcManagerDispatcher, SCREEN_SHARE_SETTINGS, SCREEN_SHARE_SIMULCAST_SETTINGS, STREAM_TYPES, ServerSocket, Session, SfuV2Parser, TYPES, VIDEO_SETTINGS_HD, VIDEO_SETTINGS_SD, VIDEO_SETTINGS_VP9, VIDEO_SETTINGS_VP9_LOW_BANDWIDTH, VegaConnection, VegaMediaQualityMonitor, VegaRtcManager, addAbsCaptureTimeExtMap, addExtMap, assert, buildDeviceList, calculateStd, captureAudioSsrcMetrics, captureCandidatePairInfoMetrics, captureCommonSsrcMetrics, captureSsrcInfo, captureVideoSsrcMetrics, cleanSdp, compareLocalDevices, createACFCalculator, createMicAnalyser, createWorker, deprioritizeH264, detectMicrophoneNotWorking, enumerate, external_stun_servers, filterMidExtension, filterMsidSemantic, fromLocation, generateByteString, getConstraints, getCurrentPeerConnections, getDeviceData, getDisplayMedia, getIssuesAndMetrics, getMediaConstraints, getMediaSettings, getMediasoupDeviceAsync, getNumFailedStatsReports, getNumFailedTrackSsrcLookups, getNumMissingTrackSsrcLookups, getPeerConnectionIndex, getStats, getStream, getUpdatedDevices, getUpdatedStats, getUserMedia, hasGetDisplayMedia, ipRegex, isMobile, issueDetectorOrMetricEnabled, maybeTurnOnly, modifyMediaCapabilities, removePeerConnection, replaceTracksInStream, _default as rtcManagerEvents, rtcStats, setClientProvider, setCodecPreferenceSDP, setPeerConnectionsForTests, setVideoBandwidthUsingSetParameters, sortCodecs, standardDeviation, startPerformanceMonitor, stopStreamTracks, subscribeIssues, subscribeStats, trackAnnotations, turnServerOverride, variance };
2020
- export type { AddCameraStreamOptions, AddSpotlightRequest, AudioEnableRequest, AudioEnableRequestedEvent, AudioEnabledEvent, BreakoutConfig, BreakoutGroupJoinedEvent, BreakoutSessionUpdatedEvent, BuildDeviceListOptions, CannotJoinUnclaimedRoomError, ChatMessage, ClearableTimeout, ClientKickedEvent, ClientLeftEvent, ClientMetadataPayload, ClientMetadataReceivedEvent, ClientRole, ClientUnableToJoinEvent, CloudRecordingStartedEvent, Codec, ConnectionStatus, Credentials, ForbiddenError, ForbiddenErrorNames, GetConstraintsOptions, GetDeviceDataResult, GetMediaConstraintsOptions, GetStreamOptions, GetStreamResult, GetUpdatedDevicesResult, HostPresenceControlsError, IdentifyDeviceRequest, InternalServerError, InvalidAssistantKeyError, IssuesAndMetricsByView, JoinRoomRequest, KnockAcceptedEvent, KnockRejectedEvent, KnockRoomRequest, KnockerLeftEvent, LiveTranscriptionStartedEvent, LiveTranscriptionStoppedEvent, MaxViewerLimitReachedError, MediaPrefs, Metric, NewClientEvent, OrganizationAssistantNotEnabledError, OrganizationAssistantNotFoundError, OrganizationPlanExhaustedError, RemoveScreenshareStreamOptions, RemoveSpotlightRequest, RoleName, RoomConcurrencyControlsError, RoomEmptyError, RoomFullError, RoomJoinPermissionDeniedError, RoomJoinedErrors, RoomJoinedEvent, RoomJoinedSuccess, RoomKnockedEvent, RoomLockedError, RoomLockedEvent, RoomMeetingTimeExhaustedError, RoomMode, RoomSessionEndedEvent, RtcClientConnectionStatusChangedPayload, RtcEventEmitter, RtcEvents, RtcLocalStreamTrackAddedPayload, RtcLocalStreamTrackRemovedPayload, RtcManager, RtcManagerCreatedPayload, RtcManagerOptions, RtcStreamAddedPayload, ScreenshareStartedEvent, ScreenshareStoppedEvent, SendClientMetadataRequest, SignalClient, SignalEvents, SignalIceCandidateMessage, SignalIceEndOfCandidatesMessage, SignalIceServer, SignalKnocker, SignalMediaServerConfig, SignalRTCSessionDescription, SignalReadyToReceiveOfferMessage, SignalRequests, SignalRoom, SignalSDPMessage, SignalSFUServer, SignalTurnServer, SocketConf, SocketManager, Spotlight, SpotlightAddedEvent, SpotlightRemovedEvent, StatsMonitorOptions, StatsMonitorState, StatsSubscription, TurnTransportProtocol, UniqueRoleAlreadyInRoomError, UpdatedDeviceInfo, UpdatedDevicesInfo, VegaConnectionOptions, VegaRtcManagerOptions, VideoEnableRequest, VideoEnableRequestedEvent, VideoEnabledEvent, WebRTCProvider };
2034
+ export type { AddCameraStreamOptions, AddSpotlightRequest, AudioEnableRequest, AudioEnableRequestedEvent, AudioEnabledEvent, BreakoutConfig, BreakoutGroupJoinedEvent, BreakoutSessionUpdatedEvent, BuildDeviceListOptions, CannotJoinUnclaimedRoomError, ChatMessage, ClearableTimeout, ClientKickedEvent, ClientLeftEvent, ClientMetadataPayload, ClientMetadataReceivedEvent, ClientRole, ClientUnableToJoinEvent, CloudRecordingStartedEvent, Codec, ConnectionStatus, Credentials, ForbiddenError, ForbiddenErrorNames, GetConstraintsOptions, GetDeviceDataResult, GetMediaConstraintsOptions, GetStreamOptions, GetStreamResult, GetUpdatedDevicesResult, GetUserMediaAttempt, GetUserMediaAttemptOutcome, HostPresenceControlsError, IdentifyDeviceRequest, InternalServerError, InvalidAssistantKeyError, IssuesAndMetricsByView, JoinRoomRequest, KnockAcceptedEvent, KnockRejectedEvent, KnockRoomRequest, KnockerLeftEvent, LiveTranscriptionStartedEvent, LiveTranscriptionStoppedEvent, MaxViewerLimitReachedError, MediaPrefs, Metric, NewClientEvent, OrganizationAssistantNotEnabledError, OrganizationAssistantNotFoundError, OrganizationPlanExhaustedError, RemoveScreenshareStreamOptions, RemoveSpotlightRequest, RoleName, RoomConcurrencyControlsError, RoomEmptyError, RoomFullError, RoomJoinPermissionDeniedError, RoomJoinedErrors, RoomJoinedEvent, RoomJoinedSuccess, RoomKnockedEvent, RoomLockedError, RoomLockedEvent, RoomMeetingTimeExhaustedError, RoomMode, RoomSessionEndedEvent, RtcClientConnectionStatusChangedPayload, RtcEventEmitter, RtcEvents, RtcLocalStreamTrackAddedPayload, RtcLocalStreamTrackRemovedPayload, RtcManager, RtcManagerCreatedPayload, RtcManagerOptions, RtcStreamAddedPayload, ScreenshareStartedEvent, ScreenshareStoppedEvent, SendClientMetadataRequest, SignalClient, SignalEvents, SignalIceCandidateMessage, SignalIceEndOfCandidatesMessage, SignalIceServer, SignalKnocker, SignalMediaServerConfig, SignalRTCSessionDescription, SignalReadyToReceiveOfferMessage, SignalRequests, SignalRoom, SignalSDPMessage, SignalSFUServer, SignalTurnServer, SocketConf, SocketManager, Spotlight, SpotlightAddedEvent, SpotlightRemovedEvent, StatsMonitorOptions, StatsMonitorState, StatsSubscription, TurnTransportProtocol, UniqueRoleAlreadyInRoomError, UpdatedDeviceInfo, UpdatedDevicesInfo, VegaConnectionOptions, VegaRtcManagerOptions, VideoEnableRequest, VideoEnableRequestedEvent, VideoEnabledEvent, WebRTCProvider };
package/dist/index.mjs CHANGED
@@ -2552,8 +2552,9 @@ class P2pRtcManager {
2552
2552
  isInitializedWith({ selfId, roomName, isSfu }) {
2553
2553
  return this._selfId === selfId && this._roomName === roomName && !isSfu;
2554
2554
  }
2555
- addCameraStream(stream, { beforeEffectTracks = [] } = { beforeEffectTracks: [] }) {
2555
+ addCameraStream(stream, { videoPaused, beforeEffectTracks = [] } = { beforeEffectTracks: [] }) {
2556
2556
  logger$6.info("addCameraStream: [stream.id: %s]", stream.id);
2557
+ this._webcamPaused = videoPaused;
2557
2558
  if (stream === this._localCameraStream) {
2558
2559
  return;
2559
2560
  }
@@ -3433,6 +3434,7 @@ class P2pRtcManager {
3433
3434
  stopOrResumeVideo(localStream, enable) {
3434
3435
  var _a;
3435
3436
  logger$6.info("stopOrResumeVideo() [enable: %s]", enable);
3437
+ this._webcamPaused = !enable;
3436
3438
  if (!["chrome", "safari"].includes(browserName$1)) {
3437
3439
  return;
3438
3440
  }
@@ -3466,6 +3468,10 @@ class P2pRtcManager {
3466
3468
  .getUserMedia({ video: constraints })
3467
3469
  .then((stream) => {
3468
3470
  const track = stream.getVideoTracks()[0];
3471
+ if (this._webcamPaused) {
3472
+ track.stop();
3473
+ return;
3474
+ }
3469
3475
  localStream.addTrack(track);
3470
3476
  this._monitorVideoTrack(track);
3471
3477
  this._emit(EVENTS.LOCAL_STREAM_TRACK_ADDED, {
@@ -5499,6 +5505,10 @@ class VegaRtcManager {
5499
5505
  .getUserMedia({ video: constraints })
5500
5506
  .then((stream) => {
5501
5507
  const track = stream.getVideoTracks()[0];
5508
+ if (this._webcamPaused) {
5509
+ track.stop();
5510
+ return;
5511
+ }
5502
5512
  localStream.addTrack(track);
5503
5513
  this._monitorVideoTrack(track);
5504
5514
  this._emitToPWA(EVENTS.LOCAL_STREAM_TRACK_ADDED, {
@@ -7128,9 +7138,25 @@ function getStream(constraintOpt_1) {
7128
7138
  let newConstraints;
7129
7139
  let retryConstraintOpt;
7130
7140
  let stream = null;
7141
+ const attempts = [];
7131
7142
  const only = (constraintOpt.audioId === false && "video") || (constraintOpt.videoId === false && "audio");
7132
7143
  const stopTracks = isMobile || only !== "video";
7133
7144
  const constraints = getConstraints(constraintOpt);
7145
+ const attempt = (c) => __awaiter(this, void 0, void 0, function* () {
7146
+ var _a, _b;
7147
+ try {
7148
+ const s = yield getUserMedia(c);
7149
+ attempts.push({ constraints: c, outcome: { ok: true } });
7150
+ return s;
7151
+ }
7152
+ catch (e) {
7153
+ attempts.push({
7154
+ constraints: c,
7155
+ outcome: Object.assign({ ok: false, errorName: (_a = e === null || e === void 0 ? void 0 : e.name) !== null && _a !== void 0 ? _a : "UnknownError", errorMessage: (_b = e === null || e === void 0 ? void 0 : e.message) !== null && _b !== void 0 ? _b : String(e) }, ((e === null || e === void 0 ? void 0 : e.constraint) && { constraint: e.constraint })),
7156
+ });
7157
+ throw e;
7158
+ }
7159
+ });
7134
7160
  const addDetails = (err, orgErr) => {
7135
7161
  if (err) {
7136
7162
  err.details = Object.assign({ constraints, constraint: err.constraint || (orgErr === null || orgErr === void 0 ? void 0 : orgErr.constraint), newConstraints,
@@ -7142,10 +7168,15 @@ function getStream(constraintOpt_1) {
7142
7168
  return new Error("Unknown error");
7143
7169
  }
7144
7170
  };
7171
+ const attachAttempts = (err) => {
7172
+ if (err)
7173
+ err.attempts = attempts;
7174
+ return err;
7175
+ };
7145
7176
  const getSingleStream = (e) => __awaiter(this, void 0, void 0, function* () {
7146
7177
  if (constraints.audio && constraints.video) {
7147
7178
  try {
7148
- stream = yield getUserMedia(getConstraints(Object.assign(Object.assign({}, constraintOpt), { audioId: false })));
7179
+ stream = yield attempt(getConstraints(Object.assign(Object.assign({}, constraintOpt), { audioId: false })));
7149
7180
  }
7150
7181
  catch (e2) {
7151
7182
  if ((e2 === null || e2 === void 0 ? void 0 : e2.name) !== "NotFoundError") {
@@ -7154,7 +7185,7 @@ function getStream(constraintOpt_1) {
7154
7185
  }
7155
7186
  try {
7156
7187
  if (!stream)
7157
- stream = yield getUserMedia(getConstraints(Object.assign(Object.assign({}, constraintOpt), { videoId: false })));
7188
+ stream = yield attempt(getConstraints(Object.assign(Object.assign({}, constraintOpt), { videoId: false })));
7158
7189
  }
7159
7190
  catch (e2) {
7160
7191
  addDetails(e2, e);
@@ -7164,12 +7195,12 @@ function getStream(constraintOpt_1) {
7164
7195
  if (stopTracks && replaceStream)
7165
7196
  stopStreamTracks(replaceStream, only);
7166
7197
  try {
7167
- stream = yield getUserMedia(constraints);
7198
+ stream = yield attempt(constraints);
7168
7199
  }
7169
7200
  catch (e) {
7170
7201
  error = e;
7171
7202
  if (!fallback) {
7172
- throw addDetails(e);
7203
+ throw attachAttempts(addDetails(e));
7173
7204
  }
7174
7205
  if ((e === null || e === void 0 ? void 0 : e.name) === "OverconstrainedError") {
7175
7206
  const laxConstraints = {
@@ -7193,7 +7224,7 @@ function getStream(constraintOpt_1) {
7193
7224
  }
7194
7225
  else if (e.name !== "NotAllowedError") {
7195
7226
  try {
7196
- stream = yield getUserMedia(getConstraints(Object.assign(Object.assign({}, constraintOpt), { options: Object.assign(Object.assign({}, constraintOpt.options), { lax: true }) })));
7227
+ stream = yield attempt(getConstraints(Object.assign(Object.assign({}, constraintOpt), { options: Object.assign(Object.assign({}, constraintOpt.options), { lax: true }) })));
7197
7228
  }
7198
7229
  catch (e2) {
7199
7230
  logger.warn(`Tried getting stream again with laxer constraints, but failed: ${"" + e2}`);
@@ -7202,7 +7233,7 @@ function getStream(constraintOpt_1) {
7202
7233
  const problemWith = { audio: "audioId", video: "videoId" }[((_a = /(video|audio)/.exec(errMsg)) === null || _a === void 0 ? void 0 : _a[0]) || only || ""];
7203
7234
  if (!stream && problemWith) {
7204
7235
  try {
7205
- stream = yield getUserMedia(getConstraints(Object.assign(Object.assign({}, constraintOpt), { [problemWith]: null })));
7236
+ stream = yield attempt(getConstraints(Object.assign(Object.assign({}, constraintOpt), { [problemWith]: null })));
7206
7237
  }
7207
7238
  catch (e2) {
7208
7239
  logger.warn(`Re-tried ${problemWith} with no constraints, but failed: ${"" + e2}`);
@@ -7212,7 +7243,7 @@ function getStream(constraintOpt_1) {
7212
7243
  const tryOnly = problemWith ? [problemWith] : ["videoId", "audioId"];
7213
7244
  for (const kind of tryOnly) {
7214
7245
  try {
7215
- stream = yield getUserMedia(getConstraints(Object.assign(Object.assign({}, constraintOpt), { [kind]: false })));
7246
+ stream = yield attempt(getConstraints(Object.assign(Object.assign({}, constraintOpt), { [kind]: false })));
7216
7247
  }
7217
7248
  catch (e2) {
7218
7249
  logger.warn(`Re-tried without ${kind}, but failed: ${"" + e2}`);
@@ -7229,16 +7260,17 @@ function getStream(constraintOpt_1) {
7229
7260
  }
7230
7261
  if (retryConstraintOpt) {
7231
7262
  const onlyConstraints = only ? { audio: { videoId: false }, video: { audioId: false } }[only] : {};
7232
- newConstraints = getConstraints(Object.assign(Object.assign(Object.assign(Object.assign({}, constraintOpt), retryConstraintOpt), { options: Object.assign(Object.assign({}, constraintOpt.options), { lax: retryConstraintOpt.lax }) }), onlyConstraints));
7263
+ const retryConstraints = getConstraints(Object.assign(Object.assign(Object.assign(Object.assign({}, constraintOpt), retryConstraintOpt), { options: Object.assign(Object.assign({}, constraintOpt.options), { lax: retryConstraintOpt.lax }) }), onlyConstraints));
7264
+ newConstraints = retryConstraints;
7233
7265
  try {
7234
- stream = yield getUserMedia(newConstraints);
7266
+ stream = yield attempt(retryConstraints);
7235
7267
  }
7236
7268
  catch (e) {
7237
- throw addDetails(e, error);
7269
+ throw attachAttempts(addDetails(e, error));
7238
7270
  }
7239
7271
  }
7240
7272
  if (!stream) {
7241
- throw addDetails(error);
7273
+ throw attachAttempts(addDetails(error));
7242
7274
  }
7243
7275
  let replacedTracks;
7244
7276
  if (replaceStream) {
@@ -7247,7 +7279,7 @@ function getStream(constraintOpt_1) {
7247
7279
  replacedTracks = replaceTracksInStream(replaceStream, stream, only);
7248
7280
  stream = replaceStream;
7249
7281
  }
7250
- return { error: error && addDetails(error), stream, replacedTracks };
7282
+ return { error: error && addDetails(error), stream, replacedTracks, attempts };
7251
7283
  });
7252
7284
  }
7253
7285
  function hasGetDisplayMedia() {
@@ -2552,8 +2552,9 @@ class P2pRtcManager {
2552
2552
  isInitializedWith({ selfId, roomName, isSfu }) {
2553
2553
  return this._selfId === selfId && this._roomName === roomName && !isSfu;
2554
2554
  }
2555
- addCameraStream(stream, { beforeEffectTracks = [] } = { beforeEffectTracks: [] }) {
2555
+ addCameraStream(stream, { videoPaused, beforeEffectTracks = [] } = { beforeEffectTracks: [] }) {
2556
2556
  logger$6.info("addCameraStream: [stream.id: %s]", stream.id);
2557
+ this._webcamPaused = videoPaused;
2557
2558
  if (stream === this._localCameraStream) {
2558
2559
  return;
2559
2560
  }
@@ -3433,6 +3434,7 @@ class P2pRtcManager {
3433
3434
  stopOrResumeVideo(localStream, enable) {
3434
3435
  var _a;
3435
3436
  logger$6.info("stopOrResumeVideo() [enable: %s]", enable);
3437
+ this._webcamPaused = !enable;
3436
3438
  if (!["chrome", "safari"].includes(browserName$1)) {
3437
3439
  return;
3438
3440
  }
@@ -3466,6 +3468,10 @@ class P2pRtcManager {
3466
3468
  .getUserMedia({ video: constraints })
3467
3469
  .then((stream) => {
3468
3470
  const track = stream.getVideoTracks()[0];
3471
+ if (this._webcamPaused) {
3472
+ track.stop();
3473
+ return;
3474
+ }
3469
3475
  localStream.addTrack(track);
3470
3476
  this._monitorVideoTrack(track);
3471
3477
  this._emit(EVENTS.LOCAL_STREAM_TRACK_ADDED, {
@@ -5499,6 +5505,10 @@ class VegaRtcManager {
5499
5505
  .getUserMedia({ video: constraints })
5500
5506
  .then((stream) => {
5501
5507
  const track = stream.getVideoTracks()[0];
5508
+ if (this._webcamPaused) {
5509
+ track.stop();
5510
+ return;
5511
+ }
5502
5512
  localStream.addTrack(track);
5503
5513
  this._monitorVideoTrack(track);
5504
5514
  this._emitToPWA(EVENTS.LOCAL_STREAM_TRACK_ADDED, {
@@ -7128,9 +7138,25 @@ function getStream(constraintOpt_1) {
7128
7138
  let newConstraints;
7129
7139
  let retryConstraintOpt;
7130
7140
  let stream = null;
7141
+ const attempts = [];
7131
7142
  const only = (constraintOpt.audioId === false && "video") || (constraintOpt.videoId === false && "audio");
7132
7143
  const stopTracks = isMobile || only !== "video";
7133
7144
  const constraints = getConstraints(constraintOpt);
7145
+ const attempt = (c) => __awaiter(this, void 0, void 0, function* () {
7146
+ var _a, _b;
7147
+ try {
7148
+ const s = yield getUserMedia(c);
7149
+ attempts.push({ constraints: c, outcome: { ok: true } });
7150
+ return s;
7151
+ }
7152
+ catch (e) {
7153
+ attempts.push({
7154
+ constraints: c,
7155
+ outcome: Object.assign({ ok: false, errorName: (_a = e === null || e === void 0 ? void 0 : e.name) !== null && _a !== void 0 ? _a : "UnknownError", errorMessage: (_b = e === null || e === void 0 ? void 0 : e.message) !== null && _b !== void 0 ? _b : String(e) }, ((e === null || e === void 0 ? void 0 : e.constraint) && { constraint: e.constraint })),
7156
+ });
7157
+ throw e;
7158
+ }
7159
+ });
7134
7160
  const addDetails = (err, orgErr) => {
7135
7161
  if (err) {
7136
7162
  err.details = Object.assign({ constraints, constraint: err.constraint || (orgErr === null || orgErr === void 0 ? void 0 : orgErr.constraint), newConstraints,
@@ -7142,10 +7168,15 @@ function getStream(constraintOpt_1) {
7142
7168
  return new Error("Unknown error");
7143
7169
  }
7144
7170
  };
7171
+ const attachAttempts = (err) => {
7172
+ if (err)
7173
+ err.attempts = attempts;
7174
+ return err;
7175
+ };
7145
7176
  const getSingleStream = (e) => __awaiter(this, void 0, void 0, function* () {
7146
7177
  if (constraints.audio && constraints.video) {
7147
7178
  try {
7148
- stream = yield getUserMedia(getConstraints(Object.assign(Object.assign({}, constraintOpt), { audioId: false })));
7179
+ stream = yield attempt(getConstraints(Object.assign(Object.assign({}, constraintOpt), { audioId: false })));
7149
7180
  }
7150
7181
  catch (e2) {
7151
7182
  if ((e2 === null || e2 === void 0 ? void 0 : e2.name) !== "NotFoundError") {
@@ -7154,7 +7185,7 @@ function getStream(constraintOpt_1) {
7154
7185
  }
7155
7186
  try {
7156
7187
  if (!stream)
7157
- stream = yield getUserMedia(getConstraints(Object.assign(Object.assign({}, constraintOpt), { videoId: false })));
7188
+ stream = yield attempt(getConstraints(Object.assign(Object.assign({}, constraintOpt), { videoId: false })));
7158
7189
  }
7159
7190
  catch (e2) {
7160
7191
  addDetails(e2, e);
@@ -7164,12 +7195,12 @@ function getStream(constraintOpt_1) {
7164
7195
  if (stopTracks && replaceStream)
7165
7196
  stopStreamTracks(replaceStream, only);
7166
7197
  try {
7167
- stream = yield getUserMedia(constraints);
7198
+ stream = yield attempt(constraints);
7168
7199
  }
7169
7200
  catch (e) {
7170
7201
  error = e;
7171
7202
  if (!fallback) {
7172
- throw addDetails(e);
7203
+ throw attachAttempts(addDetails(e));
7173
7204
  }
7174
7205
  if ((e === null || e === void 0 ? void 0 : e.name) === "OverconstrainedError") {
7175
7206
  const laxConstraints = {
@@ -7193,7 +7224,7 @@ function getStream(constraintOpt_1) {
7193
7224
  }
7194
7225
  else if (e.name !== "NotAllowedError") {
7195
7226
  try {
7196
- stream = yield getUserMedia(getConstraints(Object.assign(Object.assign({}, constraintOpt), { options: Object.assign(Object.assign({}, constraintOpt.options), { lax: true }) })));
7227
+ stream = yield attempt(getConstraints(Object.assign(Object.assign({}, constraintOpt), { options: Object.assign(Object.assign({}, constraintOpt.options), { lax: true }) })));
7197
7228
  }
7198
7229
  catch (e2) {
7199
7230
  logger.warn(`Tried getting stream again with laxer constraints, but failed: ${"" + e2}`);
@@ -7202,7 +7233,7 @@ function getStream(constraintOpt_1) {
7202
7233
  const problemWith = { audio: "audioId", video: "videoId" }[((_a = /(video|audio)/.exec(errMsg)) === null || _a === void 0 ? void 0 : _a[0]) || only || ""];
7203
7234
  if (!stream && problemWith) {
7204
7235
  try {
7205
- stream = yield getUserMedia(getConstraints(Object.assign(Object.assign({}, constraintOpt), { [problemWith]: null })));
7236
+ stream = yield attempt(getConstraints(Object.assign(Object.assign({}, constraintOpt), { [problemWith]: null })));
7206
7237
  }
7207
7238
  catch (e2) {
7208
7239
  logger.warn(`Re-tried ${problemWith} with no constraints, but failed: ${"" + e2}`);
@@ -7212,7 +7243,7 @@ function getStream(constraintOpt_1) {
7212
7243
  const tryOnly = problemWith ? [problemWith] : ["videoId", "audioId"];
7213
7244
  for (const kind of tryOnly) {
7214
7245
  try {
7215
- stream = yield getUserMedia(getConstraints(Object.assign(Object.assign({}, constraintOpt), { [kind]: false })));
7246
+ stream = yield attempt(getConstraints(Object.assign(Object.assign({}, constraintOpt), { [kind]: false })));
7216
7247
  }
7217
7248
  catch (e2) {
7218
7249
  logger.warn(`Re-tried without ${kind}, but failed: ${"" + e2}`);
@@ -7229,16 +7260,17 @@ function getStream(constraintOpt_1) {
7229
7260
  }
7230
7261
  if (retryConstraintOpt) {
7231
7262
  const onlyConstraints = only ? { audio: { videoId: false }, video: { audioId: false } }[only] : {};
7232
- newConstraints = getConstraints(Object.assign(Object.assign(Object.assign(Object.assign({}, constraintOpt), retryConstraintOpt), { options: Object.assign(Object.assign({}, constraintOpt.options), { lax: retryConstraintOpt.lax }) }), onlyConstraints));
7263
+ const retryConstraints = getConstraints(Object.assign(Object.assign(Object.assign(Object.assign({}, constraintOpt), retryConstraintOpt), { options: Object.assign(Object.assign({}, constraintOpt.options), { lax: retryConstraintOpt.lax }) }), onlyConstraints));
7264
+ newConstraints = retryConstraints;
7233
7265
  try {
7234
- stream = yield getUserMedia(newConstraints);
7266
+ stream = yield attempt(retryConstraints);
7235
7267
  }
7236
7268
  catch (e) {
7237
- throw addDetails(e, error);
7269
+ throw attachAttempts(addDetails(e, error));
7238
7270
  }
7239
7271
  }
7240
7272
  if (!stream) {
7241
- throw addDetails(error);
7273
+ throw attachAttempts(addDetails(error));
7242
7274
  }
7243
7275
  let replacedTracks;
7244
7276
  if (replaceStream) {
@@ -7247,7 +7279,7 @@ function getStream(constraintOpt_1) {
7247
7279
  replacedTracks = replaceTracksInStream(replaceStream, stream, only);
7248
7280
  stream = replaceStream;
7249
7281
  }
7250
- return { error: error && addDetails(error), stream, replacedTracks };
7282
+ return { error: error && addDetails(error), stream, replacedTracks, attempts };
7251
7283
  });
7252
7284
  }
7253
7285
  function hasGetDisplayMedia() {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@whereby.com/media",
3
3
  "description": "Media library for Whereby",
4
- "version": "9.0.0",
4
+ "version": "9.1.1",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/whereby/sdk",
7
7
  "repository": {
@@ -61,8 +61,8 @@
61
61
  "prettier": "^3.5.3",
62
62
  "process": "^0.11.10",
63
63
  "typescript": "^5.8.3",
64
- "@whereby.com/eslint-config": "0.1.0",
65
64
  "@whereby.com/jest-config": "0.1.0",
65
+ "@whereby.com/eslint-config": "0.1.0",
66
66
  "@whereby.com/prettier-config": "0.1.0",
67
67
  "@whereby.com/rollup-config": "0.1.1",
68
68
  "@whereby.com/tsconfig": "0.1.0"