@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
@@ -103,6 +103,7 @@ export declare class Call {
103
103
  private statsReportingIntervalInMs;
104
104
  private statsReporter?;
105
105
  private sfuStatsReporter?;
106
+ private lastStatsOptions?;
106
107
  private dropTimeout;
107
108
  private readonly clientStore;
108
109
  readonly streamClient: StreamClient;
@@ -45,5 +45,6 @@ export declare class CameraManager extends DeviceManager<CameraManagerState> {
45
45
  */
46
46
  apply(settings: VideoSettingsResponse, publish: boolean): Promise<void>;
47
47
  protected getDevices(): Observable<MediaDeviceInfo[]>;
48
+ protected getResolvedConstraints(constraints: MediaTrackConstraints): MediaTrackConstraints;
48
49
  protected getStream(constraints: MediaTrackConstraints): Promise<MediaStream>;
49
50
  }
@@ -6,6 +6,7 @@ import { ScopedLogger } from '../logger';
6
6
  import { TrackType } from '../gen/video/sfu/models/models';
7
7
  import { MediaStreamFilter, MediaStreamFilterRegistrationResult } from './filters';
8
8
  import { DevicePersistenceOptions } from './devicePersistence';
9
+ import { VirtualDevice, VirtualDeviceEntry, VirtualDeviceHandle } from './VirtualDevice';
9
10
  export declare abstract class DeviceManager<S extends DeviceManagerState<C>, C = MediaTrackConstraints> {
10
11
  /**
11
12
  * if true, stops the media stream when call is left
@@ -21,6 +22,9 @@ export declare abstract class DeviceManager<S extends DeviceManagerState<C>, C =
21
22
  protected areSubscriptionsSetUp: boolean;
22
23
  private isTrackStoppedDueToTrackEnd;
23
24
  private filters;
25
+ private virtualDevicesSubject;
26
+ private activeVirtualSession;
27
+ private virtualDeviceConcurrencyTag;
24
28
  private statusChangeConcurrencyTag;
25
29
  private filterRegistrationConcurrencyTag;
26
30
  protected constructor(call: Call, state: S, trackType: TrackType, devicePersistence: Required<DevicePersistenceOptions>);
@@ -33,6 +37,21 @@ export declare abstract class DeviceManager<S extends DeviceManagerState<C>, C =
33
37
  * @returns an Observable that will be updated if a device is connected or disconnected
34
38
  */
35
39
  listDevices(): Observable<MediaDeviceInfo[]>;
40
+ /**
41
+ * Registers a virtual camera or microphone backed by a caller-supplied
42
+ * stream factory. The device appears in `listDevices()` and can be selected
43
+ * via `select()` like any real device.
44
+ *
45
+ * Web only. React Native is not supported.
46
+ *
47
+ * Only supported for camera and microphone managers; calling on any other
48
+ * manager throws.
49
+ */
50
+ registerVirtualDevice(virtualDevice: VirtualDevice<C>): VirtualDeviceHandle;
51
+ protected sanitizeVirtualStream(stream: MediaStream): MediaStream;
52
+ protected findVirtualDevice(deviceId: string | undefined): VirtualDeviceEntry<C> | undefined;
53
+ private stopActiveVirtualSession;
54
+ protected getSelectedStream(constraints: C): Promise<MediaStream>;
36
55
  /**
37
56
  * Returns `true` when this device is in enabled state.
38
57
  */
@@ -93,6 +112,7 @@ export declare abstract class DeviceManager<S extends DeviceManagerState<C>, C =
93
112
  private runCurrentStreamCleanups;
94
113
  protected applySettingsToStream(): Promise<void>;
95
114
  protected abstract getDevices(): Observable<MediaDeviceInfo[]>;
115
+ protected getResolvedConstraints(constraints: C): C;
96
116
  protected abstract getStream(constraints: C): Promise<MediaStream>;
97
117
  protected publishStream(stream: MediaStream, options?: TrackPublishOptions): Promise<void>;
98
118
  protected stopPublishStream(): Promise<void>;
@@ -0,0 +1,59 @@
1
+ /**
2
+ * A MediaStream produced for a virtual device session, along with an optional
3
+ * cleanup callback. Returned by {@link VirtualDevice.getUserMedia}.
4
+ */
5
+ export interface VirtualDeviceSession {
6
+ readonly stream: MediaStream;
7
+ readonly stop?: () => void | Promise<void>;
8
+ }
9
+ /**
10
+ * A virtual camera or microphone definition supplied by the integrator.
11
+ *
12
+ * Pass this to `camera.registerVirtualDevice()` /
13
+ * `microphone.registerVirtualDevice()` to make it appear in the device list
14
+ * and become selectable.
15
+ */
16
+ export interface VirtualDevice<C = MediaTrackConstraints> {
17
+ /**
18
+ * Human-readable label shown in device dropdowns.
19
+ */
20
+ label: string;
21
+ /**
22
+ * Called when the virtual device is selected and the SDK needs media.
23
+ * Returns the MediaStream to publish along with an optional `stop`
24
+ * callback that runs when the session is replaced, the tracks end, or
25
+ * the device is unregistered.
26
+ *
27
+ * `constraints` is the resolved set the SDK would otherwise pass to
28
+ * `getUserMedia` for a real device.
29
+ */
30
+ getUserMedia: (constraints: C) => VirtualDeviceSession | Promise<VirtualDeviceSession>;
31
+ }
32
+ /**
33
+ * @internal Internal entry stored in the device manager's registry.
34
+ */
35
+ export interface VirtualDeviceEntry<C = MediaTrackConstraints> extends VirtualDevice<C> {
36
+ readonly deviceId: string;
37
+ readonly kind: 'audioinput' | 'videoinput';
38
+ }
39
+ /**
40
+ * @internal Tracks the currently active virtual device session inside the
41
+ * device manager so its `stop` callback can be invoked when the session is
42
+ * replaced or torn down.
43
+ */
44
+ export interface ActiveVirtualSession {
45
+ deviceId: string;
46
+ stop?: () => void | Promise<void>;
47
+ }
48
+ export interface VirtualDeviceHandle {
49
+ /**
50
+ * The device id under which the virtual device was registered. Pass this
51
+ * to `camera.select()` / `microphone.select()` to switch to it.
52
+ */
53
+ readonly deviceId: string;
54
+ /**
55
+ * Removes the virtual device from the manager. If it is currently selected,
56
+ * the selection is reset so the SDK falls back to the default device.
57
+ */
58
+ unregister: () => Promise<void>;
59
+ }
@@ -21,7 +21,7 @@ export type LocalDevicePreferences = {
21
21
  };
22
22
  export declare const defaultDeviceId = "default";
23
23
  export declare const normalize: (options: DevicePersistenceOptions | undefined) => Required<DevicePersistenceOptions>;
24
- export declare const createSyntheticDevice: (deviceId: string, kind: MediaDeviceKind) => MediaDeviceInfo;
24
+ export declare const createSyntheticDevice: (deviceId: string, kind: MediaDeviceKind, label?: string) => MediaDeviceInfo;
25
25
  export declare const readPreferences: (storageKey: string) => LocalDevicePreferences;
26
26
  export declare const writePreferences: (currentDevice: MediaDeviceInfo | undefined, deviceKey: DevicePreferenceKey, muted: boolean | undefined, storageKey: string) => void;
27
27
  export declare const toPreferenceList: (preference?: LocalDevicePreference | LocalDevicePreference[]) => LocalDevicePreference[];
@@ -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';
@@ -623,6 +623,10 @@ export interface SubscriberOffer {
623
623
  * @generated from protobuf field: string sdp = 2;
624
624
  */
625
625
  sdp: string;
626
+ /**
627
+ * @generated from protobuf field: uint32 negotiation_id = 3;
628
+ */
629
+ negotiationId: number;
626
630
  }
627
631
  /**
628
632
  * @generated from protobuf message stream.video.sfu.event.PublisherAnswer
@@ -449,6 +449,10 @@ export interface ClientDetails {
449
449
  * @generated from protobuf field: stream.video.sfu.models.Device device = 4;
450
450
  */
451
451
  device?: Device;
452
+ /**
453
+ * @generated from protobuf field: string webrtc_version = 5;
454
+ */
455
+ webrtcVersion: string;
452
456
  }
453
457
  /**
454
458
  * @generated from protobuf message stream.video.sfu.models.Sdk
@@ -702,6 +706,155 @@ export interface PerformanceStats {
702
706
  */
703
707
  targetBitrate: number;
704
708
  }
