@stream-io/video-client 1.48.0 → 1.50.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 (86) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/index.browser.es.js +1497 -677
  3. package/dist/index.browser.es.js.map +1 -1
  4. package/dist/index.cjs.js +1497 -677
  5. package/dist/index.cjs.js.map +1 -1
  6. package/dist/index.es.js +1497 -677
  7. package/dist/index.es.js.map +1 -1
  8. package/dist/src/Call.d.ts +77 -4
  9. package/dist/src/StreamSfuClient.d.ts +8 -1
  10. package/dist/src/coordinator/connection/client.d.ts +1 -1
  11. package/dist/src/coordinator/connection/connection.d.ts +31 -25
  12. package/dist/src/coordinator/connection/types.d.ts +14 -0
  13. package/dist/src/coordinator/connection/utils.d.ts +1 -0
  14. package/dist/src/devices/DeviceManager.d.ts +3 -0
  15. package/dist/src/devices/DeviceManagerState.d.ts +13 -1
  16. package/dist/src/gen/video/sfu/event/events.d.ts +5 -1
  17. package/dist/src/gen/video/sfu/models/models.d.ts +34 -0
  18. package/dist/src/helpers/AudioBindingsWatchdog.d.ts +3 -3
  19. package/dist/src/helpers/BlockedAudioTracker.d.ts +30 -0
  20. package/dist/src/helpers/DynascaleManager.d.ts +8 -86
  21. package/dist/src/helpers/MediaPlaybackWatchdog.d.ts +32 -0
  22. package/dist/src/helpers/SlidingWindowRateLimiter.d.ts +28 -0
  23. package/dist/src/helpers/TrackSubscriptionManager.d.ts +114 -0
  24. package/dist/src/helpers/ViewportTracker.d.ts +11 -17
  25. package/dist/src/helpers/browsers.d.ts +13 -0
  26. package/dist/src/helpers/concurrency.d.ts +6 -4
  27. package/dist/src/rtc/BasePeerConnection.d.ts +11 -2
  28. package/dist/src/rtc/Publisher.d.ts +17 -0
  29. package/dist/src/rtc/Subscriber.d.ts +1 -0
  30. package/dist/src/rtc/helpers/degradationPreference.d.ts +2 -0
  31. package/dist/src/rtc/index.d.ts +1 -0
  32. package/dist/src/rtc/types.d.ts +33 -1
  33. package/dist/src/stats/rtc/types.d.ts +1 -1
  34. package/dist/src/store/rxUtils.d.ts +9 -0
  35. package/dist/src/types.d.ts +18 -0
  36. package/package.json +2 -2
  37. package/src/Call.ts +268 -40
  38. package/src/StreamSfuClient.ts +75 -12
  39. package/src/__tests__/Call.lifecycle.test.ts +67 -0
  40. package/src/__tests__/Call.publishing.test.ts +103 -0
  41. package/src/__tests__/StreamSfuClient.test.ts +275 -0
  42. package/src/coordinator/connection/__tests__/connection.test.ts +482 -0
  43. package/src/coordinator/connection/client.ts +1 -1
  44. package/src/coordinator/connection/connection.ts +149 -96
  45. package/src/coordinator/connection/types.ts +15 -0
  46. package/src/coordinator/connection/utils.ts +15 -0
  47. package/src/devices/DeviceManager.ts +92 -32
  48. package/src/devices/DeviceManagerState.ts +20 -1
  49. package/src/devices/__tests__/DeviceManager.test.ts +283 -0
  50. package/src/devices/__tests__/ScreenShareManager.test.ts +0 -2
  51. package/src/devices/__tests__/mocks.ts +2 -0
  52. package/src/devices/devices.ts +2 -1
  53. package/src/gen/video/sfu/event/events.ts +15 -0
  54. package/src/gen/video/sfu/models/models.ts +44 -0
  55. package/src/helpers/AudioBindingsWatchdog.ts +10 -7
  56. package/src/helpers/BlockedAudioTracker.ts +74 -0
  57. package/src/helpers/DynascaleManager.ts +46 -337
  58. package/src/helpers/MediaPlaybackWatchdog.ts +121 -0
  59. package/src/helpers/SlidingWindowRateLimiter.ts +49 -0
  60. package/src/helpers/TrackSubscriptionManager.ts +243 -0
  61. package/src/helpers/ViewportTracker.ts +74 -19
  62. package/src/helpers/__tests__/BlockedAudioTracker.test.ts +114 -0
  63. package/src/helpers/__tests__/DynascaleManager.test.ts +175 -122
  64. package/src/helpers/__tests__/MediaPlaybackWatchdog.test.ts +180 -0
  65. package/src/helpers/__tests__/SlidingWindowRateLimiter.test.ts +43 -0
  66. package/src/helpers/__tests__/TrackSubscriptionManager.test.ts +310 -0
  67. package/src/helpers/__tests__/ViewportTracker.test.ts +83 -0
  68. package/src/helpers/__tests__/browsers.test.ts +85 -1
  69. package/src/helpers/browsers.ts +24 -0
  70. package/src/helpers/concurrency.ts +9 -10
  71. package/src/rpc/retryable.ts +0 -1
  72. package/src/rtc/BasePeerConnection.ts +96 -6
  73. package/src/rtc/Publisher.ts +49 -2
  74. package/src/rtc/Subscriber.ts +42 -14
  75. package/src/rtc/__tests__/Call.reconnect.test.ts +761 -0
  76. package/src/rtc/__tests__/Publisher.test.ts +332 -10
  77. package/src/rtc/__tests__/Subscriber.test.ts +202 -1
  78. package/src/rtc/__tests__/mocks/webrtc.mocks.ts +13 -2
  79. package/src/rtc/helpers/__tests__/degradationPreference.test.ts +23 -0
  80. package/src/rtc/helpers/degradationPreference.ts +22 -0
  81. package/src/rtc/index.ts +1 -0
  82. package/src/rtc/types.ts +38 -1
  83. package/src/stats/rtc/types.ts +1 -0
  84. package/src/store/__tests__/rxUtils.test.ts +276 -0
  85. package/src/store/rxUtils.ts +19 -0
  86. package/src/types.ts +19 -0
