@stream-io/video-client 1.24.0 → 1.25.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/index.browser.es.js +367 -128
  3. package/dist/index.browser.es.js.map +1 -1
  4. package/dist/index.cjs.js +366 -127
  5. package/dist/index.cjs.js.map +1 -1
  6. package/dist/index.es.js +367 -128
  7. package/dist/index.es.js.map +1 -1
  8. package/dist/src/StreamSfuClient.d.ts +12 -4
  9. package/dist/src/StreamVideoClient.d.ts +3 -1
  10. package/dist/src/coordinator/connection/errors.d.ts +1 -0
  11. package/dist/src/devices/InputMediaDeviceManager.d.ts +2 -0
  12. package/dist/src/devices/MicrophoneManager.d.ts +1 -0
  13. package/dist/src/devices/ScreenShareManager.d.ts +1 -0
  14. package/dist/src/devices/SpeakerManager.d.ts +2 -0
  15. package/dist/src/gen/video/sfu/models/models.d.ts +4 -0
  16. package/dist/src/rtc/BasePeerConnection.d.ts +23 -4
  17. package/dist/src/rtc/NegotiationError.d.ts +15 -0
  18. package/dist/src/rtc/Publisher.d.ts +2 -2
  19. package/dist/src/rtc/helpers/sdp.d.ts +7 -0
  20. package/dist/src/types.d.ts +11 -0
  21. package/package.json +1 -1
  22. package/src/Call.ts +72 -38
  23. package/src/StreamSfuClient.ts +17 -7
  24. package/src/StreamVideoClient.ts +17 -7
  25. package/src/coordinator/connection/connection.ts +2 -1
  26. package/src/coordinator/connection/errors.ts +31 -0
  27. package/src/devices/CameraManagerState.ts +1 -1
  28. package/src/devices/InputMediaDeviceManager.ts +13 -0
  29. package/src/devices/MicrophoneManager.ts +3 -0
  30. package/src/devices/ScreenShareManager.ts +18 -5
  31. package/src/devices/SpeakerManager.ts +13 -0
  32. package/src/devices/devices.ts +23 -12
  33. package/src/events/__tests__/internal.test.ts +1 -0
  34. package/src/gen/google/protobuf/struct.ts +2 -2
  35. package/src/gen/google/protobuf/timestamp.ts +1 -1
  36. package/src/gen/video/sfu/event/events.ts +15 -15
  37. package/src/gen/video/sfu/models/models.ts +9 -5
  38. package/src/gen/video/sfu/signal_rpc/signal.client.ts +1 -1
  39. package/src/gen/video/sfu/signal_rpc/signal.ts +6 -6
  40. package/src/rtc/BasePeerConnection.ts +132 -46
  41. package/src/rtc/NegotiationError.ts +21 -0
  42. package/src/rtc/Publisher.ts +12 -9
  43. package/src/rtc/Subscriber.ts +8 -2
  44. package/src/rtc/__tests__/Publisher.test.ts +160 -17
  45. package/src/rtc/__tests__/Subscriber.test.ts +31 -14
  46. package/src/rtc/helpers/__tests__/sdp.stereo.test.ts +120 -0
  47. package/src/rtc/helpers/sdp.ts +43 -1
  48. package/src/types.ts +12 -0