709
+ /**
710
+ * ===================================================================
711
+ * BASE (shared by all RTP directions)
712
+ * ===================================================================
713
+ *
714
+ * @generated from protobuf message stream.video.sfu.models.RtpBase
715
+ */
716
+ export interface RtpBase {
717
+ /**
718
+ * @generated from protobuf field: uint32 ssrc = 1;
719
+ */
720
+ ssrc: number;
721
+ /**
722
+ * @generated from protobuf field: string kind = 2;
723
+ */
724
+ kind: string;
725
+ /**
726
+ * @generated from protobuf field: double timestamp_ms = 3;
727
+ */
728
+ timestampMs: number;
729
+ }
730
+ /**
731
+ * ===================================================================
732
+ * INBOUND (SUBSCRIBER RECEIVING MEDIA)
733
+ * ===================================================================
734
+ *
735
+ * @generated from protobuf message stream.video.sfu.models.InboundRtp
736
+ */
737
+ export interface InboundRtp {
738
+ /**
739
+ * @generated from protobuf field: stream.video.sfu.models.RtpBase base = 1;
740
+ */
741
+ base?: RtpBase;
742
+ /**
743
+ * @generated from protobuf field: double jitter_seconds = 2;
744
+ */
745
+ jitterSeconds: number;
746
+ /**
747
+ * @generated from protobuf field: uint64 packets_received = 3;
748
+ */
749
+ packetsReceived: string;
750
+ /**
751
+ * @generated from protobuf field: uint64 packets_lost = 4;
752
+ */
753
+ packetsLost: string;
754
+ /**
755
+ * @generated from protobuf field: double packet_loss_percent = 5;
756
+ */
757
+ packetLossPercent: number;
758
+ /**
759
+ * -------- AUDIO METRICS --------
760
+ *
761
+ * @generated from protobuf field: uint32 concealment_events = 10;
762
+ */
763
+ concealmentEvents: number;
764
+ /**
765
+ * @generated from protobuf field: double concealment_percent = 11;
766
+ */
767
+ concealmentPercent: number;
768
+ /**
769
+ * -------- VIDEO METRICS --------
770
+ *
771
+ * @generated from protobuf field: double fps = 20;
772
+ */
773
+ fps: number;
774
+ /**
775
+ * @generated from protobuf field: double freeze_duration_seconds = 21;
776
+ */
777
+ freezeDurationSeconds: number;
778
+ /**
779
+ * @generated from protobuf field: double avg_decode_time_seconds = 22;
780
+ */
781
+ avgDecodeTimeSeconds: number;
782
+ /**
783
+ * @generated from protobuf field: uint32 min_dimension_px = 23;
784
+ */
785
+ minDimensionPx: number;
786
+ }
787
+ /**
788
+ * ===================================================================
789
+ * OUTBOUND (PUBLISHER SENDING MEDIA)
790
+ * ===================================================================
791
+ *
792
+ * @generated from protobuf message stream.video.sfu.models.OutboundRtp
793
+ */
794
+ export interface OutboundRtp {
795
+ /**
796
+ * @generated from protobuf field: stream.video.sfu.models.RtpBase base = 1;
797
+ */
798
+ base?: RtpBase;
799
+ /**
800
+ * @generated from protobuf field: double fps = 10;
801
+ */
802
+ fps: number;
803
+ /**
804
+ * @generated from protobuf field: double avg_encode_time_seconds = 11;
805
+ */
806
+ avgEncodeTimeSeconds: number;
807
+ /**
808
+ * @generated from protobuf field: double bitrate_bps = 12;
809
+ */
810
+ bitrateBps: number;
811
+ /**
812
+ * @generated from protobuf field: uint32 min_dimension_px = 13;
813
+ */
814
+ minDimensionPx: number;
815
+ }
816
+ /**
817
+ * ===================================================================
818
+ * SFU FEEDBACK: REMOTE-INBOUND (Publisher receives feedback)
819
+ * ===================================================================
820
+ *
821
+ * @generated from protobuf message stream.video.sfu.models.RemoteInboundRtp
822
+ */
823
+ export interface RemoteInboundRtp {
824
+ /**
825
+ * @generated from protobuf field: stream.video.sfu.models.RtpBase base = 1;
826
+ */
827
+ base?: RtpBase;
828
+ /**
829
+ * @generated from protobuf field: double jitter_seconds = 2;
830
+ */
831
+ jitterSeconds: number;
832
+ /**
833
+ * @generated from protobuf field: double round_trip_time_s = 3;
834
+ */
835
+ roundTripTimeS: number;
836
+ }
837
+ /**
838
+ * ===================================================================
839
+ * SFU FEEDBACK: REMOTE-OUTBOUND (Subscriber receives feedback)
840
+ * ===================================================================
841
+ *
842
+ * @generated from protobuf message stream.video.sfu.models.RemoteOutboundRtp
843
+ */
844
+ export interface RemoteOutboundRtp {
845
+ /**
846
+ * @generated from protobuf field: stream.video.sfu.models.RtpBase base = 1;
847
+ */
848
+ base?: RtpBase;
849
+ /**
850
+ * @generated from protobuf field: double jitter_seconds = 2;
851
+ */
852
+ jitterSeconds: number;
853
+ /**
854
+ * @generated from protobuf field: double round_trip_time_s = 3;
855
+ */
856
+ roundTripTimeS: number;
857
+ }
705
858
  /**
706
859
  * @generated from protobuf enum stream.video.sfu.models.PeerType
707
860
  */