@@ -0,0 +1,28 @@
1
+ /**
2
+ * A generic sliding-window rate limiter.
3
+ *
4
+ * Allows at most `maxAttempts` registrations inside a rolling `windowMs`.
5
+ * Attempts spaced further apart than `windowMs` are always allowed.
6
+ */
7
+ export declare class SlidingWindowRateLimiter {
8
+ private maxAttempts;
9
+ private windowMs;
10
+ private timestamps;
11
+ constructor(maxAttempts: number, windowMs: number);
12
+ /**
13
+ * Attempts to register a new event at `now`. Returns `true` if the attempt
14
+ * fits inside the budget (and records it), or `false` if the budget is
15
+ * exhausted (in which case no timestamp is recorded).
16
+ */
17
+ tryRegister: (now?: number) => boolean;
18
+ /**
19
+ * Clears the attempt history.
20
+ */
21
+ reset: () => void;
22
+ /**
23
+ * Updates the budget and window size. Existing timestamps are kept; they
24
+ * will be pruned by the next `tryRegister` call.
25
+ */
26
+ setLimits: (maxAttempts: number, windowMs: number) => void;
27
+ private prune;
28
+ }
@@ -0,0 +1,114 @@
1
+ import { DebounceType } from '../types';
2
+ import type { TrackSubscriptionDetails } from '../gen/video/sfu/signal_rpc/signal';
3
+ import { VideoDimension } from '../gen/video/sfu/models/models';
4
+ import { CallState } from '../store';
5
+ import type { StreamSfuClient } from '../StreamSfuClient';
6
+ import { Tracer } from '../stats';
7
+ /**
8
+ * Per-participant (or global) video-subscription override.
9
+ *
10
+ * - `{ enabled: true, dimension }`: request video at a specific
11
+ * resolution. If set globally, applies to every remote participant
12
+ * that doesn't have a per-session override.
13
+ * - `{ enabled: false }`: unsubscribe from video entirely. The SFU
14
+ * sends nothing; bandwidth is saved.
15
+ */
16
+ export type VideoTrackSubscriptionOverride = {
17
+ enabled: true;
18
+ dimension: VideoDimension;
19
+ } | {
20
+ enabled: false;
21
+ };
22
+ /** Symbol key for the "applies to all participants" override slot. */
23
+ declare const globalOverrideKey: unique symbol;
24
+ /**
25
+ * Map of per-session overrides plus one optional global override under
26
+ * the `globalOverrideKey` symbol slot.
27
+ */
28
+ export interface VideoTrackSubscriptionOverrides {
29
+ [sessionId: string]: VideoTrackSubscriptionOverride | undefined;
30
+ [globalOverrideKey]?: VideoTrackSubscriptionOverride;
31
+ }
32
+ /**
33
+ * Owns the SFU-side video-subscription machinery for a `Call`:
34
+ *
35
+ * - Holds the per-session / global override state in a
36
+ * `BehaviorSubject<VideoTrackSubscriptionOverrides>`.
37
+ * - Derives the SFU subscription list from `CallState` participants +
38
+ * current overrides via the `subscriptions` getter.
39
+ * - Debounces and pushes the list to the SFU through
40
+ * `sfuClient.updateSubscriptions`.
41
+ * - Exposes `incomingVideoSettings$`: a consumer-friendly projection of
42
+ * the override state for React hooks.
43
+ *
44
+ * Owned by `DynascaleManager` as `readonly trackSubscriptionManager`.
45
+ * `DynascaleManager.bindVideoElement` triggers `apply()` on every
46
+ * dimension / visibility change.
47
+ */
48
+ export declare class TrackSubscriptionManager {
49
+ private logger;
50
+ private callState;
51
+ private tracer;
52
+ private sfuClient;
53
+ private pendingUpdate;
54
+ private overridesSubject;
55
+ overrides$: import("rxjs").Observable<VideoTrackSubscriptionOverrides>;
56
+ /**
57
+ * Consumer-friendly projection of the override state. Used by the
58
+ * `useIncomingVideoSettings()` React hook.
59
+ */
60
+ incomingVideoSettings$: import("rxjs").Observable<{
61
+ enabled: boolean;
62
+ preferredResolution: VideoDimension | undefined;
63
+ participants: {
64
+ [k: string]: {
65
+ enabled: boolean;
66
+ preferredResolution: VideoDimension | undefined;
67
+ };
68
+ };
69
+ isParticipantVideoEnabled: (sessionId: string) => boolean;
70
+ }>;
71
+ /**
72
+ * Constructs new TrackSubscriptionManager instance.
73
+ *
74
+ * @param callState the call state.
75
+ * @param tracer the tracer to use.
76
+ */
77
+ constructor(callState: CallState, tracer: Tracer);
78
+ /**
79
+ * Sets the SFU client used by `apply()` to push subscription updates.
80
+ * Called by the owner on call join; cleared on leave.
81
+ */
82
+ setSfuClient: (sfuClient: StreamSfuClient | undefined) => void;
83
+ /**
84
+ * Cancels any pending debounced subscription push. Idempotent.
85
+ */
86
+ dispose: () => void;
87
+ /**
88
+ * The current SFU subscription list, computed from `CallState`
89
+ * participants and the override state. Used by:
90
+ *
91
+ * - `apply()` to push to the SFU each time the set changes.
92
+ * - `Call.getReconnectDetails` to include the subscription list in
93
+ * the reconnect payload.
94
+ */
95
+ get subscriptions(): TrackSubscriptionDetails[];
96
+ get overrides(): VideoTrackSubscriptionOverrides;
97
+ /**
98
+ * Sets video-subscription overrides. Called by
99
+ * `Call.setIncomingVideoEnabled` and
100
+ * `Call.setPreferredIncomingVideoResolution`.
101
+ *
102
+ * - `sessionIds` omitted → applies `override` globally (or clears the
103
+ * global override if `override` is `undefined`).
104
+ * - `sessionIds` provided → applies `override` to each listed session.
105
+ */
106
+ setOverrides: (override: VideoTrackSubscriptionOverride | undefined, sessionIds?: string[]) => VideoTrackSubscriptionOverrides;
107
+ /**
108
+ * Pushes `subscriptions` to the SFU. Debounced by `debounceType`
109
+ * (SLOW by default). Multiple rapid calls coalesce into one RPC.
110
+ * Passing `0` fires synchronously.
111
+ */
112
+ apply: (debounceType?: DebounceType) => void;
113
+ }
114
+ export {};
@@ -1,36 +1,30 @@
1
+ import type { CallState } from '../store';
2
+ import { VideoTrackType } from '../types';
1
3
  export type EntryHandler = (entry: IntersectionObserverEntry) => void;
