@stream-io/video-client 1.50.0 → 1.52.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 (61) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/index.browser.es.js +597 -70
  3. package/dist/index.browser.es.js.map +1 -1
  4. package/dist/index.cjs.js +597 -69
  5. package/dist/index.cjs.js.map +1 -1
  6. package/dist/index.es.js +597 -70
  7. package/dist/index.es.js.map +1 -1
  8. package/dist/src/Call.d.ts +1 -0
  9. package/dist/src/devices/CameraManager.d.ts +1 -0
  10. package/dist/src/devices/DeviceManager.d.ts +20 -0
  11. package/dist/src/devices/VirtualDevice.d.ts +59 -0
  12. package/dist/src/devices/devicePersistence.d.ts +1 -1
  13. package/dist/src/devices/index.d.ts +1 -0
  14. package/dist/src/gen/video/sfu/event/events.d.ts +4 -0
  15. package/dist/src/gen/video/sfu/models/models.d.ts +204 -2
  16. package/dist/src/gen/video/sfu/signal_rpc/signal.client.d.ts +9 -1
  17. package/dist/src/gen/video/sfu/signal_rpc/signal.d.ts +67 -1
  18. package/dist/src/helpers/participantUtils.d.ts +10 -0
  19. package/dist/src/rtc/BasePeerConnection.d.ts +8 -3
  20. package/dist/src/rtc/Publisher.d.ts +21 -3
  21. package/dist/src/rtc/TransceiverCache.d.ts +5 -1
  22. package/dist/src/rtc/helpers/degradationPreference.d.ts +1 -0
  23. package/dist/src/rtc/types.d.ts +3 -0
  24. package/dist/src/stats/rtc/StatsTracer.d.ts +2 -1
  25. package/dist/src/stats/utils.d.ts +1 -0
  26. package/package.json +14 -14
  27. package/src/Call.ts +27 -12
  28. package/src/devices/CameraManager.ts +9 -2
  29. package/src/devices/DeviceManager.ts +148 -8
  30. package/src/devices/DeviceManagerState.ts +4 -1
  31. package/src/devices/VirtualDevice.ts +69 -0
  32. package/src/devices/__tests__/CameraManager.test.ts +22 -1
  33. package/src/devices/__tests__/DeviceManager.test.ts +124 -2
  34. package/src/devices/__tests__/MicrophoneManager.test.ts +3 -1
  35. package/src/devices/__tests__/MicrophoneManagerRN.test.ts +3 -1
  36. package/src/devices/__tests__/ScreenShareManager.test.ts +3 -1
  37. package/src/devices/__tests__/web-audio.mocks.ts +3 -1
  38. package/src/devices/devicePersistence.ts +2 -1
  39. package/src/devices/index.ts +1 -0
  40. package/src/gen/video/sfu/event/events.ts +10 -0
  41. package/src/gen/video/sfu/models/models.ts +338 -0
  42. package/src/gen/video/sfu/signal_rpc/signal.client.ts +28 -2
  43. package/src/gen/video/sfu/signal_rpc/signal.ts +121 -15
  44. package/src/helpers/__tests__/DynascaleManager.test.ts +8 -7
  45. package/src/helpers/__tests__/browsers.test.ts +4 -4
  46. package/src/helpers/__tests__/participantUtils.test.ts +47 -0
  47. package/src/helpers/client-details.ts +4 -1
  48. package/src/helpers/participantUtils.ts +15 -0
  49. package/src/rtc/BasePeerConnection.ts +22 -4
  50. package/src/rtc/Publisher.ts +140 -41
  51. package/src/rtc/Subscriber.ts +1 -0
  52. package/src/rtc/TransceiverCache.ts +10 -3
  53. package/src/rtc/__tests__/Call.reconnect.test.ts +121 -2
  54. package/src/rtc/__tests__/Publisher.test.ts +659 -112
  55. package/src/rtc/__tests__/Subscriber.test.ts +7 -3
  56. package/src/rtc/__tests__/mocks/webrtc.mocks.ts +16 -15
  57. package/src/rtc/helpers/__tests__/degradationPreference.test.ts +33 -1
  58. package/src/rtc/helpers/degradationPreference.ts +18 -0
  59. package/src/rtc/types.ts +3 -0
  60. package/src/stats/rtc/StatsTracer.ts +25 -4
  61. package/src/stats/rtc/__tests__/StatsTracer.test.ts +155 -0