@@ -968,7 +1121,15 @@ export declare enum SdkType {
968
1121
  /**
969
1122
  * @generated from protobuf enum value: SDK_TYPE_PLAIN_JAVASCRIPT = 9;
970
1123
  */
971
- PLAIN_JAVASCRIPT = 9
1124
+ PLAIN_JAVASCRIPT = 9,
1125
+ /**
1126
+ * @generated from protobuf enum value: SDK_TYPE_PYTHON = 10;
1127
+ */
1128
+ PYTHON = 10,
1129
+ /**
1130
+ * @generated from protobuf enum value: SDK_TYPE_VISION_AGENTS = 11;
1131
+ */
1132
+ VISION_AGENTS = 11
972
1133
  }
973
1134
  /**
974
1135
  * @generated from protobuf enum stream.video.sfu.models.TrackUnpublishReason
@@ -1172,7 +1333,13 @@ export declare enum ClientCapability {
1172
1333
  *
1173
1334
  * @generated from protobuf enum value: CLIENT_CAPABILITY_SUBSCRIBER_VIDEO_PAUSE = 1;
1174
1335
  */
1175
- SUBSCRIBER_VIDEO_PAUSE = 1
1336
+ SUBSCRIBER_VIDEO_PAUSE = 1,
1337
+ /**
1338
+ * Instructs SFU that stats will be sent to the coordinator
1339
+ *
1340
+ * @generated from protobuf enum value: CLIENT_CAPABILITY_COORDINATOR_STATS = 2;
1341
+ */
1342
+ COORDINATOR_STATS = 2
1176
1343
  }
