@stream-io/video-client 1.11.7 → 1.11.9

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.js CHANGED
@@ -3318,7 +3318,7 @@ const retryable = async (rpc, signal) => {
3318
3318
  return result;
3319
3319
  };
3320
3320
 
3321
- const version = "1.11.7";
3321
+ const version = "1.11.9";
3322
3322
  const [major, minor, patch] = version.split('.');
3323
3323
  let sdkInfo = {
3324
3324
  type: SdkType.PLAIN_JAVASCRIPT,
@@ -3424,7 +3424,7 @@ var browsers = /*#__PURE__*/Object.freeze({
3424
3424
  * @param codecToRemove the codec to exclude from the list.
3425
3425
  * @param codecPreferencesSource the source of the codec preferences.
3426
3426
  */
3427
- const getPreferredCodecs = (kind, preferredCodec, codecToRemove, codecPreferencesSource = 'receiver') => {
3427
+ const getPreferredCodecs = (kind, preferredCodec, codecToRemove, codecPreferencesSource) => {
3428
3428
  const source = codecPreferencesSource === 'receiver' ? RTCRtpReceiver : RTCRtpSender;
3429
3429
  if (!('getCapabilities' in source))
3430
3430
  return;
@@ -3460,10 +3460,7 @@ const getPreferredCodecs = (kind, preferredCodec, codecToRemove, codecPreference
3460
3460
  partiallyPreferred.push(codec);
3461
3461
  continue;
3462
3462
  }
3463
- // packetization-mode mode is optional; when not present it defaults to 0:
3464
- // https://datatracker.ietf.org/doc/html/rfc6184#section-6.2
3465
- if (sdpFmtpLine.includes('packetization-mode=0') ||
3466
- !sdpFmtpLine.includes('packetization-mode')) {
3463
+ if (sdpFmtpLine.includes('packetization-mode=1')) {
3467
3464
  preferred.unshift(codec);
3468
3465
  }
3469
3466
  else {
@@ -3500,8 +3497,9 @@ const getOptimalVideoCodec = (preferredCodec) => {
3500
3497
  const os = getOSInfo()?.name.toLowerCase();
3501
3498
  if (os === 'android')
3502
3499
  return preferredOr(preferredCodec, 'vp8');
3503
- if (os === 'ios' || os === 'ipados')
3504
- return 'h264';
3500
+ if (os === 'ios' || os === 'ipados') {
3501
+ return supportsH264Baseline() ? 'h264' : 'vp8';
3502
+ }
3505
3503
  return preferredOr(preferredCodec, 'h264');
3506
3504
  }
3507
3505
  if (isSafari())
@@ -3532,6 +3530,18 @@ const preferredOr = (codec, fallback) => {
3532
3530
  ? codec
3533
3531
  : fallback;
3534
3532
  };
3533
+ /**
3534
+ * Returns whether the platform supports the H264 baseline codec.
3535
+ */
3536
+ const supportsH264Baseline = () => {
3537
+ if (!('getCapabilities' in RTCRtpSender))
3538
+ return false;
3539
+ const capabilities = RTCRtpSender.getCapabilities('video');
3540
+ if (!capabilities)
3541
+ return false;
3542
+ return capabilities.codecs.some((c) => c.mimeType.toLowerCase() === 'video/h264' &&
3543
+ c.sdpFmtpLine?.includes('profile-level-id=42e01f'));
3544
+ };
3535
3545
  /**
3536
3546
  * Returns whether the codec is an SVC codec.
3537
3547
  *
@@ -5504,8 +5514,14 @@ const preserveCodec = (sdp, mid, codec) => {
5504
5514
  // find the payload id of the desired codec
5505
5515
  const payloads = new Set();
5506
5516
  for (const rtp of media.rtp) {
5507
- if (rtp.codec.toLowerCase() === codecName &&
5508
- media.fmtp.some((f) => f.payload === rtp.payload && equal(toSet(f.config), codecFmtp))) {
5517
+ if (rtp.codec.toLowerCase() !== codecName)
5518
+ continue;
5519
+ const match =
5520
+ // vp8 doesn't have any fmtp, we preserve it without any additional checks
5521
+ codecName === 'vp8'
5522
+ ? true
5523
+ : media.fmtp.some((f) => f.payload === rtp.payload && equal(toSet(f.config), codecFmtp));
5524
+ if (match) {
5509
5525
  payloads.add(rtp.payload);
5510
5526
  }
5511
5527
  }
@@ -5707,7 +5723,7 @@ class Publisher {
5707
5723
  // handle codec preferences
5708
5724
  if (!('setCodecPreferences' in transceiver))
5709
5725
  return;
5710
- const codecPreferences = this.getCodecPreferences(trackType, trackType === TrackType.VIDEO ? codecInUse : undefined);
5726
+ const codecPreferences = this.getCodecPreferences(trackType, trackType === TrackType.VIDEO ? codecInUse : undefined, 'receiver');
5711
5727
  if (!codecPreferences)
5712
5728
  return;
5713
5729
  try {
@@ -5868,12 +5884,12 @@ class Publisher {
5868
5884
  };
5869
5885
  this.getCodecPreferences = (trackType, preferredCodec, codecPreferencesSource) => {
5870
5886
  if (trackType === TrackType.VIDEO) {
5871
- return getPreferredCodecs('video', preferredCodec || 'vp8', codecPreferencesSource);
5887
+ return getPreferredCodecs('video', preferredCodec || 'vp8', undefined, codecPreferencesSource);
5872
5888
  }
5873
5889
  if (trackType === TrackType.AUDIO) {
5874
5890
  const defaultAudioCodec = this.isRedEnabled ? 'red' : 'opus';
5875
5891
  const codecToRemove = !this.isRedEnabled ? 'red' : undefined;
5876
- return getPreferredCodecs('audio', preferredCodec ?? defaultAudioCodec, codecToRemove);
5892
+ return getPreferredCodecs('audio', preferredCodec ?? defaultAudioCodec, codecToRemove, codecPreferencesSource);
5877
5893
  }
5878
5894
  };
5879
5895
  this.onIceCandidate = (e) => {
@@ -6098,7 +6114,8 @@ class Publisher {
6098
6114
  }
6099
6115
  removeUnpreferredCodecs(sdp, trackType) {
6100
6116
  const opts = this.publishOptsForTrack.get(trackType);
6101
- if (!opts || !opts.forceSingleCodec)
6117
+ const forceSingleCodec = !!opts?.forceSingleCodec || isReactNative() || isFirefox();
6118
+ if (!opts || !forceSingleCodec)
6102
6119
  return sdp;
6103
6120
  const codec = opts.forceCodec || getOptimalVideoCodec(opts.preferredCodec);
6104
6121
  const orderedCodecs = this.getCodecPreferences(trackType, codec, 'sender');
@@ -8348,7 +8365,7 @@ const getAudioStream = async (trackConstraints) => {
8348
8365
  const constraints = {
8349
8366
  audio: {
8350
8367
  ...audioDeviceConstraints.audio,
8351
- ...trackConstraints,
8368
+ ...normalizeContraints(trackConstraints),
8352
8369
  },
8353
8370
  };
8354
8371
  try {
@@ -8359,11 +8376,6 @@ const getAudioStream = async (trackConstraints) => {
8359
8376
  return await getStream(constraints);
8360
8377
  }
8361
8378
  catch (error) {
8362
- if (error instanceof OverconstrainedError && trackConstraints?.deviceId) {
8363
- const { deviceId, ...relaxedContraints } = trackConstraints;
8364
- getLogger(['devices'])('warn', 'Failed to get audio stream, will try again with relaxed contraints', { error, constraints, relaxedContraints });
8365
- return getAudioStream(relaxedContraints);
8366
- }
8367
8379
  getLogger(['devices'])('error', 'Failed to get audio stream', {
8368
8380
  error,
8369
8381
  constraints,
@@ -8383,7 +8395,7 @@ const getVideoStream = async (trackConstraints) => {
8383
8395
  const constraints = {
8384
8396
  video: {
8385
8397
  ...videoDeviceConstraints.video,
8386
- ...trackConstraints,
8398
+ ...normalizeContraints(trackConstraints),
8387
8399
  },
8388
8400
  };
8389
8401
  try {
@@ -8394,11 +8406,6 @@ const getVideoStream = async (trackConstraints) => {
8394
8406
  return await getStream(constraints);
8395
8407
  }
8396
8408
  catch (error) {
8397
- if (error instanceof OverconstrainedError && trackConstraints?.deviceId) {
8398
- const { deviceId, ...relaxedContraints } = trackConstraints;
8399
- getLogger(['devices'])('warn', 'Failed to get video stream, will try again with relaxed contraints', { error, constraints, relaxedContraints });
8400
- return getVideoStream(relaxedContraints);
8401
- }
8402
8409
  getLogger(['devices'])('error', 'Failed to get video stream', {
8403
8410
  error,
8404
8411
  constraints,
@@ -8406,6 +8413,16 @@ const getVideoStream = async (trackConstraints) => {
8406
8413
  throw error;
8407
8414
  }
8408
8415
  };
8416
+ function normalizeContraints(constraints) {
8417
+ if (constraints?.deviceId === 'default' ||
8418
+ (typeof constraints?.deviceId === 'object' &&
8419
+ 'exact' in constraints.deviceId &&
8420
+ constraints.deviceId.exact === 'default')) {
8421
+ const { deviceId, ...contraintsWithoutDeviceId } = constraints;
8422
+ return contraintsWithoutDeviceId;
8423
+ }
8424
+ return constraints;
8425
+ }
8409
8426
  /**
8410
8427
  * Prompts the user for a permission to share a screen.
8411
8428
  * If the user grants the permission, a screen sharing stream is returned. Throws otherwise.
@@ -8632,6 +8649,7 @@ class InputMediaDeviceManager {
8632
8649
  }
8633
8650
  catch (error) {
8634
8651
  this.state.setDevice(prevDeviceId);
8652
+ await this.applySettingsToStream();
8635
8653
  throw error;
8636
8654
  }
8637
8655
  }
@@ -12615,7 +12633,7 @@ class StreamClient {
12615
12633
  return await this.wsConnection.connect(this.defaultWSTimeout);
12616
12634
  };
12617
12635
  this.getUserAgent = () => {
12618
- const version = "1.11.7";
12636
+ const version = "1.11.9";
12619
12637
  return (this.userAgent ||
12620
12638
  `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
12621
12639
  };