@@ -13,9 +13,12 @@ export class ScreenShareManager extends InputMediaDeviceManager<
13
13
  > {
14
14
  constructor(call: Call) {
15
15
  super(call, new ScreenShareState(), TrackType.SCREEN_SHARE);
16
+ }
16
17
 
18
+ override setup(): void {
19
+ super.setup();
17
20
  this.subscriptions.push(
18
- createSubscription(call.state.settings$, (settings) => {
21
+ createSubscription(this.call.state.settings$, (settings) => {
19
22
  const maybeTargetResolution = settings?.screensharing.target_resolution;
20
23
 
21
24
  if (maybeTargetResolution) {
@@ -70,16 +73,26 @@ export class ScreenShareManager extends InputMediaDeviceManager<
70
73
  return of([]); // there are no devices to be listed for Screen Share
71
74
  }
72
75
 
73
- protected getStream(
76
+ protected async getStream(
74
77
  constraints: DisplayMediaStreamOptions,
75
78
  ): Promise<MediaStream> {
76
79
  if (!this.state.audioEnabled) {
77
80
  constraints.audio = false;
78
81
  }
79
- return getScreenShareStream(constraints, this.call.tracer);
82
+ const stream = await getScreenShareStream(constraints, this.call.tracer);
83
+ const [track] = stream.getVideoTracks();
84
+ const { contentHint } = this.state.settings || {};
85
+ if (typeof contentHint !== 'undefined' && track && 'contentHint' in track) {
86
+ this.call.tracer.trace(
87
+ 'navigator.mediaDevices.getDisplayMedia.contentHint',
88
+ contentHint,
89
+ );
90
+ track.contentHint = contentHint;
91
+ }
92
+ return stream;
80
93
  }
81
94
 
82
- protected async stopPublishStream(): Promise<void> {
95
+ protected override async stopPublishStream(): Promise<void> {
83
96
  return this.call.stopPublish(
84
97
  TrackType.SCREEN_SHARE,
85
98
  TrackType.SCREEN_SHARE_AUDIO,
@@ -89,7 +102,7 @@ export class ScreenShareManager extends InputMediaDeviceManager<
89
102
  /**
90
103
  * Overrides the default `select` method to throw an error.
91
104
  */
92
- async select(): Promise<void> {
105
+ override async select(): Promise<void> {
93
106
  throw new Error('Not supported');
94
107
  }
95
108
  }
@@ -7,11 +7,22 @@ import { deviceIds$, getAudioOutputDevices } from './devices';
7
7
  export class SpeakerManager {
8
8
  readonly state: SpeakerState;
9
9
  private subscriptions: Subscription[] = [];
10
+ private areSubscriptionsSetUp = false;
10
11
  private readonly call: Call;
11
12
 
12
13
  constructor(call: Call) {
13
14
  this.call = call;
14
15
  this.state = new SpeakerState(call.tracer);
16
+ this.setup();
17
+ }
18
+
19
+ setup() {
20
+ if (this.areSubscriptionsSetUp) {
21
+ return;
22
+ }
23
+
24
+ this.areSubscriptionsSetUp = true;
25
+
15
26
  if (deviceIds$ && !isReactNative()) {
16
27
  this.subscriptions.push(
17
28
  combineLatest([deviceIds$!, this.state.selectedDevice$]).subscribe(
@@ -71,6 +82,8 @@ export class SpeakerManager {
71
82
  */
72
83
  dispose = () => {
73
84
  this.subscriptions.forEach((s) => s.unsubscribe());
85
+ this.subscriptions = [];
86
+ this.areSubscriptionsSetUp = false;
74
87
  };
75
88
 
76
89
  /**
@@ -324,21 +324,32 @@ export const getScreenShareStream = async (
324
324
  ) => {
325
325
  const tag = `navigator.mediaDevices.getDisplayMedia.${getDisplayMediaExecId++}.`;
326
326
  try {
327
- tracer?.trace(tag, options);
328
- const stream = await navigator.mediaDevices.getDisplayMedia({
329
- video: true,
330
- audio: {
331
- channelCount: {
332
- ideal: 2,
333
- },
334
- echoCancellation: false,
335
- autoGainControl: false,
336
- noiseSuppression: false,
337
- },
327
+ const constraints: DisplayMediaStreamOptions = {
338
328
  // @ts-expect-error - not present in types yet
339
329
  systemAudio: 'include',
340
330
  ...options,
341
- });
331
+ video:
332
+ typeof options?.video === 'boolean'
333
+ ? options.video // must be 'true'
334
+ : {
335
+ width: { max: 2560 },
336
+ height: { max: 1440 },
337
+ frameRate: { ideal: 30 },
338
+ ...options?.video,
339
+ },
340
+ audio:
341
+ typeof options?.audio === 'boolean'
342
+ ? options.audio
343
+ : {
344
+ channelCount: { ideal: 2 },
345
+ echoCancellation: false,
346
+ autoGainControl: false,
347
+ noiseSuppression: false,
348
+ ...options?.audio,
349
+ },
350
+ };
351
+ tracer?.trace(tag, constraints);
352
+ const stream = await navigator.mediaDevices.getDisplayMedia(constraints);
342
353
  tracer?.trace(`${tag}OnSuccess`, dumpStream(stream));
343
354
  return stream;
344
355
  } catch (e) {
@@ -97,6 +97,7 @@ describe('internal events', () => {
97
97
  permissionsContext: { hasPermission: () => true },
98
98
  leave: vi.fn().mockResolvedValue(undefined),
99
99
  logger: vi.fn(),
100
+ state: new CallState(),
100
101
  } as unknown as Call;
101
102
 
102
103
  watchLiveEnded(dispatcher, call);
@@ -5,7 +5,7 @@ import type {
5
5
  JsonValue,
6
6
  JsonWriteOptions,
7
7
  } from '@protobuf-ts/runtime';
8
- // @generated by protobuf-ts 2.9.6 with parameter long_type_string,client_generic,server_none,eslint_disable,optimize_code_size
8
+ // @generated by protobuf-ts 2.10.0 with parameter long_type_string,client_generic,server_none,eslint_disable,optimize_code_size
9
9
  // @generated from protobuf file "google/protobuf/struct.proto" (package "google.protobuf", syntax proto3)
10
10
  // tslint:disable
11
11
  //
@@ -358,7 +358,7 @@ class ListValue$Type extends MessageType<ListValue> {
358
358
  no: 1,
359
359
  name: 'values',
360
360
  kind: 'message',
361
- repeat: 1 /*RepeatType.PACKED*/,
361
+ repeat: 2 /*RepeatType.UNPACKED*/,
362
362
  T: () => Value,
363
363
  },
364
364
  ]);
@@ -4,7 +4,7 @@ import type {
4
4
  JsonValue,
5
5
  JsonWriteOptions,
6
6
  } from '@protobuf-ts/runtime';
7
- // @generated by protobuf-ts 2.9.6 with parameter long_type_string,client_generic,server_none,eslint_disable,optimize_code_size
7
+ // @generated by protobuf-ts 2.10.0 with parameter long_type_string,client_generic,server_none,eslint_disable,optimize_code_size
8
8
  // @generated from protobuf file "google/protobuf/timestamp.proto" (package "google.protobuf", syntax proto3)
9
9
  // tslint:disable
10
10
  //
@@ -1,4 +1,4 @@
1
- // @generated by protobuf-ts 2.9.6 with parameter long_type_string,client_generic,server_none,eslint_disable,optimize_code_size
1
+ // @generated by protobuf-ts 2.10.0 with parameter long_type_string,client_generic,server_none,eslint_disable,optimize_code_size
2
2
  // @generated from protobuf file "video/sfu/event/events.proto" (package "stream.video.sfu.event", syntax proto3)
3
3
  // tslint:disable
4
4
  import { MessageType } from '@protobuf-ts/runtime';
@@ -1048,7 +1048,7 @@ class ChangePublishOptions$Type extends MessageType<ChangePublishOptions> {
1048
1048
  no: 1,
1049
1049
  name: 'publish_options',
1050
1050
  kind: 'message',
1051
- repeat: 1 /*RepeatType.PACKED*/,
1051
+ repeat: 2 /*RepeatType.UNPACKED*/,
1052
1052
  T: () => PublishOption,
1053
1053
  },
1054
1054
  { no: 2, name: 'reason', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
@@ -1089,7 +1089,7 @@ class PinsChanged$Type extends MessageType<PinsChanged> {
1089
1089
  no: 1,
1090
1090
  name: 'pins',
1091
1091
  kind: 'message',
1092
- repeat: 1 /*RepeatType.PACKED*/,
1092
+ repeat: 2 /*RepeatType.UNPACKED*/,
1093
1093
  T: () => Pin,
1094
1094
  },
1095
1095
  ]);
@@ -1332,14 +1332,14 @@ class JoinRequest$Type extends MessageType<JoinRequest> {
1332
1332
  no: 9,
1333
1333
  name: 'preferred_publish_options',
1334
1334
  kind: 'message',
1335
- repeat: 1 /*RepeatType.PACKED*/,
1335
+ repeat: 2 /*RepeatType.UNPACKED*/,
1336
1336
  T: () => PublishOption,
1337
1337
  },
1338
1338
  {
1339
1339
  no: 10,
1340
1340
  name: 'preferred_subscribe_options',
1341
1341
  kind: 'message',
1342
- repeat: 1 /*RepeatType.PACKED*/,
1342
+ repeat: 2 /*RepeatType.UNPACKED*/,
1343
1343
  T: () => SubscribeOption,
1344
1344
  },
1345
1345
  ]);
@@ -1367,14 +1367,14 @@ class ReconnectDetails$Type extends MessageType<ReconnectDetails> {
1367
1367
  no: 3,
1368
1368
  name: 'announced_tracks',
1369
1369
  kind: 'message',
1370
- repeat: 1 /*RepeatType.PACKED*/,
1370
+ repeat: 2 /*RepeatType.UNPACKED*/,
1371
1371
  T: () => TrackInfo,
1372
1372
  },
1373
1373
  {
1374
1374
  no: 4,
1375
1375
  name: 'subscriptions',
1376
1376
  kind: 'message',
1377
- repeat: 1 /*RepeatType.PACKED*/,
1377
+ repeat: 2 /*RepeatType.UNPACKED*/,
1378
1378
  T: () => TrackSubscriptionDetails,
1379
1379
  },
1380
1380
  {
@@ -1417,14 +1417,14 @@ class Migration$Type extends MessageType<Migration> {
1417
1417
  no: 2,
1418
1418
  name: 'announced_tracks',
1419
1419
  kind: 'message',
1420
- repeat: 1 /*RepeatType.PACKED*/,
1420
+ repeat: 2 /*RepeatType.UNPACKED*/,
1421
1421
  T: () => TrackInfo,
1422
1422
  },
1423
1423
  {
1424
1424
  no: 3,
1425
1425
  name: 'subscriptions',
1426
1426
  kind: 'message',
1427
- repeat: 1 /*RepeatType.PACKED*/,
1427
+ repeat: 2 /*RepeatType.UNPACKED*/,
1428
1428
  T: () => TrackSubscriptionDetails,
1429
1429
  },
1430
1430
  ]);
@@ -1450,7 +1450,7 @@ class JoinResponse$Type extends MessageType<JoinResponse> {
1450
1450
  no: 4,
1451
1451
  name: 'publish_options',
1452
1452
  kind: 'message',
1453
- repeat: 1 /*RepeatType.PACKED*/,
1453
+ repeat: 2 /*RepeatType.UNPACKED*/,
1454
1454
  T: () => PublishOption,
1455
1455
  },
1456
1456
  ]);
@@ -1532,7 +1532,7 @@ class ConnectionQualityChanged$Type extends MessageType<ConnectionQualityChanged
1532
1532
  no: 1,
1533
1533
  name: 'connection_quality_updates',
1534
1534
  kind: 'message',
1535
- repeat: 1 /*RepeatType.PACKED*/,
1535
+ repeat: 2 /*RepeatType.UNPACKED*/,
1536
1536
  T: () => ConnectionQualityInfo,
1537
1537
  },
1538
1538
  ]);
@@ -1601,7 +1601,7 @@ class AudioLevelChanged$Type extends MessageType<AudioLevelChanged> {
1601
1601
  no: 1,
1602
1602
  name: 'audio_levels',
1603
1603
  kind: 'message',
1604
- repeat: 1 /*RepeatType.PACKED*/,
1604
+ repeat: 2 /*RepeatType.UNPACKED*/,
1605
1605
  T: () => AudioLevel,
1606
1606
  },
1607
1607
  ]);
@@ -1681,7 +1681,7 @@ class VideoSender$Type extends MessageType<VideoSender> {
1681
1681
  no: 3,
1682
1682
  name: 'layers',
1683
1683
  kind: 'message',
1684
- repeat: 1 /*RepeatType.PACKED*/,
1684
+ repeat: 2 /*RepeatType.UNPACKED*/,
1685
1685
  T: () => VideoLayerSetting,
1686
1686
  },
1687
1687
  {
@@ -1715,14 +1715,14 @@ class ChangePublishQuality$Type extends MessageType<ChangePublishQuality> {
1715
1715
  no: 1,
1716
1716
  name: 'audio_senders',
1717
1717
  kind: 'message',
1718
- repeat: 1 /*RepeatType.PACKED*/,
1718
+ repeat: 2 /*RepeatType.UNPACKED*/,
1719
1719
  T: () => AudioSender,
1720
1720
  },
1721
1721
  {
1722
1722
  no: 2,
1723
1723
  name: 'video_senders',
1724
1724
  kind: 'message',
1725
- repeat: 1 /*RepeatType.PACKED*/,
1725
+ repeat: 2 /*RepeatType.UNPACKED*/,
1726
1726
  T: () => VideoSender,
1727
1727
  },
1728
1728
  ]);
@@ -1,4 +1,4 @@
1
- // @generated by protobuf-ts 2.9.6 with parameter long_type_string,client_generic,server_none,eslint_disable,optimize_code_size
1
+ // @generated by protobuf-ts 2.10.0 with parameter long_type_string,client_generic,server_none,eslint_disable,optimize_code_size
2
2
  // @generated from protobuf file "video/sfu/models/models.proto" (package "stream.video.sfu.models", syntax proto3)
3
3
  // tslint:disable
4
4
  import { MessageType } from '@protobuf-ts/runtime';
@@ -811,6 +811,10 @@ export enum ErrorCode {
811
811
  * @generated from protobuf enum value: ERROR_CODE_PARTICIPANT_MEDIA_TRANSPORT_FAILURE = 205;
812
812
  */
813
813
  PARTICIPANT_MEDIA_TRANSPORT_FAILURE = 205,
814
+ /**
815
+ * @generated from protobuf enum value: ERROR_CODE_PARTICIPANT_SIGNAL_LOST = 206;
816
+ */
817
+ PARTICIPANT_SIGNAL_LOST = 206,
814
818
  /**
815
819
  * @generated from protobuf enum value: ERROR_CODE_CALL_NOT_FOUND = 300;
816
820
  */
@@ -1084,7 +1088,7 @@ class CallState$Type extends MessageType<CallState> {
1084
1088
  no: 1,
1085
1089
  name: 'participants',
1086
1090
  kind: 'message',
1087
- repeat: 1 /*RepeatType.PACKED*/,
1091
+ repeat: 2 /*RepeatType.UNPACKED*/,
1088
1092
  T: () => Participant,
1089
1093
  },
1090
1094
  { no: 2, name: 'started_at', kind: 'message', T: () => Timestamp },
@@ -1098,7 +1102,7 @@ class CallState$Type extends MessageType<CallState> {
1098
1102
  no: 4,
1099
1103
  name: 'pins',
1100
1104
  kind: 'message',
1101
- repeat: 1 /*RepeatType.PACKED*/,
1105
+ repeat: 2 /*RepeatType.UNPACKED*/,
1102
1106
  T: () => Pin,
1103
1107
  },
1104
1108
  ]);
@@ -1276,7 +1280,7 @@ class SubscribeOption$Type extends MessageType<SubscribeOption> {
1276
1280
  no: 2,
1277
1281
  name: 'codecs',
1278
1282
  kind: 'message',
1279
- repeat: 1 /*RepeatType.PACKED*/,
1283
+ repeat: 2 /*RepeatType.UNPACKED*/,
1280
1284
  T: () => Codec,
1281
1285
  },
1282
1286
  ]);