1177
1344
  /**
1178
1345
  * DegradationPreference represents the RTCDegradationPreference from WebRTC.
@@ -1384,4 +1551,39 @@ declare class PerformanceStats$Type extends MessageType<PerformanceStats> {
1384
1551
  * @generated MessageType for protobuf message stream.video.sfu.models.PerformanceStats
1385
1552
  */
1386
1553
  export declare const PerformanceStats: PerformanceStats$Type;
1554
+ declare class RtpBase$Type extends MessageType<RtpBase> {
1555
+ constructor();
1556
+ }
1557
+ /**
1558
+ * @generated MessageType for protobuf message stream.video.sfu.models.RtpBase
1559
+ */
1560
+ export declare const RtpBase: RtpBase$Type;
1561
+ declare class InboundRtp$Type extends MessageType<InboundRtp> {
1562
+ constructor();
1563
+ }
1564
+ /**
1565
+ * @generated MessageType for protobuf message stream.video.sfu.models.InboundRtp
1566
+ */
1567
+ export declare const InboundRtp: InboundRtp$Type;
1568
+ declare class OutboundRtp$Type extends MessageType<OutboundRtp> {
1569
+ constructor();
1570
+ }
1571
+ /**
1572
+ * @generated MessageType for protobuf message stream.video.sfu.models.OutboundRtp
1573
+ */
1574
+ export declare const OutboundRtp: OutboundRtp$Type;
1575
+ declare class RemoteInboundRtp$Type extends MessageType<RemoteInboundRtp> {
1576
+ constructor();
1577
+ }
1578
+ /**
1579
+ * @generated MessageType for protobuf message stream.video.sfu.models.RemoteInboundRtp
1580
+ */
1581
+ export declare const RemoteInboundRtp: RemoteInboundRtp$Type;
1582
+ declare class RemoteOutboundRtp$Type extends MessageType<RemoteOutboundRtp> {
1583
+ constructor();
1584
+ }
1585
+ /**
1586
+ * @generated MessageType for protobuf message stream.video.sfu.models.RemoteOutboundRtp
1587
+ */
1588
+ export declare const RemoteOutboundRtp: RemoteOutboundRtp$Type;
1387
1589
  export {};