@@ -17,7 +17,7 @@ import {
17
17
  } from './mocks';
18
18
  import { DeviceManager } from '../DeviceManager';
19
19
  import { DeviceManagerState } from '../DeviceManagerState';
20
- import { of } from 'rxjs';
20
+ import { firstValueFrom, of } from 'rxjs';
21
21
  import { TrackType } from '../../gen/video/sfu/models/models';
22
22
  import { PermissionsContext } from '../../permissions';
23
23
  import { readPreferences } from '../devicePersistence';
@@ -25,7 +25,9 @@ import { readPreferences } from '../devicePersistence';
25
25
  vi.mock('../../Call.ts', () => {
26
26
  console.log('MOCKING Call');
27
27
  return {
28
- Call: vi.fn(() => mockCall()),
28
+ Call: vi.fn(function () {
29
+ return mockCall();
30
+ }),
29
31
  };
30
32
  });
31
33
 
@@ -221,6 +223,126 @@ describe('Device Manager', () => {
221
223
  expect(spy.mock.calls.length).toBe(1);
222
224
  });
223
225
 
226
+ it('should use a virtual device stream factory instead of requesting a real device stream', async () => {
227
+ const virtualStream = mockVideoStream();
228
+ const getUserMedia = vi.fn(() => ({ stream: virtualStream }));
229
+
230
+ const { deviceId } = manager.registerVirtualDevice({
231
+ label: 'Virtual camera',
232
+ getUserMedia,
233
+ });
234
+
235
+ await manager.select(deviceId);
236
+ await manager.enable();
237
+
238
+ expect(getUserMedia).toHaveBeenCalledOnce();
239
+ expect(getUserMedia).toHaveBeenCalledWith({
240
+ deviceId: { exact: deviceId },
241
+ });
242
+ expect(manager.getStream).not.toHaveBeenCalled();
243
+ expect(manager.state.mediaStream).toBe(virtualStream);
244
+ expect(manager.state.selectedDevice).toBe(deviceId);
245
+ });
246
+
247
+ it('should call virtual device stop when switching away from it', async () => {
248
+ const stop = vi.fn();
249
+ const virtualStream = mockVideoStream();
250
+
251
+ const { deviceId } = manager.registerVirtualDevice({
252
+ label: 'Virtual camera',
253
+ getUserMedia: vi.fn(() => ({ stream: virtualStream, stop })),
254
+ });
255
+
256
+ await manager.select(deviceId);
257
+ await manager.enable();
258
+ await manager.select(mockVideoDevices[1].deviceId);
259
+
260
+ expect(stop).toHaveBeenCalledTimes(1);
261
+ });
262
+
263
+ it('should support an async getUserMedia returning a Promise', async () => {
264
+ const virtualStream = mockVideoStream();
265
+ const getUserMedia = vi.fn(() =>
266
+ Promise.resolve({ stream: virtualStream }),
267
+ );
268
+
269
+ const { deviceId } = manager.registerVirtualDevice({
270
+ label: 'Async virtual camera',
271
+ getUserMedia,
272
+ });
273
+
274
+ await manager.select(deviceId);
275
+ await manager.enable();
276
+
277
+ expect(getUserMedia).toHaveBeenCalledOnce();
278
+ expect(manager.state.mediaStream).toBe(virtualStream);
279
+ expect(manager.state.selectedDevice).toBe(deviceId);
280
+ });
281
+
282
+ it('should roll back selection when getUserMedia rejects', async () => {
283
+ const failure = new Error('factory boom');
284
+ const getUserMedia = vi.fn(() => Promise.reject(failure));
285
+
286
+ await manager.enable();
287
+ const previousDevice = manager.state.selectedDevice;
288
+
289
+ const { deviceId } = manager.registerVirtualDevice({
290
+ label: 'Failing camera',
291
+ getUserMedia,
292
+ });
293
+
294
+ await expect(manager.select(deviceId)).rejects.toThrow(failure);
295
+
296
+ expect(manager.state.selectedDevice).toBe(previousDevice);
297
+ });
298
+
299
+ it('should stop the active session and clear selection on unregister', async () => {
300
+ const stop = vi.fn();
301
+ const virtualStream = mockVideoStream();
302
+
303
+ const { deviceId, unregister } = manager.registerVirtualDevice({
304
+ label: 'Virtual camera',
305
+ getUserMedia: vi.fn(() => ({ stream: virtualStream, stop })),
306
+ });
307
+
308
+ await manager.select(deviceId);
309
+ await manager.enable();
310
+
311
+ await unregister();
312
+
313
+ expect(stop).toHaveBeenCalledTimes(1);
314
+ expect(manager.state.selectedDevice).not.toBe(deviceId);
315
+ });
316
+
317
+ it('should remove the entry on unregister without stopping when not selected', async () => {
318
+ const stop = vi.fn();
319
+ const getUserMedia = vi.fn(() => ({ stream: mockVideoStream(), stop }));
320
+
321
+ const { unregister } = manager.registerVirtualDevice({
322
+ label: 'Unused virtual camera',
323
+ getUserMedia,
324
+ });
325
+
326
+ await unregister();
327
+
328
+ expect(stop).not.toHaveBeenCalled();
329
+ expect(getUserMedia).not.toHaveBeenCalled();
330
+ });
331
+
332
+ it('should expose virtual devices via listDevices() with the provided label', async () => {
333
+ manager.registerVirtualDevice({
334
+ label: 'My virtual camera',
335
+ getUserMedia: vi.fn(() => ({ stream: mockVideoStream() })),
336
+ });
337
+
338
+ const devices = await firstValueFrom(manager.listDevices());
339
+
340
+ expect(devices.length).toBe(mockVideoDevices.length + 1);
341
+ const virtual = devices.find((d) => d.label === 'My virtual camera');
342
+ expect(virtual).toBeDefined();
343
+ expect(virtual?.kind).toBe('videoinput');
344
+ });
345
+
224
346
  it('should resume previously enabled state', async () => {
225
347
  vi.spyOn(manager, 'enable');
226
348
 
@@ -76,7 +76,9 @@ vi.mock('../../helpers/no-audio-detector.ts', () => {
76
76
  vi.mock('../../Call.ts', () => {
77
77
  console.log('MOCKING Call');
78
78
  return {
79
- Call: vi.fn(() => mockCall()),
79
+ Call: vi.fn(function () {
80
+ return mockCall();
81
+ }),
80
82
  };
81
83
  });
82
84
 
@@ -43,7 +43,9 @@ vi.mock('../devices.ts', () => {
43
43
  vi.mock('../../Call.ts', () => {
44
44
  console.log('MOCKING Call');
45
45
  return {
46
- Call: vi.fn(() => mockCall()),
46
+ Call: vi.fn(function () {
47
+ return mockCall();
48
+ }),
47
49
  };
48
50
  });
49
51
 
@@ -26,7 +26,9 @@ vi.mock('../devices.ts', () => {
26
26
  vi.mock('../../Call.ts', () => {
27
27
  console.log('MOCKING Call');
28
28
  return {
29
- Call: vi.fn(() => mockCall()),
29
+ Call: vi.fn(function () {
30
+ return mockCall();
31
+ }),
30
32
  };
31
33
  });
32
34
 
@@ -63,7 +63,9 @@ export const setupAudioContextMock = () => {
63
63
  const mockContext = createMockAudioContext();
64
64
  vi.stubGlobal(
65
65
  'AudioContext',
66
- vi.fn(() => mockContext),
66
+ vi.fn(function () {
67
+ return mockContext;
68
+ }),
67
69
  );
68
70
  return mockContext;
69
71
  };
@@ -48,8 +48,9 @@ export const normalize = (
48
48
  export const createSyntheticDevice = (
49
49
  deviceId: string,
50
50
  kind: MediaDeviceKind,
51
+ label = '',
51
52
  ): MediaDeviceInfo => {
52
- return { deviceId, kind, label: '', groupId: '' } as MediaDeviceInfo;
53
+ return { deviceId, kind, label, groupId: '' } as MediaDeviceInfo;
53
54
  };
54
55
 
55
56
  export const readPreferences = (storageKey: string): LocalDevicePreferences => {
@@ -10,3 +10,4 @@ export * from './ScreenShareManager';
10
10
  export * from './ScreenShareState';
11
11
  export * from './SpeakerManager';
12
12
  export * from './SpeakerState';
13
+ export * from './VirtualDevice';
@@ -675,6 +675,10 @@ export interface SubscriberOffer {
675
675
  * @generated from protobuf field: string sdp = 2;
676
676
  */
677
677
  sdp: string;
678
+ /**
679
+ * @generated from protobuf field: uint32 negotiation_id = 3;
680
+ */
681
+ negotiationId: number;
678
682
  }
679
683
  /**
680
684
  * @generated from protobuf message stream.video.sfu.event.PublisherAnswer
@@ -1606,6 +1610,12 @@ class SubscriberOffer$Type extends MessageType<SubscriberOffer> {
1606
1610
  super('stream.video.sfu.event.SubscriberOffer', [
1607
1611
  { no: 1, name: 'ice_restart', kind: 'scalar', T: 8 /*ScalarType.BOOL*/ },
1608
1612
  { no: 2, name: 'sdp', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
1613
+ {
1614
+ no: 3,
1615
+ name: 'negotiation_id',
1616
+ kind: 'scalar',
1617
+ T: 13 /*ScalarType.UINT32*/,
1618
+ },
1609
1619
  ]);
1610
1620
  }
1611
1621
  }
@@ -453,6 +453,10 @@ export interface ClientDetails {
453
453
  * @generated from protobuf field: stream.video.sfu.models.Device device = 4;
454
454
  */
455
455
  device?: Device;
456
+ /**
457
+ * @generated from protobuf field: string webrtc_version = 5;
458
+ */
459
+ webrtcVersion: string;
456
460
  }
457
461
  /**
458
462
  * @generated from protobuf message stream.video.sfu.models.Sdk
@@ -706,6 +710,155 @@ export interface PerformanceStats {
706
710
  */
707
711
  targetBitrate: number;
708
712
  }
713
+ /**
714
+ * ===================================================================
715
+ * BASE (shared by all RTP directions)
716
+ * ===================================================================
717
+ *
718
+ * @generated from protobuf message stream.video.sfu.models.RtpBase
719
+ */
720
+ export interface RtpBase {
721
+ /**
722
+ * @generated from protobuf field: uint32 ssrc = 1;
723
+ */
724
+ ssrc: number; // raw stat["ssrc"]
725
+ /**
726
+ * @generated from protobuf field: string kind = 2;
727
+ */
728
+ kind: string; // stat["kind"] ("audio","video")
729
+ /**
730
+ * @generated from protobuf field: double timestamp_ms = 3;
731
+ */
732
+ timestampMs: number; // stat["timestamp"] in milliseconds
733
+ }
734
+ /**
735
+ * ===================================================================
736
+ * INBOUND (SUBSCRIBER RECEIVING MEDIA)
737
+ * ===================================================================
738
+ *
739
+ * @generated from protobuf message stream.video.sfu.models.InboundRtp
740
+ */
741
+ export interface InboundRtp {
742
+ /**
743
+ * @generated from protobuf field: stream.video.sfu.models.RtpBase base = 1;
744
+ */
745
+ base?: RtpBase;
746
+ /**
747
+ * @generated from protobuf field: double jitter_seconds = 2;
748
+ */
749
+ jitterSeconds: number; // stat["jitter"]
750
+ /**
751
+ * @generated from protobuf field: uint64 packets_received = 3;
752
+ */
753
+ packetsReceived: string; // stat["packetsReceived"]
754
+ /**
755
+ * @generated from protobuf field: uint64 packets_lost = 4;
756
+ */
757
+ packetsLost: string; // stat["packetsLost"]
758
+ /**
759
+ * @generated from protobuf field: double packet_loss_percent = 5;
760
+ */
761
+ packetLossPercent: number; // (packets_lost / (packets_received + packets_lost)) * 100;skip if denominator <= 0 or counters decreased
762
+ /**
763
+ * -------- AUDIO METRICS --------
764
+ *
765
+ * @generated from protobuf field: uint32 concealment_events = 10;
766
+ */
767
+ concealmentEvents: number; // stat["concealmentEvents"]
768
+ /**
769
+ * @generated from protobuf field: double concealment_percent = 11;
770
+ */
771
+ concealmentPercent: number; // (concealedSamples / totalSamplesReceived) * 100 when totalSamplesReceived >= 96_000 (≈2 s @ 48 kHz)
772
+ /**
773
+ * -------- VIDEO METRICS --------
774
+ *
775
+ * @generated from protobuf field: double fps = 20;
776
+ */
777
+ fps: number; // use delta(framesDecoded)/delta(time) with prev sample
778
+ /**
779
+ * @generated from protobuf field: double freeze_duration_seconds = 21;
780
+ */
781
+ freezeDurationSeconds: number; // stat["totalFreezesDuration"]
782
+ /**
783
+ * @generated from protobuf field: double avg_decode_time_seconds = 22;
784
+ */
785
+ avgDecodeTimeSeconds: number; // stat["totalDecodeTime"] / max(1, stat["framesDecoded"])
786
+ /**
787
+ * @generated from protobuf field: uint32 min_dimension_px = 23;
788
+ */
789
+ minDimensionPx: number; // min(stat["frameWidth"], stat["frameHeight"]) for video-like tracks
790
+ }
791
+ /**
792
+ * ===================================================================
793
+ * OUTBOUND (PUBLISHER SENDING MEDIA)
794
+ * ===================================================================
795
+ *
796
+ * @generated from protobuf message stream.video.sfu.models.OutboundRtp
797
+ */
798
+ export interface OutboundRtp {
799
+ /**
800
+ * @generated from protobuf field: stream.video.sfu.models.RtpBase base = 1;
801
+ */
802
+ base?: RtpBase;
803
+ /**
804
+ * @generated from protobuf field: double fps = 10;
805
+ */
806
+ fps: number; // delta(framesEncoded)/delta(time) if missing
807
+ /**
808
+ * @generated from protobuf field: double avg_encode_time_seconds = 11;
809
+ */
810
+ avgEncodeTimeSeconds: number; // stat["totalEncodeTime"] / max(1, stat["framesEncoded"])
811
+ /**
812
+ * @generated from protobuf field: double bitrate_bps = 12;
813
+ */
814
+ bitrateBps: number; // delta(bytesSent)*8 / delta(timeSeconds); requires prev bytes/timestamp; ignore if delta<=0
815
+ /**
816
+ * @generated from protobuf field: uint32 min_dimension_px = 13;
817
+ */
818
+ minDimensionPx: number; // min(stat["frameWidth"], stat["frameHeight"])
819
+ }
820
+ /**
821
+ * ===================================================================
822
+ * SFU FEEDBACK: REMOTE-INBOUND (Publisher receives feedback)
823
+ * ===================================================================
824
+ *
825
+ * @generated from protobuf message stream.video.sfu.models.RemoteInboundRtp
826
+ */
827
+ export interface RemoteInboundRtp {
828
+ /**
829
+ * @generated from protobuf field: stream.video.sfu.models.RtpBase base = 1;
830
+ */
831
+ base?: RtpBase;
832
+ /**
833
+ * @generated from protobuf field: double jitter_seconds = 2;
834
+ */
835
+ jitterSeconds: number; // stat["jitter"]
836
+ /**
837
+ * @generated from protobuf field: double round_trip_time_s = 3;
838
+ */
839
+ roundTripTimeS: number; // stat["roundTripTime"]
840
+ }
841
+ /**
842
+ * ===================================================================
843
+ * SFU FEEDBACK: REMOTE-OUTBOUND (Subscriber receives feedback)
844
+ * ===================================================================
845
+ *
846
+ * @generated from protobuf message stream.video.sfu.models.RemoteOutboundRtp
847
+ */
848
+ export interface RemoteOutboundRtp {
849
+ /**
850
+ * @generated from protobuf field: stream.video.sfu.models.RtpBase base = 1;
851
+ */
852
+ base?: RtpBase;
853
+ /**
854
+ * @generated from protobuf field: double jitter_seconds = 2;
855
+ */
856
+ jitterSeconds: number; // stat["jitter"] if provided
857
+ /**
858
+ * @generated from protobuf field: double round_trip_time_s = 3;
859
+ */
860
+ roundTripTimeS: number; // stat["roundTripTime"]
861
+ }
709
862
  /**
710
863
  * @generated from protobuf enum stream.video.sfu.models.PeerType
711
864
  */
@@ -973,6 +1126,14 @@ export enum SdkType {
973
1126
  * @generated from protobuf enum value: SDK_TYPE_PLAIN_JAVASCRIPT = 9;
974
1127
  */
975
1128
  PLAIN_JAVASCRIPT = 9,
1129
+ /**
1130
+ * @generated from protobuf enum value: SDK_TYPE_PYTHON = 10;
1131
+ */
1132
+ PYTHON = 10,
1133
+ /**
1134
+ * @generated from protobuf enum value: SDK_TYPE_VISION_AGENTS = 11;
1135
+ */
1136
+ VISION_AGENTS = 11,
976
1137
  }
977
1138
  /**
978
1139
  * @generated from protobuf enum stream.video.sfu.models.TrackUnpublishReason
@@ -1177,6 +1338,12 @@ export enum ClientCapability {
1177
1338
  * @generated from protobuf enum value: CLIENT_CAPABILITY_SUBSCRIBER_VIDEO_PAUSE = 1;
1178
1339
  */
1179
1340
  SUBSCRIBER_VIDEO_PAUSE = 1,
1341
+ /**
1342
+ * Instructs SFU that stats will be sent to the coordinator
1343
+ *
1344
+ * @generated from protobuf enum value: CLIENT_CAPABILITY_COORDINATOR_STATS = 2;
1345
+ */
1346
+ COORDINATOR_STATS = 2,
1180
1347
  }
1181
1348
  /**
1182
1349
  * DegradationPreference represents the RTCDegradationPreference from WebRTC.
@@ -1641,6 +1808,12 @@ class ClientDetails$Type extends MessageType<ClientDetails> {
1641
1808
  { no: 2, name: 'os', kind: 'message', T: () => OS },
1642
1809
  { no: 3, name: 'browser', kind: 'message', T: () => Browser },
1643
1810
  { no: 4, name: 'device', kind: 'message', T: () => Device },
1811
+ {
1812
+ no: 5,
1813
+ name: 'webrtc_version',
1814
+ kind: 'scalar',
1815
+ T: 9 /*ScalarType.STRING*/,
1816
+ },
1644
1817
  ]);
1645
1818
  }