2
4
  export type Unobserve = () => void;
3
5
  export type Observe = (element: HTMLElement, entryHandler: EntryHandler) => Unobserve;
4
6
  export declare class ViewportTracker {
5
- /**
6
- * @private
7
- */
7
+ private callState;
8
8
  private elementHandlerMap;
9
- /**
10
- * @private
11
- */
12
9
  private observer;
13
- /**
14
- * @private
15
- */
16
10
  private queueSet;
11
+ constructor(callState: CallState);
17
12
  /**
18
13
  * Method to set scrollable viewport as root for the IntersectionObserver, returns
19
14
  * cleanup function to be invoked upon disposing of the DOM element to prevent memory leaks
20
- *
21
- * @param viewportElement
22
- * @param options
23
- * @returns Unobserve
24
15
  */
25
16
  setViewport: (viewportElement: HTMLElement, options?: Pick<IntersectionObserverInit, "threshold" | "rootMargin">) => () => void;
26
17
  /**
27
18
  * Method to set element to observe and handler to be triggered whenever IntersectionObserver
28
19
  * detects a possible change in element's visibility within specified viewport, returns
29
20
  * cleanup function to be invoked upon disposing of the DOM element to prevent memory leaks
30
- *
31
- * @param element
32
- * @param handler
33
- * @returns Unobserve
34
21
  */
35
22
  observe: Observe;
23
+ /**
24
+ * Tracks the given element for visibility changes and mirrors the result
25
+ * into `participant.viewportVisibilityState[trackType]` in `CallState`.
26
+ * Returns a function that unobserves the element and resets the visibility
27
+ * state back to `UNKNOWN`.
28
+ */
29
+ trackElementVisibility: <T extends HTMLElement>(element: T, sessionId: string, trackType: VideoTrackType) => () => void;
36
30
  }