@@ -1,5 +1,5 @@
1
1
  import type { RpcOptions, RpcTransport, ServiceInfo, UnaryCall } from '@protobuf-ts/runtime-rpc';
2
- import type { ICERestartRequest, ICERestartResponse, ICETrickleResponse, SendAnswerRequest, SendAnswerResponse, SendStatsRequest, SendStatsResponse, SetPublisherRequest, SetPublisherResponse, StartNoiseCancellationRequest, StartNoiseCancellationResponse, StopNoiseCancellationRequest, StopNoiseCancellationResponse, UpdateMuteStatesRequest, UpdateMuteStatesResponse, UpdateSubscriptionsRequest, UpdateSubscriptionsResponse } from './signal';
2
+ import type { ICERestartRequest, ICERestartResponse, ICETrickleResponse, SendAnswerRequest, SendAnswerResponse, SendMetricsRequest, SendMetricsResponse, SendStatsRequest, SendStatsResponse, SetPublisherRequest, SetPublisherResponse, StartNoiseCancellationRequest, StartNoiseCancellationResponse, StopNoiseCancellationRequest, StopNoiseCancellationResponse, UpdateMuteStatesRequest, UpdateMuteStatesResponse, UpdateSubscriptionsRequest, UpdateSubscriptionsResponse } from './signal';
3
3
  import type { ICETrickle } from '../models/models';
4
4
  /**
5
5
  * @generated from protobuf service stream.video.sfu.signal.SignalServer
@@ -42,6 +42,10 @@ export interface ISignalServerClient {
42
42
  * @generated from protobuf rpc: SendStats(stream.video.sfu.signal.SendStatsRequest) returns (stream.video.sfu.signal.SendStatsResponse);
43
43
  */
44
44
  sendStats(input: SendStatsRequest, options?: RpcOptions): UnaryCall<SendStatsRequest, SendStatsResponse>;
45
+ /**
46
+ * @generated from protobuf rpc: SendMetrics(stream.video.sfu.signal.SendMetricsRequest) returns (stream.video.sfu.signal.SendMetricsResponse);
47
+ */
48
+ sendMetrics(input: SendMetricsRequest, options?: RpcOptions): UnaryCall<SendMetricsRequest, SendMetricsResponse>;
45
49
  /**
46
50
  * @generated from protobuf rpc: StartNoiseCancellation(stream.video.sfu.signal.StartNoiseCancellationRequest) returns (stream.video.sfu.signal.StartNoiseCancellationResponse);
47
51
  */
@@ -99,6 +103,10 @@ export declare class SignalServerClient implements ISignalServerClient, ServiceI
99
103
  * @generated from protobuf rpc: SendStats(stream.video.sfu.signal.SendStatsRequest) returns (stream.video.sfu.signal.SendStatsResponse);
100
104
  */
101
105
  sendStats(input: SendStatsRequest, options?: RpcOptions): UnaryCall<SendStatsRequest, SendStatsResponse>;
106
+ /**
107
+ * @generated from protobuf rpc: SendMetrics(stream.video.sfu.signal.SendMetricsRequest) returns (stream.video.sfu.signal.SendMetricsResponse);
108
+ */
109
+ sendMetrics(input: SendMetricsRequest, options?: RpcOptions): UnaryCall<SendMetricsRequest, SendMetricsResponse>;
102
110
  /**
103
111
  * @generated from protobuf rpc: StartNoiseCancellation(stream.video.sfu.signal.StartNoiseCancellationRequest) returns (stream.video.sfu.signal.StartNoiseCancellationResponse);
104
112
  */