1646
1819
  }
@@ -1913,3 +2086,168 @@ class PerformanceStats$Type extends MessageType<PerformanceStats> {
1913
2086
  * @generated MessageType for protobuf message stream.video.sfu.models.PerformanceStats
1914
2087
  */
1915
2088
  export const PerformanceStats = new PerformanceStats$Type();
2089
+ // @generated message type with reflection information, may provide speed optimized methods
2090
+ class RtpBase$Type extends MessageType<RtpBase> {
2091
+ constructor() {
2092
+ super('stream.video.sfu.models.RtpBase', [
2093
+ { no: 1, name: 'ssrc', kind: 'scalar', T: 13 /*ScalarType.UINT32*/ },
2094
+ { no: 2, name: 'kind', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
2095
+ {
2096
+ no: 3,
2097
+ name: 'timestamp_ms',
2098
+ kind: 'scalar',
2099
+ T: 1 /*ScalarType.DOUBLE*/,
2100
+ },
2101
+ ]);
2102
+ }
2103
+ }
2104
+ /**
2105
+ * @generated MessageType for protobuf message stream.video.sfu.models.RtpBase
2106
+ */
2107
+ export const RtpBase = new RtpBase$Type();
2108
+ // @generated message type with reflection information, may provide speed optimized methods
2109
+ class InboundRtp$Type extends MessageType<InboundRtp> {
2110
+ constructor() {
2111
+ super('stream.video.sfu.models.InboundRtp', [
2112
+ { no: 1, name: 'base', kind: 'message', T: () => RtpBase },
2113
+ {
2114
+ no: 2,
2115
+ name: 'jitter_seconds',
2116
+ kind: 'scalar',
2117
+ T: 1 /*ScalarType.DOUBLE*/,
2118
+ },
2119
+ {
2120
+ no: 3,
2121
+ name: 'packets_received',
2122
+ kind: 'scalar',
2123
+ T: 4 /*ScalarType.UINT64*/,
2124
+ },
2125
+ {
2126
+ no: 4,
2127
+ name: 'packets_lost',
2128
+ kind: 'scalar',
2129
+ T: 4 /*ScalarType.UINT64*/,
2130
+ },
2131
+ {
2132
+ no: 5,
2133
+ name: 'packet_loss_percent',
2134
+ kind: 'scalar',
2135
+ T: 1 /*ScalarType.DOUBLE*/,
2136
+ },
2137
+ {
2138
+ no: 10,
2139
+ name: 'concealment_events',
2140
+ kind: 'scalar',
2141
+ T: 13 /*ScalarType.UINT32*/,
2142
+ },
2143
+ {
2144
+ no: 11,
2145
+ name: 'concealment_percent',
2146
+ kind: 'scalar',
2147
+ T: 1 /*ScalarType.DOUBLE*/,
2148
+ },
2149
+ { no: 20, name: 'fps', kind: 'scalar', T: 1 /*ScalarType.DOUBLE*/ },
2150
+ {
2151
+ no: 21,
2152
+ name: 'freeze_duration_seconds',
2153
+ kind: 'scalar',
2154
+ T: 1 /*ScalarType.DOUBLE*/,
2155
+ },
2156
+ {
2157
+ no: 22,
2158
+ name: 'avg_decode_time_seconds',
2159
+ kind: 'scalar',
2160
+ T: 1 /*ScalarType.DOUBLE*/,
2161
+ },
2162
+ {
2163
+ no: 23,
2164
+ name: 'min_dimension_px',
2165
+ kind: 'scalar',
2166
+ T: 13 /*ScalarType.UINT32*/,
2167
+ },
2168
+ ]);
2169
+ }
2170
+ }
2171
+ /**
2172
+ * @generated MessageType for protobuf message stream.video.sfu.models.InboundRtp
2173
+ */
2174
+ export const InboundRtp = new InboundRtp$Type();
2175
+ // @generated message type with reflection information, may provide speed optimized methods
2176
+ class OutboundRtp$Type extends MessageType<OutboundRtp> {
2177
+ constructor() {
2178
+ super('stream.video.sfu.models.OutboundRtp', [
2179
+ { no: 1, name: 'base', kind: 'message', T: () => RtpBase },
2180
+ { no: 10, name: 'fps', kind: 'scalar', T: 1 /*ScalarType.DOUBLE*/ },
2181
+ {
2182
+ no: 11,
2183
+ name: 'avg_encode_time_seconds',
2184
+ kind: 'scalar',
2185
+ T: 1 /*ScalarType.DOUBLE*/,
2186
+ },
2187
+ {
2188
+ no: 12,
2189
+ name: 'bitrate_bps',
2190
+ kind: 'scalar',
2191
+ T: 1 /*ScalarType.DOUBLE*/,
2192
+ },
2193
+ {
2194
+ no: 13,
2195
+ name: 'min_dimension_px',
2196
+ kind: 'scalar',
2197
+ T: 13 /*ScalarType.UINT32*/,
2198
+ },
2199
+ ]);
2200
+ }
2201
+ }
2202
+ /**
2203
+ * @generated MessageType for protobuf message stream.video.sfu.models.OutboundRtp
2204
+ */
2205
+ export const OutboundRtp = new OutboundRtp$Type();
2206
+ // @generated message type with reflection information, may provide speed optimized methods
2207
+ class RemoteInboundRtp$Type extends MessageType<RemoteInboundRtp> {
2208
+ constructor() {
2209
+ super('stream.video.sfu.models.RemoteInboundRtp', [
2210
+ { no: 1, name: 'base', kind: 'message', T: () => RtpBase },
2211
+ {
2212
+ no: 2,
2213
+ name: 'jitter_seconds',
2214
+ kind: 'scalar',
2215
+ T: 1 /*ScalarType.DOUBLE*/,
2216
+ },
2217
+ {
2218
+ no: 3,
2219
+ name: 'round_trip_time_s',
2220
+ kind: 'scalar',
2221
+ T: 1 /*ScalarType.DOUBLE*/,
2222
+ },
2223
+ ]);
2224
+ }
2225
+ }
2226
+ /**
2227
+ * @generated MessageType for protobuf message stream.video.sfu.models.RemoteInboundRtp
2228
+ */
2229
+ export const RemoteInboundRtp = new RemoteInboundRtp$Type();
2230
+ // @generated message type with reflection information, may provide speed optimized methods
2231
+ class RemoteOutboundRtp$Type extends MessageType<RemoteOutboundRtp> {
2232
+ constructor() {
2233
+ super('stream.video.sfu.models.RemoteOutboundRtp', [
2234
+ { no: 1, name: 'base', kind: 'message', T: () => RtpBase },
2235
+ {
2236
+ no: 2,
2237
+ name: 'jitter_seconds',
2238
+ kind: 'scalar',
2239
+ T: 1 /*ScalarType.DOUBLE*/,
2240
+ },
2241
+ {
2242
+ no: 3,
2243
+ name: 'round_trip_time_s',
2244
+ kind: 'scalar',
2245
+ T: 1 /*ScalarType.DOUBLE*/,
2246
+ },
2247
+ ]);
2248
+ }
2249
+ }
2250
+ /**
2251
+ * @generated MessageType for protobuf message stream.video.sfu.models.RemoteOutboundRtp
2252
+ */
2253
+ export const RemoteOutboundRtp = new RemoteOutboundRtp$Type();
@@ -14,6 +14,8 @@ import type {
14
14
  ICETrickleResponse,
15
15
  SendAnswerRequest,
16
16
  SendAnswerResponse,
17
+ SendMetricsRequest,
18
+ SendMetricsResponse,
17
19
  SendStatsRequest,
18
20
  SendStatsResponse,
19
21
  SetPublisherRequest,
@@ -92,6 +94,13 @@ export interface ISignalServerClient {
92
94
  input: SendStatsRequest,
93
95
  options?: RpcOptions,
94
96
  ): UnaryCall<SendStatsRequest, SendStatsResponse>;
97
+ /**
98
+ * @generated from protobuf rpc: SendMetrics(stream.video.sfu.signal.SendMetricsRequest) returns (stream.video.sfu.signal.SendMetricsResponse);
99
+ */
100
+ sendMetrics(
101
+ input: SendMetricsRequest,
102
+ options?: RpcOptions,
103
+ ): UnaryCall<SendMetricsRequest, SendMetricsResponse>;
95
104
  /**
96
105
  * @generated from protobuf rpc: StartNoiseCancellation(stream.video.sfu.signal.StartNoiseCancellationRequest) returns (stream.video.sfu.signal.StartNoiseCancellationResponse);
97
106
  */
@@ -240,6 +249,23 @@ export class SignalServerClient implements ISignalServerClient, ServiceInfo {
240
249
  input,
241
250
  );
242
251
  }
252
+ /**
253
+ * @generated from protobuf rpc: SendMetrics(stream.video.sfu.signal.SendMetricsRequest) returns (stream.video.sfu.signal.SendMetricsResponse);
254
+ */
255
+ sendMetrics(
256
+ input: SendMetricsRequest,
257
+ options?: RpcOptions,
258
+ ): UnaryCall<SendMetricsRequest, SendMetricsResponse> {
259
+ const method = this.methods[7],
260
+ opt = this._transport.mergeOptions(options);
261
+ return stackIntercept<SendMetricsRequest, SendMetricsResponse>(
262
+ 'unary',
263
+ this._transport,
264
+ method,
265
+ opt,
266
+ input,
267
+ );
268
+ }
243
269
  /**
244
270
  * @generated from protobuf rpc: StartNoiseCancellation(stream.video.sfu.signal.StartNoiseCancellationRequest) returns (stream.video.sfu.signal.StartNoiseCancellationResponse);
245
271
  */
@@ -247,7 +273,7 @@ export class SignalServerClient implements ISignalServerClient, ServiceInfo {
247
273
  input: StartNoiseCancellationRequest,
248
274
  options?: RpcOptions,
249
275
  ): UnaryCall<StartNoiseCancellationRequest, StartNoiseCancellationResponse> {
250
- const method = this.methods[7],
276
+ const method = this.methods[8],
251
277
  opt = this._transport.mergeOptions(options);
252
278
  return stackIntercept<
253
279
  StartNoiseCancellationRequest,
@@ -261,7 +287,7 @@ export class SignalServerClient implements ISignalServerClient, ServiceInfo {
261
287
  input: StopNoiseCancellationRequest,
262
288
  options?: RpcOptions,
263
289
  ): UnaryCall<StopNoiseCancellationRequest, StopNoiseCancellationResponse> {
264
- const method = this.methods[8],
290
+ const method = this.methods[9],
265
291
  opt = this._transport.mergeOptions(options);
266
292
  return stackIntercept<
267
293
  StopNoiseCancellationRequest,