@@ -2,6 +2,19 @@
2
2
  * Checks whether the current browser is Safari.
3
3
  */
4
4
  export declare const isSafari: () => boolean;
5
+ /**
6
+ * Checks whether the current runtime is a WebKit-engine browser.
7
+ *
8
+ * Returns true for desktop Safari, iOS Safari, bare iOS WKWebView hosts
9
+ * (in-app browsers, React Native WebView, Tauri-on-macOS, etc.), and for
10
+ * Chromium / Gecko-branded iOS browsers (`CriOS`, `EdgiOS`, `OPiOS`,
11
+ * `FxiOS`) since Apple forces every iOS browser onto WKWebView and they
12
+ * share the underlying WebKit quirks.
13
+ *
14
+ * Returns false for desktop Chromium-based browsers (which reuse the
15
+ * `AppleWebKit/` token in their UA) and Android.
16
+ */
17
+ export declare const isWebKit: () => boolean;
5
18
  /**
6
19
  * Checks whether the current browser is Firefox.
7
20
  */
@@ -1,3 +1,4 @@
1
+ type TagKey = string | symbol | object;
1
2
  /**
2
3
  * Runs async functions serially. Useful for wrapping async actions that
3
4
  * should never run simultaneously: if marked with the same tag, functions
@@ -8,7 +9,7 @@
8
9
  * @param cb Async function to run.
9
10
  * @returns Promise that resolves when async functions returns.
10
11
  */
11
- export declare const withoutConcurrency: <T>(tag: string | symbol, cb: () => Promise<T>) => Promise<T>;
12
+ export declare const withoutConcurrency: <T>(tag: TagKey, cb: () => Promise<T>) => Promise<T>;
12
13
  /**
13
14
  * Runs async functions serially, and cancels all other actions with the same tag
14
15
  * when a new action is scheduled. Useful for wrapping async actions that override
@@ -25,6 +26,7 @@ export declare const withoutConcurrency: <T>(tag: string | symbol, cb: () => Pro
25
26
  * start and was canceled, will resolve with 'canceled'. If the function started to run,
26
27
  * it's up to the function to decide how to react to cancelation.
27
28
  */