@@ -1409,7 +1413,7 @@ class TrackInfo$Type extends MessageType<TrackInfo> {
1409
1413
  no: 5,
1410
1414
  name: 'layers',
1411
1415
  kind: 'message',
1412
- repeat: 1 /*RepeatType.PACKED*/,
1416
+ repeat: 2 /*RepeatType.UNPACKED*/,
1413
1417
  T: () => VideoLayer,
1414
1418
  },
1415
1419
  { no: 6, name: 'mid', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
@@ -1,4 +1,4 @@
1
- // @generated by protobuf-ts 2.9.6 with parameter long_type_string,client_generic,server_none,eslint_disable,optimize_code_size
1
+ // @generated by protobuf-ts 2.10.0 with parameter long_type_string,client_generic,server_none,eslint_disable,optimize_code_size
2
2
  // @generated from protobuf file "video/sfu/signal_rpc/signal.proto" (package "stream.video.sfu.signal", syntax proto3)
3
3
  // tslint:disable
4
4
  import type {
@@ -1,4 +1,4 @@
1
- // @generated by protobuf-ts 2.9.6 with parameter long_type_string,client_generic,server_none,eslint_disable,optimize_code_size
1
+ // @generated by protobuf-ts 2.10.0 with parameter long_type_string,client_generic,server_none,eslint_disable,optimize_code_size
2
2
  // @generated from protobuf file "video/sfu/signal_rpc/signal.proto" (package "stream.video.sfu.signal", syntax proto3)
3
3
  // tslint:disable
4
4
  import {
@@ -566,14 +566,14 @@ class SendStatsRequest$Type extends MessageType<SendStatsRequest> {
566
566
  no: 16,
567
567
  name: 'encode_stats',
568
568
  kind: 'message',
569
- repeat: 1 /*RepeatType.PACKED*/,
569
+ repeat: 2 /*RepeatType.UNPACKED*/,
570
570
  T: () => PerformanceStats,
571
571
  },
572
572
  {
573
573
  no: 17,
574
574
  name: 'decode_stats',
575
575
  kind: 'message',
576
- repeat: 1 /*RepeatType.PACKED*/,
576
+ repeat: 2 /*RepeatType.UNPACKED*/,
577
577
  T: () => PerformanceStats,
578
578
  },
579
579
  {
@@ -640,7 +640,7 @@ class UpdateMuteStatesRequest$Type extends MessageType<UpdateMuteStatesRequest>
640
640
  no: 3,
641
641
  name: 'mute_states',
642
642
  kind: 'message',
643
- repeat: 1 /*RepeatType.PACKED*/,
643
+ repeat: 2 /*RepeatType.UNPACKED*/,
644
644
  T: () => TrackMuteState,
645
645
  },
646
646
  ]);
@@ -717,7 +717,7 @@ class UpdateSubscriptionsRequest$Type extends MessageType<UpdateSubscriptionsReq
717
717
  no: 3,
718
718
  name: 'tracks',
719
719
  kind: 'message',
720
- repeat: 1 /*RepeatType.PACKED*/,
720
+ repeat: 2 /*RepeatType.UNPACKED*/,
721
721
  T: () => TrackSubscriptionDetails,
722
722
  },
723
723
  ]);
@@ -817,7 +817,7 @@ class SetPublisherRequest$Type extends MessageType<SetPublisherRequest> {
817
817
  no: 3,
818
818
  name: 'tracks',
819
819
  kind: 'message',
820
- repeat: 1 /*RepeatType.PACKED*/,
820
+ repeat: 2 /*RepeatType.UNPACKED*/,
821
821
  T: () => TrackInfo,
822
822
  },
823
823
  ]);