@@ -1,6 +1,20 @@
1
- import { AndroidState, AppleState, Error, InputDevices, PeerType, PerformanceStats, RTMPIngress, TrackInfo, TrackType, VideoDimension, WebsocketReconnectStrategy } from '../models/models';
2
1
  import { ServiceType } from '@protobuf-ts/runtime-rpc';
3
2
  import { MessageType } from '@protobuf-ts/runtime';
3
+ import { TrackInfo } from '../models/models';
4
+ import { VideoDimension } from '../models/models';
5
+ import { TrackType } from '../models/models';
6
+ import { PeerType } from '../models/models';
7
+ import { PerformanceStats } from '../models/models';
8
+ import { RTMPIngress } from '../models/models';
9
+ import { AppleState } from '../models/models';
10
+ import { AndroidState } from '../models/models';
11
+ import { InputDevices } from '../models/models';
12
+ import { RemoteOutboundRtp } from '../models/models';
13
+ import { RemoteInboundRtp } from '../models/models';
14
+ import { OutboundRtp } from '../models/models';
15
+ import { InboundRtp } from '../models/models';
16
+ import { WebsocketReconnectStrategy } from '../models/models';
17
+ import { Error } from '../models/models';
4
18
  /**
5
19
  * @generated from protobuf message stream.video.sfu.signal.StartNoiseCancellationRequest
6
20
  */
@@ -73,6 +87,40 @@ export interface Telemetry {
73
87
  oneofKind: undefined;
74
88
  };
75
89
  }
90
+ /**
91
+ * @generated from protobuf message stream.video.sfu.signal.SendMetricsRequest
92
+ */
93
+ export interface SendMetricsRequest {
94
+ /**
95
+ * @generated from protobuf field: string session_id = 1;
96
+ */
97
+ sessionId: string;
98
+ /**
99
+ * @generated from protobuf field: string unified_session_id = 2;
100
+ */
101
+ unifiedSessionId: string;
102
+ /**
103
+ * @generated from protobuf field: repeated stream.video.sfu.models.InboundRtp inbounds = 3;
104
+ */
105
+ inbounds: InboundRtp[];
106
+ /**
107
+ * @generated from protobuf field: repeated stream.video.sfu.models.OutboundRtp outbounds = 4;
108
+ */
109
+ outbounds: OutboundRtp[];
110
+ /**
111
+ * @generated from protobuf field: repeated stream.video.sfu.models.RemoteInboundRtp remote_inbounds = 5;
112
+ */
113
+ remoteInbounds: RemoteInboundRtp[];
114
+ /**
115
+ * @generated from protobuf field: repeated stream.video.sfu.models.RemoteOutboundRtp remote_outbounds = 6;
116
+ */
117
+ remoteOutbounds: RemoteOutboundRtp[];
118
+ }
119
+ /**
120
+ * @generated from protobuf message stream.video.sfu.signal.SendMetricsResponse
121
+ */
122
+ export interface SendMetricsResponse {
123
+ }
76
124
  /**
77
125
  * @generated from protobuf message stream.video.sfu.signal.SendStatsRequest
78
126
  */
@@ -313,6 +361,10 @@ export interface SendAnswerRequest {
313
361
  * @generated from protobuf field: string session_id = 3;
314
362
  */
315
363
  sessionId: string;
364
+ /**
365
+ * @generated from protobuf field: uint32 negotiation_id = 4;
366
+ */
367
+ negotiationId: number;
316
368
  }
317
369
  /**
318
370
  * @generated from protobuf message stream.video.sfu.signal.SendAnswerResponse
@@ -416,6 +468,20 @@ declare class Telemetry$Type extends MessageType<Telemetry> {
416
468
  * @generated MessageType for protobuf message stream.video.sfu.signal.Telemetry
417
469
  */
418
470
  export declare const Telemetry: Telemetry$Type;