28
- export declare const withCancellation: <T>(tag: string | symbol, cb: (signal: AbortSignal) => Promise<T | "canceled">) => Promise<T | "canceled">;
29
- export declare function hasPending(tag: string | symbol): boolean;
30
- export declare function settled(tag: string | symbol): Promise<void>;
29
+ export declare const withCancellation: <T>(tag: TagKey, cb: (signal: AbortSignal) => Promise<T | "canceled">) => Promise<T | "canceled">;
30
+ export declare function hasPending(tag: TagKey): boolean;
31
+ export declare function settled(tag: TagKey): Promise<void>;
32
+ export {};
@@ -5,7 +5,7 @@ import { PeerType, TrackType } from '../gen/video/sfu/models/models';
5
5
  import { StreamSfuClient } from '../StreamSfuClient';
6
6
  import { AllSfuEvents, Dispatcher } from './Dispatcher';
7
7
  import { StatsTracer, Tracer } from '../stats';
8
- import type { BasePeerConnectionOpts } from './types';
8
+ import { BasePeerConnectionOpts } from './types';
9
9
  import type { ClientPublishOptions } from '../types';
10
10
  /**
11
11
  * A base class for the `Publisher` and `Subscriber` classes.
@@ -21,8 +21,11 @@ export declare abstract class BasePeerConnection {
21
21
  protected tag: string;
22
22
  protected sfuClient: StreamSfuClient;
23
23
  private onReconnectionNeeded?;
24
+ private onIceConnected?;
24
25
  private readonly iceRestartDelay;
26
+ private iceHasEverConnected;
25
27
  private iceRestartTimeout?;
28
+ private preConnectStuckTimeout?;
26
29
  protected isIceRestarting: boolean;
27
30
  private isDisposed;
28
31
  protected trackIdToTrackType: Map<string, TrackType>;
@@ -34,7 +37,7 @@ export declare abstract class BasePeerConnection {
34
37
  /**
35
38
  * Constructs a new `BasePeerConnection` instance.
36
39
  */
37
- protected constructor(peerType: PeerType, { sfuClient, connectionConfig, state, dispatcher, onReconnectionNeeded, tag, enableTracing, clientPublishOptions, iceRestartDelay, }: BasePeerConnectionOpts);
40
+ protected constructor(peerType: PeerType, { sfuClient, connectionConfig, state, dispatcher, onReconnectionNeeded, onIceConnected, tag, enableTracing, clientPublishOptions, iceRestartDelay, }: BasePeerConnectionOpts);
38
41
  private createPeerConnection;
39
42
  /**
40
43
  * Disposes the `RTCPeerConnection` instance.
@@ -85,6 +88,12 @@ export declare abstract class BasePeerConnection {
85
88
  * it returns `false`, otherwise it returns `true`.
86
89
  */
87
90
  isHealthy: () => boolean;
91
+ /**
92
+ * Returns true only when the peer connection is currently fully established
93
+ * (ICE `connected`/`completed` AND connection state `connected`).
94
+ * Transient states like `disconnected`, `checking`, or `new` return false.
95
+ */
96
+ isStable: () => boolean;
88
97
  /**
89
98
  * Handles the ICECandidate event and
90
99
  * Initiates an ICE Trickle process with the SFU.
@@ -51,6 +51,23 @@ export declare class Publisher extends BasePeerConnection {
51
51
  * @param trackType the track type to check. If omitted, checks if any track is being published.
52
52
  */
53
53
  isPublishing: (trackType?: TrackType) => boolean;
54
+ /**
55
+ * Re-arms the encoder for the given track type by detaching and
56
+ * reattaching the currently published track on each matching sender.
57
+ *
58
+ * Workaround for a WebKit / iOS Safari quirk: after a system audio
59
+ * session interruption (Siri, PSTN call), the `RTCRtpSender` encoder
60
+ * can stop producing RTP packets even though the underlying
61
+ * `MediaStreamTrack` is `live` and `track.muted === false`.
62
+ * `replaceTrack(null)` followed by `replaceTrack(track)` resets the
63
+ * sender's encoder pipeline without renegotiation, restoring packet
64
+ * flow with the same SSRC.
65
+ *
66
+ * No-op when nothing is published for the given track type.
67
+ *
68
+ * @param trackType the track type to refresh.
69
+ */
70
+ refreshTrack: (trackType: TrackType) => Promise<void>;
54
71
  /**
55
72
  * Stops the cloned track that is being published to the SFU.
56
73
  */
