@stream-io/video-client 1.49.0 → 1.51.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.
- package/CHANGELOG.md +22 -0
- package/dist/index.browser.es.js +1404 -682
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +1404 -682
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +1404 -682
- package/dist/index.es.js.map +1 -1
- package/dist/src/Call.d.ts +43 -3
- package/dist/src/coordinator/connection/client.d.ts +1 -1
- package/dist/src/coordinator/connection/connection.d.ts +31 -25
- package/dist/src/coordinator/connection/types.d.ts +14 -0
- package/dist/src/coordinator/connection/utils.d.ts +1 -0
- package/dist/src/devices/CameraManager.d.ts +1 -0
- package/dist/src/devices/DeviceManager.d.ts +23 -0
- package/dist/src/devices/DeviceManagerState.d.ts +0 -1
- package/dist/src/devices/VirtualDevice.d.ts +59 -0
- package/dist/src/devices/devicePersistence.d.ts +1 -1
- package/dist/src/devices/index.d.ts +1 -0
- package/dist/src/gen/video/sfu/event/events.d.ts +5 -1
- package/dist/src/gen/video/sfu/models/models.d.ts +34 -0
- package/dist/src/helpers/AudioBindingsWatchdog.d.ts +3 -3
- package/dist/src/helpers/BlockedAudioTracker.d.ts +30 -0
- package/dist/src/helpers/DynascaleManager.d.ts +8 -86
- package/dist/src/helpers/MediaPlaybackWatchdog.d.ts +32 -0
- package/dist/src/helpers/TrackSubscriptionManager.d.ts +114 -0
- package/dist/src/helpers/ViewportTracker.d.ts +11 -17
- package/dist/src/helpers/browsers.d.ts +13 -0
- package/dist/src/helpers/concurrency.d.ts +6 -4
- package/dist/src/rtc/BasePeerConnection.d.ts +7 -2
- package/dist/src/rtc/Publisher.d.ts +38 -3
- package/dist/src/rtc/Subscriber.d.ts +1 -0
- package/dist/src/rtc/TransceiverCache.d.ts +5 -1
- package/dist/src/rtc/helpers/degradationPreference.d.ts +3 -0
- package/dist/src/rtc/types.d.ts +2 -0
- package/dist/src/stats/rtc/types.d.ts +1 -1
- package/dist/src/store/rxUtils.d.ts +9 -0
- package/dist/src/types.d.ts +18 -0
- package/package.json +2 -2
- package/src/Call.ts +111 -33
- package/src/__tests__/Call.lifecycle.test.ts +67 -0
- package/src/coordinator/connection/__tests__/connection.test.ts +482 -0
- package/src/coordinator/connection/client.ts +1 -1
- package/src/coordinator/connection/connection.ts +149 -96
- package/src/coordinator/connection/types.ts +15 -0
- package/src/coordinator/connection/utils.ts +15 -0
- package/src/devices/CameraManager.ts +9 -2
- package/src/devices/DeviceManager.ts +239 -39
- package/src/devices/DeviceManagerState.ts +4 -2
- package/src/devices/VirtualDevice.ts +69 -0
- package/src/devices/__tests__/CameraManager.test.ts +19 -0
- package/src/devices/__tests__/DeviceManager.test.ts +404 -1
- package/src/devices/__tests__/mocks.ts +2 -0
- package/src/devices/devicePersistence.ts +2 -1
- package/src/devices/index.ts +1 -0
- package/src/gen/video/sfu/event/events.ts +15 -0
- package/src/gen/video/sfu/models/models.ts +44 -0
- package/src/helpers/AudioBindingsWatchdog.ts +10 -7
- package/src/helpers/BlockedAudioTracker.ts +74 -0
- package/src/helpers/DynascaleManager.ts +46 -337
- package/src/helpers/MediaPlaybackWatchdog.ts +121 -0
- package/src/helpers/TrackSubscriptionManager.ts +243 -0
- package/src/helpers/ViewportTracker.ts +74 -19
- package/src/helpers/__tests__/BlockedAudioTracker.test.ts +114 -0
- package/src/helpers/__tests__/DynascaleManager.test.ts +175 -122
- package/src/helpers/__tests__/MediaPlaybackWatchdog.test.ts +180 -0
- package/src/helpers/__tests__/TrackSubscriptionManager.test.ts +310 -0
- package/src/helpers/__tests__/ViewportTracker.test.ts +83 -0
- package/src/helpers/__tests__/browsers.test.ts +85 -1
- package/src/helpers/browsers.ts +24 -0
- package/src/helpers/concurrency.ts +9 -10
- package/src/rtc/BasePeerConnection.ts +15 -3
- package/src/rtc/Publisher.ts +185 -40
- package/src/rtc/Subscriber.ts +42 -14
- package/src/rtc/TransceiverCache.ts +10 -3
- package/src/rtc/__tests__/Call.reconnect.test.ts +121 -2
- package/src/rtc/__tests__/Publisher.test.ts +747 -88
- package/src/rtc/__tests__/Subscriber.test.ts +148 -3
- package/src/rtc/__tests__/mocks/webrtc.mocks.ts +13 -2
- package/src/rtc/helpers/__tests__/degradationPreference.test.ts +55 -0
- package/src/rtc/helpers/degradationPreference.ts +40 -0
- package/src/rtc/types.ts +2 -0
- package/src/stats/rtc/types.ts +1 -0
- package/src/store/__tests__/rxUtils.test.ts +276 -0
- package/src/store/rxUtils.ts +19 -0
- package/src/types.ts +19 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Tracer } from '../stats';
|
|
2
|
+
type MediaKind = 'audio' | 'video';
|
|
3
|
+
export type MediaPlaybackWatchdogOptions = {
|
|
4
|
+
element: HTMLMediaElement;
|
|
5
|
+
kind: MediaKind;
|
|
6
|
+
tracer: Tracer;
|
|
7
|
+
isBlocked?: () => boolean;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Watches a single audio or video element and attempts to recover playback
|
|
11
|
+
* after the element transitions to a paused or suspended state unexpectedly.
|
|
12
|
+
*/
|
|
13
|
+
export declare class MediaPlaybackWatchdog {
|
|
14
|
+
private logger;
|
|
15
|
+
private readonly kind;
|
|
16
|
+
private readonly isBlocked;
|
|
17
|
+
private element;
|
|
18
|
+
private tracer;
|
|
19
|
+
private controller;
|
|
20
|
+
private pendingTimer;
|
|
21
|
+
private attempt;
|
|
22
|
+
private disposed;
|
|
23
|
+
constructor(opts: MediaPlaybackWatchdogOptions);
|
|
24
|
+
private attach;
|
|
25
|
+
dispose: () => void;
|
|
26
|
+
private onPlaying;
|
|
27
|
+
private onPauseOrSuspend;
|
|
28
|
+
private scheduleRecovery;
|
|
29
|
+
private computeSkipReason;
|
|
30
|
+
private attemptPlay;
|
|
31
|
+
}
|
|
32
|
+
export {};
|
|
@@ -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:
|
|
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:
|
|
29
|
-
export declare function hasPending(tag:
|
|
30
|
-
export declare function settled(tag:
|
|
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 {};
|
|
@@ -27,7 +27,7 @@ export declare abstract class BasePeerConnection {
|
|
|
27
27
|
private iceRestartTimeout?;
|
|
28
28
|
private preConnectStuckTimeout?;
|
|
29
29
|
protected isIceRestarting: boolean;
|
|
30
|
-
|
|
30
|
+
protected isDisposed: boolean;
|
|
31
31
|
protected trackIdToTrackType: Map<string, TrackType>;
|
|
32
32
|
readonly tracer?: Tracer;
|
|
33
33
|
readonly stats: StatsTracer;
|
|
@@ -42,7 +42,7 @@ export declare abstract class BasePeerConnection {
|
|
|
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
|
*
|
|
@@ -51,14 +51,31 @@ 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
|
*/
|
|
57
|
-
stopTracks: (...trackTypes: TrackType[]) => void
|
|
74
|
+
stopTracks: (...trackTypes: TrackType[]) => Promise<void>;
|
|
58
75
|
/**
|
|
59
76
|
* Stops all the cloned tracks that are being published to the SFU.
|
|
60
77
|
*/
|
|
61
|
-
stopAllTracks: () => void
|
|
78
|
+
stopAllTracks: () => Promise<void>;
|
|
62
79
|
private changePublishQuality;
|
|
63
80
|
/**
|
|
64
81
|
* Restarts the ICE connection and renegotiates with the SFU.
|
|
@@ -91,4 +108,22 @@ export declare class Publisher extends BasePeerConnection {
|
|
|
91
108
|
private toTrackInfo;
|
|
92
109
|
private cloneTrack;
|
|
93
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;
|
|
94
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
|
*/
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { DegradationPreference } from '../../gen/video/sfu/models/models';
|
|
2
|
+
export declare const toRTCDegradationPreference: (preference: DegradationPreference) => RTCDegradationPreference | undefined;
|
|
3
|
+
export declare const fromRTCDegradationPreference: (preference: RTCDegradationPreference | undefined) => DegradationPreference;
|
package/dist/src/rtc/types.d.ts
CHANGED
|
@@ -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
|
|
@@ -55,6 +56,7 @@ export type PublishBundle = {
|
|
|
55
56
|
publishOption: PublishOption;
|
|
56
57
|
transceiver: RTCRtpTransceiver;
|
|
57
58
|
options: TrackPublishOptions;
|
|
59
|
+
videoSender?: VideoSender;
|
|
58
60
|
};
|
|
59
61
|
export type TrackLayersCache = {
|
|
60
62
|
publishOption: PublishOption;
|
|
@@ -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.
|
package/dist/src/types.d.ts
CHANGED
|
@@ -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.
|
|
3
|
+
"version": "1.51.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.
|
|
49
|
+
"@stream-io/audio-filters-web": "^0.8.1",
|
|
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",
|