471
+ declare class SendMetricsRequest$Type extends MessageType<SendMetricsRequest> {
472
+ constructor();
473
+ }
474
+ /**
475
+ * @generated MessageType for protobuf message stream.video.sfu.signal.SendMetricsRequest
476
+ */
477
+ export declare const SendMetricsRequest: SendMetricsRequest$Type;
478
+ declare class SendMetricsResponse$Type extends MessageType<SendMetricsResponse> {
479
+ constructor();
480
+ }
481
+ /**
482
+ * @generated MessageType for protobuf message stream.video.sfu.signal.SendMetricsResponse
483
+ */
484
+ export declare const SendMetricsResponse: SendMetricsResponse$Type;
419
485
  declare class SendStatsRequest$Type extends MessageType<SendStatsRequest> {
420
486
  constructor();
421
487
  }
@@ -1,4 +1,5 @@
1
1
  import { StreamVideoParticipant, VideoTrackType } from '../types';
2
+ import { TrackType } from '../gen/video/sfu/models/models';
2
3
  /**
3
4
  * Check if a participant has a video.
4
5
  *
@@ -29,6 +30,15 @@ export declare const hasScreenShareAudio: (p: StreamVideoParticipant) => boolean
29
30
  * @param p the participant.
30
31
  */
31
32
  export declare const isPinned: (p: StreamVideoParticipant) => boolean;
33
+ /**
34
+ * Check if a participant has a track that is currently interrupted: the
35
+ * participant intends to publish it (it is in `publishedTracks`) but no
36
+ * media is flowing right now (it is in `interruptedTracks`).
37
+ *
38
+ * @param p the participant to check.
39
+ * @param trackType the track type to check.
40
+ */
41
+ export declare const hasInterruptedTrack: (p: StreamVideoParticipant, trackType: TrackType) => boolean;
32
42
  /**
33
43
  * Check if a participant has a paused track of the specified type.
34
44
  *
@@ -27,7 +27,7 @@ export declare abstract class BasePeerConnection {
27
27
  private iceRestartTimeout?;
28
28
  private preConnectStuckTimeout?;
29
29
  protected isIceRestarting: boolean;
30
- private isDisposed;
30
+ protected isDisposed: boolean;
31
31
  protected trackIdToTrackType: Map<string, TrackType>;
32
32
  readonly tracer?: Tracer;
33
33
  readonly stats: StatsTracer;
@@ -37,12 +37,12 @@ export declare abstract class BasePeerConnection {
37
37
  /**
38
38
  * Constructs a new `BasePeerConnection` instance.
39
39
  */
40
- protected constructor(peerType: PeerType, { sfuClient, connectionConfig, state, dispatcher, onReconnectionNeeded, onIceConnected, tag, enableTracing, clientPublishOptions, iceRestartDelay, }: BasePeerConnectionOpts);
40
+ protected constructor(peerType: PeerType, { sfuClient, connectionConfig, state, dispatcher, onReconnectionNeeded, onIceConnected, tag, enableTracing, clientPublishOptions, iceRestartDelay, statsTimestampDriftThresholdMs, }: BasePeerConnectionOpts);
41
41
  private createPeerConnection;
42
42
  /**
43
43
  * Disposes the `RTCPeerConnection` instance.
44
44
  */
45
- dispose(): void;
45
+ dispose(): Promise<void>;
46
46
  /**
47
47
  * Detaches the event handlers from the `RTCPeerConnection`.
48
48
  */