@@ -22,5 +22,6 @@ export declare class Subscriber extends BasePeerConnection {
22
22
  */
23
23
  restartIce: () => Promise<void>;
24
24
  private handleOnTrack;
25
+ private setRemoteTrackInterrupted;
25
26
  private negotiate;
26
27
  }
@@ -0,0 +1,2 @@
1
+ import { DegradationPreference } from '../../gen/video/sfu/models/models';
2
+ export declare const toRTCDegradationPreference: (preference: DegradationPreference) => RTCDegradationPreference | undefined;
@@ -1,5 +1,6 @@
1
1
  export * from './codecs';
2
2
  export * from './Dispatcher';
3
+ export * from './NegotiationError';
3
4
  export * from './IceTrickleBuffer';
4
5
  export * from './Publisher';
5
6
  export * from './Subscriber';
@@ -4,13 +4,45 @@ 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
- export type OnReconnectionNeeded = (kind: WebsocketReconnectStrategy, reason: string, peerType: PeerType) => void;
7
+ /**
8
+ * Canonical reasons the SDK uses to trigger a reconnection. Free-form strings
9
+ * are still accepted at the callback boundary (e.g. when forwarding an SFU
10
+ * error message), but only the members below influence reconnect-loop
11
+ * behavior. In particular, `Call.reconnect` programmatically inspects
12
+ * `ICE_NEVER_CONNECTED` to drive the unsupported-network detector — pass a
13
+ * canonical member when you want the SDK to react to the reason; pass a
14
+ * free-form string when the value is purely diagnostic.
15
+ */
16
+ export declare const ReconnectReason: {
17
+ /** ICE never reached `connected`/`completed`, escalate to REJOIN. */
18
+ readonly ICE_NEVER_CONNECTED: "ice_never_connected";
19
+ /** RTCPeerConnection.connectionState became `failed`. */
20
+ readonly CONNECTION_FAILED: "connection_failed";
21
+ /** `restartIce()` rejected. */
22
+ readonly RESTART_ICE_FAILED: "restart_ice_failed";
23
+ /** SFU `goAway` event, migrate to a new SFU. */
24
+ readonly GO_AWAY: "go_away";
25
+ /** Network came back online after going offline. */
26
+ readonly NETWORK_BACK_ONLINE: "network_back_online";
27
+ /** SFU error event with no descriptive message. */
28
+ readonly SFU_ERROR: "sfu_error";
29
+ };
30
+ export type ReconnectReason = (typeof ReconnectReason)[keyof typeof ReconnectReason] | (string & {});
31
+ export type OnReconnectionNeeded = (kind: WebsocketReconnectStrategy, reason: ReconnectReason, peerType: PeerType) => void;
32
+ /**
33
+ * Fires the first time a peer connection's ICE transport reaches
34
+ * `connected` or `completed` during its lifetime. Used by `Call` to reset
35
+ * the "ICE never connected" failure counter only when WebRTC has actually
36
+ * recovered, not merely when the SFU join handshake succeeded.
37
+ */
38
+ export type OnIceConnected = (peerType: PeerType) => void;
8
39
  export type BasePeerConnectionOpts = {
9
40
  sfuClient: StreamSfuClient;
10
41
  state: CallState;
11
42
  connectionConfig?: RTCConfiguration;
12
43
  dispatcher: Dispatcher;
13
44
  onReconnectionNeeded?: OnReconnectionNeeded;
45
+ onIceConnected?: OnIceConnected;
14
46
  tag: string;
15
47
  enableTracing: boolean;
16
48
  iceRestartDelay?: number;
@@ -1,5 +1,5 @@
1
1
  import type { PerformanceStats } from '../../gen/video/sfu/models/models';
2
- export type RTCStatsDataType = RTCConfiguration | RTCIceCandidate | RTCSignalingState | RTCIceConnectionState | RTCIceGatheringState | RTCPeerConnectionState | [number | null | string] | string | boolean | RTCOfferOptions | [string | RTCDataChannelInit | undefined] | (RTCOfferOptions | undefined) | RTCSessionDescriptionInit | (RTCIceCandidateInit | RTCIceCandidate) | object | null | undefined;
2
+ export type RTCStatsDataType = RTCConfiguration | RTCIceCandidate | RTCSignalingState | RTCIceConnectionState | RTCIceGatheringState | RTCPeerConnectionState | [number | null | string] | string | boolean | RTCOfferOptions | [string | RTCDataChannelInit | undefined] | (RTCOfferOptions | undefined) | RTCSessionDescriptionInit | (RTCIceCandidateInit | RTCIceCandidate) | object | number | null | undefined;
3
3
  export type TraceKey = 'device-enumeration' | (string & {});
4
4
  export type Trace = (tag: string, data: RTCStatsDataType) => void;
5
5
  export type TraceRecord = [
@@ -1,5 +1,6 @@
1
1
  import { BehaviorSubject, Observable, Subject } from 'rxjs';
2
2
  type FunctionPatch<T> = (currentValue: T) => T;
3
+ type AsyncFunctionPatch<T> = (currentValue: T) => Promise<T>;
3
4
  /**
4
5
  * A value or a function which takes the current value and returns a new value.
5
6
  */
@@ -21,6 +22,14 @@ export declare const getCurrentValue: <T>(observable$: Observable<T>) => T;
21
22
  * @return the updated value.
22
23
  */
23
24
  export declare const setCurrentValue: <T>(subject: Subject<T>, update: Patch<T>) => T;
25
+ /**
26
+ * Updates the value of the provided Subject asynchronously.
27
+ * Locks the subject to prevent concurrent updates.
28
+ *
29
+ * @param subject the subject to update.
30
+ * @param update the update to apply to the subject.
31
+ */
32
+ export declare const setCurrentValueAsync: <T>(subject: Subject<T>, update: AsyncFunctionPatch<T>) => Promise<T>;
24
33
  /**
25
34
  * Updates the value of the provided Subject and returns the previous value
26
35
  * and a function to roll back the update.
@@ -58,6 +58,24 @@ export interface StreamVideoParticipant extends Participant {
58
58
  * This is useful to avoid any unwanted video and audio artifacts.
59
59
  */
60
60
  pausedTracks?: TrackType[];
61
+ /**
62
+ * The list of tracks that are currently not producing media.
63
+ *
64
+ * For remote participants this is currently surfaced for `TrackType.AUDIO`
65
+ * only and reflects the receiver-side `RTCRtpReceiver` track `mute`/`unmute`
66
+ * state, so it covers system mute on the sender (OS audio session
67
+ * interruption, etc.), the sender pausing its track, sustained RTP stalls,
68
+ * and SFU drops. Remote video and screen-share interruption is not tracked.
69
+ *
70
+ * For the local participant it reflects the local track `mute`/`unmute`
71
+ * events surfaced by the browser (e.g. bluetooth disconnect, OS-level
72
+ * mic/camera kill switch, iOS audio session interruption).
73
+ *
74
+ * Orthogonal to `publishedTracks`: a track can be in `publishedTracks`
75
+ * AND in `interruptedTracks` (the participant intends to publish, but
76
+ * no media is flowing right now).
77
+ */
78
+ interruptedTracks?: TrackType[];
61
79
  /**
62
80
  * True if the participant is the local participant.
63
81
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stream-io/video-client",
3
- "version": "1.48.0",
3
+ "version": "1.50.0",
4
4
  "main": "dist/index.cjs.js",
5
5
  "module": "dist/index.es.js",
6
6
  "browser": "dist/index.browser.es.js",
@@ -46,7 +46,7 @@
46
46
  "@openapitools/openapi-generator-cli": "^2.25.0",
47
47
  "@rollup/plugin-replace": "^6.0.2",
48
48
  "@rollup/plugin-typescript": "^12.1.4",
49
- "@stream-io/audio-filters-web": "^0.7.3",
49
+ "@stream-io/audio-filters-web": "^0.8.0",
50
50
  "@stream-io/node-sdk": "^0.7.28",
51
51
  "@total-typescript/shoehorn": "^0.1.2",
52
52
  "@types/sdp-transform": "^2.15.0",