@@ -62,6 +62,11 @@ export declare abstract class BasePeerConnection {
62
62
  * Consecutive events are queued and executed one after the other.
63
63
  */
64
64
  protected on: <E extends keyof AllSfuEvents>(event: E, fn: CallEventListener<E>) => void;
65
+ /**
66
+ * Returns the per-event `withoutConcurrency` tag used to serialize the
67
+ * dispatcher handler for `event` on this peer connection.
68
+ */
69
+ protected eventLockKey: (event: keyof AllSfuEvents) => string;
65
70
  /**
66
71
  * Appends the trickled ICE candidates to the `RTCPeerConnection`.
67
72
  */
@@ -17,7 +17,7 @@ export declare class Publisher extends BasePeerConnection {
17
17
  /**
18
18
  * Disposes this Publisher instance.
19
19
  */
20
- dispose(): void;
20
+ dispose(): Promise<void>;
21
21
  /**
22
22
  * Starts publishing the given track of the given media stream.
23
23
  *
@@ -71,11 +71,11 @@ export declare class Publisher extends BasePeerConnection {
71
71
  /**
72
72
  * Stops the cloned track that is being published to the SFU.
73
73
  */
74
- stopTracks: (...trackTypes: TrackType[]) => void;
74
+ stopTracks: (...trackTypes: TrackType[]) => Promise<void>;
75
75
  /**
76
76
  * Stops all the cloned tracks that are being published to the SFU.
77
77
  */
78
- stopAllTracks: () => void;
78
+ stopAllTracks: () => Promise<void>;
79
79
  private changePublishQuality;
80
80
  /**
81
81
  * Restarts the ICE connection and renegotiates with the SFU.
@@ -108,4 +108,22 @@ export declare class Publisher extends BasePeerConnection {
108
108
  private toTrackInfo;
109
109
  private cloneTrack;
110
110
  private stopTrack;
111
+ /**
112
+ * Silences a Firefox sender on the wire during unpublish.
113
+ *
114
+ * Firefox keeps emitting RTP after track.stop(), but the right lever
115
+ * differs by track type:
116
+ * - audio: `replaceTrack(null)` is the only reliable silencer;
117
+ * `setParameters({encodings:[...active:false]})` does NOT stop
118
+ * the Opus encoder.
119
+ * - video: `setParameters({encodings:[...active:false]})` pauses
120
+ * the encoder; `replaceTrack(null)` does NOT reliably stop the
121
+ * video encoder. The prior active=true configuration is captured
122
+ * onto `bundle.videoSender` so `updateTransceiver` can restore
123
+ * it on the next publish.
124
+ *
125
+ * No-op on non-Firefox browsers and during teardown.
126
+ */
127
+ private silenceSenderOnFirefox;
128
+ private disableAllEncodings;
111
129
  }
@@ -1,4 +1,4 @@
1
- import { PublishOption } from '../gen/video/sfu/models/models';
1
+ import { PublishOption, TrackType } from '../gen/video/sfu/models/models';
2
2
  import type { OptimalVideoLayer } from './layers';
3
3
  import type { PublishBundle } from './types';
4
4
  export declare class TransceiverCache {
@@ -18,6 +18,10 @@ export declare class TransceiverCache {
18
18
  * Gets the transceiver for the given publish option.
19
19
  */
20
20
  get: (publishOption: PublishOption) => PublishBundle | undefined;
21
+ /**
22
+ * Gets the transceiver for the given publish option id and track type.
23
+ */
24
+ getBy: (publishOptionId: number, trackType: TrackType) => PublishBundle | undefined;
21
25
  /**
22
26
  * Updates the cached bundle with the given patch.
23
27
  */
@@ -1,2 +1,3 @@
1
1
  import { DegradationPreference } from '../../gen/video/sfu/models/models';
2
2
  export declare const toRTCDegradationPreference: (preference: DegradationPreference) => RTCDegradationPreference | undefined;
3
+ export declare const fromRTCDegradationPreference: (preference: RTCDegradationPreference | undefined) => DegradationPreference;
@@ -4,6 +4,7 @@ import { CallState } from '../store';
4
4
  import { Dispatcher } from './Dispatcher';
5
5
  import type { OptimalVideoLayer } from './layers';
6
6
  import type { ClientPublishOptions } from '../types';
7
+ import type { VideoSender } from '../gen/video/sfu/event/events';
7
8
  /**
8
9
  * Canonical reasons the SDK uses to trigger a reconnection. Free-form strings
9
10
  * are still accepted at the callback boundary (e.g. when forwarding an SFU
@@ -47,6 +48,7 @@ export type BasePeerConnectionOpts = {
47
48
  enableTracing: boolean;
48
49
  iceRestartDelay?: number;
49
50
  clientPublishOptions?: ClientPublishOptions;
51
+ statsTimestampDriftThresholdMs?: number;
50
52
  };
51
53
  export type TrackPublishOptions = {
52
54
  audioBitrateProfile?: AudioBitrateProfile;
@@ -55,6 +57,7 @@ export type PublishBundle = {
55
57
  publishOption: PublishOption;
56
58
  transceiver: RTCRtpTransceiver;
57
59
  options: TrackPublishOptions;
60
+ videoSender?: VideoSender;
58
61
  };
59
62
  export type TrackLayersCache = {
60
63
  publishOption: PublishOption;