@stream-io/video-client 1.57.0 → 1.58.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 +13 -0
- package/dist/e2ee-worker.browser.es.js +1342 -0
- package/dist/e2ee-worker.browser.es.js.map +1 -0
- package/dist/index.browser.es.js +831 -55
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +875 -54
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.es.js +864 -55
- package/dist/index.es.js.map +1 -1
- package/dist/src/Call.d.ts +52 -6
- package/dist/src/coordinator/connection/connection.d.ts +1 -1
- package/dist/src/devices/CameraManager.d.ts +6 -0
- package/dist/src/devices/DeviceManager.d.ts +1 -0
- package/dist/src/devices/MicrophoneManager.d.ts +6 -0
- package/dist/src/devices/SpeakerManager.d.ts +2 -1
- package/dist/src/events/participant.d.ts +10 -3
- package/dist/src/gen/coordinator/index.d.ts +1363 -243
- package/dist/src/gen/video/sfu/models/models.d.ts +8 -0
- package/dist/src/helpers/TypedEventEmitter.d.ts +23 -0
- package/dist/src/helpers/ensureExhausted.d.ts +1 -1
- package/dist/src/permissions/PermissionsContext.d.ts +2 -2
- package/dist/src/rtc/BasePeerConnection.d.ts +3 -1
- package/dist/src/rtc/e2ee/E2EEManager.d.ts +12 -0
- package/dist/src/rtc/e2ee/EncryptionManager.d.ts +148 -0
- package/dist/src/rtc/e2ee/e2ee-worker.d.ts +25 -0
- package/dist/src/rtc/e2ee/events.d.ts +163 -0
- package/dist/src/rtc/e2ee/transformSupport.d.ts +21 -0
- package/dist/src/rtc/helpers/rtcConfiguration.d.ts +2 -2
- package/dist/src/rtc/index.d.ts +1 -0
- package/dist/src/rtc/mediaEngine.d.ts +23 -0
- package/dist/src/rtc/types.d.ts +2 -0
- package/dist/src/store/CallState.d.ts +21 -0
- package/dist/src/types.d.ts +15 -6
- package/index.ts +3 -0
- package/package.json +1 -1
- package/src/Call.ts +160 -26
- package/src/__tests__/Call.test.ts +15 -0
- package/src/coordinator/connection/connection.ts +6 -3
- package/src/devices/AudioDeviceManager.ts +6 -0
- package/src/devices/CameraManager.ts +51 -4
- package/src/devices/DeviceManager.ts +17 -0
- package/src/devices/MicrophoneManager.ts +55 -5
- package/src/devices/ScreenShareManager.ts +3 -0
- package/src/devices/SpeakerManager.ts +42 -12
- package/src/devices/__tests__/MicrophoneManagerRN.test.ts +1 -20
- package/src/devices/__tests__/SpeakerManager.test.ts +138 -42
- package/src/devices/__tests__/mocks.ts +36 -3
- package/src/events/__tests__/participant.test.ts +134 -1
- package/src/events/callEventHandlers.ts +9 -3
- package/src/events/participant.ts +42 -7
- package/src/gen/coordinator/index.ts +1384 -244
- package/src/gen/video/sfu/models/models.ts +15 -0
- package/src/helpers/TypedEventEmitter.ts +71 -0
- package/src/helpers/__tests__/TypedEventEmitter.test.ts +133 -0
- package/src/helpers/ensureExhausted.ts +4 -2
- package/src/permissions/PermissionsContext.ts +10 -5
- package/src/rtc/BasePeerConnection.ts +12 -1
- package/src/rtc/Publisher.ts +8 -0
- package/src/rtc/Subscriber.ts +5 -0
- package/src/rtc/__tests__/Publisher.test.ts +101 -0
- package/src/rtc/__tests__/Subscriber.test.ts +89 -0
- package/src/rtc/__tests__/mocks/webrtc.mocks.ts +31 -0
- package/src/rtc/e2ee/E2EEManager.ts +12 -0
- package/src/rtc/e2ee/EncryptionManager.ts +336 -0
- package/src/rtc/e2ee/SPEC.md +586 -0
- package/src/rtc/e2ee/__tests__/E2EEManager.contract.test.ts +39 -0
- package/src/rtc/e2ee/__tests__/EncryptionManager.test.ts +490 -0
- package/src/rtc/e2ee/__tests__/codec.test.ts +247 -0
- package/src/rtc/e2ee/__tests__/conformance.test.ts +184 -0
- package/src/rtc/e2ee/__tests__/failureTracker.test.ts +45 -0
- package/src/rtc/e2ee/__tests__/frameCounter.test.ts +90 -0
- package/src/rtc/e2ee/__tests__/keyStore.test.ts +221 -0
- package/src/rtc/e2ee/__tests__/notifications.test.ts +166 -0
- package/src/rtc/e2ee/__tests__/perf.test.ts +139 -0
- package/src/rtc/e2ee/__tests__/queue.test.ts +61 -0
- package/src/rtc/e2ee/__tests__/replayWindow.test.ts +133 -0
- package/src/rtc/e2ee/__tests__/trailer.test.ts +143 -0
- package/src/rtc/e2ee/__tests__/transform-pipeline.test.ts +839 -0
- package/src/rtc/e2ee/__tests__/transformSupport.test.ts +65 -0
- package/src/rtc/e2ee/e2ee-worker/codec.ts +220 -0
- package/src/rtc/e2ee/e2ee-worker/constants.ts +47 -0
- package/src/rtc/e2ee/e2ee-worker/decode.ts +159 -0
- package/src/rtc/e2ee/e2ee-worker/e2ee-worker-impl.ts +137 -0
- package/src/rtc/e2ee/e2ee-worker/encode.ts +147 -0
- package/src/rtc/e2ee/e2ee-worker/failureTracker.ts +26 -0
- package/src/rtc/e2ee/e2ee-worker/frameCounter.ts +37 -0
- package/src/rtc/e2ee/e2ee-worker/keyStore.ts +211 -0
- package/src/rtc/e2ee/e2ee-worker/notifications.ts +190 -0
- package/src/rtc/e2ee/e2ee-worker/perf.ts +129 -0
- package/src/rtc/e2ee/e2ee-worker/queue.ts +12 -0
- package/src/rtc/e2ee/e2ee-worker/replayWindow.ts +131 -0
- package/src/rtc/e2ee/e2ee-worker/trailer.ts +155 -0
- package/src/rtc/e2ee/e2ee-worker/tsconfig.json +8 -0
- package/src/rtc/e2ee/e2ee-worker/types.ts +29 -0
- package/src/rtc/e2ee/e2ee-worker.ts +27 -0
- package/src/rtc/e2ee/events.ts +179 -0
- package/src/rtc/e2ee/transformSupport.ts +35 -0
- package/src/rtc/helpers/rtcConfiguration.ts +4 -2
- package/src/rtc/index.ts +1 -0
- package/src/rtc/mediaEngine.ts +44 -0
- package/src/rtc/types.ts +2 -0
- package/src/store/CallState.ts +33 -1
- package/src/store/__tests__/CallState.test.ts +82 -1
- package/src/types.ts +23 -5
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { isChrome } from '../../helpers/browsers';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Detection and selection policy for the two WebRTC Encoded Transform APIs.
|
|
5
|
+
* Internal: which one the SDK attaches is an RTC-layer detail. Consumers want
|
|
6
|
+
* `EncryptionManager.isSupported` instead.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Chrome only, and the reason an RTCPeerConnection carrying E2EE needs the
|
|
11
|
+
* non-standard `encodedInsertableStreams` flag.
|
|
12
|
+
*/
|
|
13
|
+
export const hasInsertableStreams = (): boolean =>
|
|
14
|
+
typeof RTCRtpSender !== 'undefined' &&
|
|
15
|
+
'createEncodedStreams' in RTCRtpSender.prototype;
|
|
16
|
+
|
|
17
|
+
/** Whether the standard `RTCRtpScriptTransform` API exists. */
|
|
18
|
+
export const hasScriptTransform = (): boolean =>
|
|
19
|
+
typeof RTCRtpScriptTransform !== 'undefined';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Which Encoded Transform API to attach E2EE with here.
|
|
23
|
+
*
|
|
24
|
+
* - `'insertable'`: legacy Insertable Streams. Used on Chrome, where
|
|
25
|
+
* `RTCRtpScriptTransform` is still unreliable for E2EE.
|
|
26
|
+
* - `'script'`: the standard API. Used everywhere else.
|
|
27
|
+
* - `undefined`: neither exists, so E2EE cannot run.
|
|
28
|
+
*/
|
|
29
|
+
export const preferredTransform = (): 'script' | 'insertable' | undefined => {
|
|
30
|
+
const insertable = hasInsertableStreams();
|
|
31
|
+
// Chrome's RTCRtpScriptTransform is still unreliable for E2EE.
|
|
32
|
+
if (isChrome() && insertable) return 'insertable';
|
|
33
|
+
if (hasScriptTransform()) return 'script';
|
|
34
|
+
return insertable ? 'insertable' : undefined;
|
|
35
|
+
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ICEServerResponse } from '../../gen/coordinator';
|
|
2
2
|
|
|
3
|
-
export const toRtcConfiguration = (
|
|
3
|
+
export const toRtcConfiguration = (
|
|
4
|
+
config: ICEServerResponse[],
|
|
5
|
+
): RTCConfiguration => {
|
|
4
6
|
return {
|
|
5
7
|
bundlePolicy: 'max-bundle',
|
|
6
8
|
iceServers: config.map((ice) => ({
|
package/src/rtc/index.ts
CHANGED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A per-call media engine. On React Native it owns the call's native
|
|
3
|
+
* `PeerConnectionFactory` (built with the call's audio configuration); on web it
|
|
4
|
+
* is a no-op. Capture (`getUserMedia`/`getDisplayMedia`) and peer-connection creation
|
|
5
|
+
* always go through the WebRTC globals, which resolve to this factory while it
|
|
6
|
+
* is the live call factory — so the engine only needs to manage its lifecycle.
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export interface CallMediaEngine {
|
|
11
|
+
dispose(): Promise<boolean>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Creates a per-call {@link CallMediaEngine}. Registered once at SDK startup
|
|
16
|
+
* via {@link setCallMediaEngineProvider}. May return the engine synchronously
|
|
17
|
+
* (the default globals engine) or asynchronously (React Native, where allocating
|
|
18
|
+
* the native per-call factory is an async bridge call).
|
|
19
|
+
*
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
export type CallMediaEngineProvider = () =>
|
|
23
|
+
CallMediaEngine | Promise<CallMediaEngine>;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The default engine: a thin, stateless wrapper over the WebRTC globals.
|
|
27
|
+
*/
|
|
28
|
+
const defaultGlobalsEngine: CallMediaEngine = {
|
|
29
|
+
dispose: () => Promise.resolve(true),
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const defaultGlobalsEngineProvider: CallMediaEngineProvider = () =>
|
|
33
|
+
defaultGlobalsEngine;
|
|
34
|
+
|
|
35
|
+
let provider: CallMediaEngineProvider = defaultGlobalsEngineProvider;
|
|
36
|
+
|
|
37
|
+
export const setCallMediaEngineProvider = (
|
|
38
|
+
newProvider: CallMediaEngineProvider,
|
|
39
|
+
): void => {
|
|
40
|
+
provider = newProvider;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const getCallMediaEngineProvider = (): CallMediaEngineProvider =>
|
|
44
|
+
provider;
|
package/src/rtc/types.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { CallState } from '../store';
|
|
|
10
10
|
import { Dispatcher } from './Dispatcher';
|
|
11
11
|
import type { OptimalVideoLayer } from './layers';
|
|
12
12
|
import type { ClientPublishOptions } from '../types';
|
|
13
|
+
import type { E2EEManager } from './e2ee/E2EEManager';
|
|
13
14
|
import type { VideoSender } from '../gen/video/sfu/event/events';
|
|
14
15
|
|
|
15
16
|
/**
|
|
@@ -102,6 +103,7 @@ export type BasePeerConnectionOpts = {
|
|
|
102
103
|
iceRestartDelay?: number;
|
|
103
104
|
clientPublishOptions?: ClientPublishOptions;
|
|
104
105
|
statsTimestampDriftThresholdMs?: number;
|
|
106
|
+
e2ee?: E2EEManager;
|
|
105
107
|
};
|
|
106
108
|
|
|
107
109
|
export type TrackPublishOptions = {
|
package/src/store/CallState.ts
CHANGED
|
@@ -74,6 +74,7 @@ type OrphanedTrack = {
|
|
|
74
74
|
trackLookupPrefix: string;
|
|
75
75
|
trackType: TrackType;
|
|
76
76
|
track: MediaStream;
|
|
77
|
+
receiver?: RTCRtpReceiver;
|
|
77
78
|
};
|
|
78
79
|
|
|
79
80
|
/**
|
|
@@ -108,6 +109,7 @@ export class CallState {
|
|
|
108
109
|
>(undefined);
|
|
109
110
|
private transcribingSubject = new BehaviorSubject<boolean>(false);
|
|
110
111
|
private captioningSubject = new BehaviorSubject<boolean>(false);
|
|
112
|
+
private e2eeEnabledSubject = new BehaviorSubject<boolean>(false);
|
|
111
113
|
private endedBySubject = new BehaviorSubject<UserResponse | undefined>(
|
|
112
114
|
undefined,
|
|
113
115
|
);
|
|
@@ -311,6 +313,12 @@ export class CallState {
|
|
|
311
313
|
*/
|
|
312
314
|
captioning$: Observable<boolean>;
|
|
313
315
|
|
|
316
|
+
/**
|
|
317
|
+
* Whether end-to-end encryption is active for this call, as reported by the
|
|
318
|
+
* SFU in the join response.
|
|
319
|
+
*/
|
|
320
|
+
e2eeEnabled$: Observable<boolean>;
|
|
321
|
+
|
|
314
322
|
/**
|
|
315
323
|
* Will provide the user who ended this call.
|
|
316
324
|
*/
|
|
@@ -467,6 +475,7 @@ export class CallState {
|
|
|
467
475
|
this.rawRecording$ = duc(this.rawRecordingSubject);
|
|
468
476
|
this.transcribing$ = duc(this.transcribingSubject);
|
|
469
477
|
this.captioning$ = duc(this.captioningSubject);
|
|
478
|
+
this.e2eeEnabled$ = duc(this.e2eeEnabledSubject);
|
|
470
479
|
|
|
471
480
|
this.eventHandlers = {
|
|
472
481
|
// these events are not updating the call state:
|
|
@@ -574,6 +583,7 @@ export class CallState {
|
|
|
574
583
|
clearTimeout(taskId);
|
|
575
584
|
this.closedCaptionsTasks.delete(ccKey);
|
|
576
585
|
}
|
|
586
|
+
this.removeAllOrphanedTracks();
|
|
577
587
|
};
|
|
578
588
|
|
|
579
589
|
/**
|
|
@@ -973,6 +983,13 @@ export class CallState {
|
|
|
973
983
|
return this.getCurrentValue(this.transcribing$);
|
|
974
984
|
}
|
|
975
985
|
|
|
986
|
+
/**
|
|
987
|
+
* Whether end-to-end encryption is active for this call.
|
|
988
|
+
*/
|
|
989
|
+
get e2eeEnabled() {
|
|
990
|
+
return this.getCurrentValue(this.e2eeEnabled$);
|
|
991
|
+
}
|
|
992
|
+
|
|
976
993
|
/**
|
|
977
994
|
* Will provide the user who ended this call.
|
|
978
995
|
*/
|
|
@@ -1249,6 +1266,19 @@ export class CallState {
|
|
|
1249
1266
|
this.orphanedTracks = this.orphanedTracks.filter((o) => o.id !== id);
|
|
1250
1267
|
};
|
|
1251
1268
|
|
|
1269
|
+
/**
|
|
1270
|
+
* Drops every orphaned track. Call this when the peer connections that own
|
|
1271
|
+
* the stored receivers go away (full leave, reconnect, or migration):
|
|
1272
|
+
* `pc.close()` does not raise the track `ended` event, so the per-track
|
|
1273
|
+
* cleanup never fires and the receivers + their closed PCs would otherwise
|
|
1274
|
+
* leak for the call's lifetime.
|
|
1275
|
+
*
|
|
1276
|
+
* @internal
|
|
1277
|
+
*/
|
|
1278
|
+
removeAllOrphanedTracks = () => {
|
|
1279
|
+
this.orphanedTracks = [];
|
|
1280
|
+
};
|
|
1281
|
+
|
|
1252
1282
|
/**
|
|
1253
1283
|
* Takes all orphaned tracks with the given track lookup prefix.
|
|
1254
1284
|
* All orphaned tracks with the given track lookup prefix are removed from the call state.
|
|
@@ -1336,7 +1366,8 @@ export class CallState {
|
|
|
1336
1366
|
currentSessionId: string,
|
|
1337
1367
|
reconnectDetails?: ReconnectDetails,
|
|
1338
1368
|
) => {
|
|
1339
|
-
const { participants, participantCount, startedAt, pins } =
|
|
1369
|
+
const { participants, participantCount, startedAt, pins, e2EeEnabled } =
|
|
1370
|
+
callState;
|
|
1340
1371
|
const localPublishedTracks =
|
|
1341
1372
|
reconnectDetails?.announcedTracks.map((t) => t.trackType) ?? [];
|
|
1342
1373
|
this.setParticipants(() => {
|
|
@@ -1365,6 +1396,7 @@ export class CallState {
|
|
|
1365
1396
|
this.setAnonymousParticipantCount(participantCount?.anonymous || 0);
|
|
1366
1397
|
this.setStartedAt(startedAt ? Timestamp.toDate(startedAt) : new Date());
|
|
1367
1398
|
this.setServerSidePins(pins);
|
|
1399
|
+
this.setCurrentValue(this.e2eeEnabledSubject, e2EeEnabled);
|
|
1368
1400
|
};
|
|
1369
1401
|
|
|
1370
1402
|
private updateFromMemberRemoved = (event: CallMemberRemovedEvent) => {
|
|
@@ -5,7 +5,10 @@ import { fromPartial } from '@total-typescript/shoehorn';
|
|
|
5
5
|
import { StreamVideoParticipant, VisibilityState } from '../../types';
|
|
6
6
|
import { CallingState } from '../CallingState';
|
|
7
7
|
import { CallState } from '../CallState';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
type CallState as SfuCallState,
|
|
10
|
+
TrackType,
|
|
11
|
+
} from '../../gen/video/sfu/models/models';
|
|
9
12
|
import {
|
|
10
13
|
combineComparators,
|
|
11
14
|
conditional,
|
|
@@ -387,6 +390,48 @@ describe('CallState', () => {
|
|
|
387
390
|
});
|
|
388
391
|
});
|
|
389
392
|
|
|
393
|
+
describe('e2ee', () => {
|
|
394
|
+
const sfuCallState = (e2EeEnabled: boolean) =>
|
|
395
|
+
fromPartial<SfuCallState>({
|
|
396
|
+
participants: [],
|
|
397
|
+
pins: [],
|
|
398
|
+
e2EeEnabled,
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
it('is disabled until the SFU reports otherwise', () => {
|
|
402
|
+
const state = new CallState();
|
|
403
|
+
expect(state.e2eeEnabled).toBe(false);
|
|
404
|
+
|
|
405
|
+
state.updateFromSfuCallState(sfuCallState(false), 'session-id');
|
|
406
|
+
expect(state.e2eeEnabled).toBe(false);
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
it('is enabled when the SFU call state says so', () => {
|
|
410
|
+
const state = new CallState();
|
|
411
|
+
state.updateFromSfuCallState(sfuCallState(true), 'session-id');
|
|
412
|
+
expect(state.e2eeEnabled).toBe(true);
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
it('follows the SFU across a rejoin into a plain call', () => {
|
|
416
|
+
const state = new CallState();
|
|
417
|
+
state.updateFromSfuCallState(sfuCallState(true), 'session-id');
|
|
418
|
+
state.updateFromSfuCallState(sfuCallState(false), 'session-id');
|
|
419
|
+
expect(state.e2eeEnabled).toBe(false);
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
it(`doesn't emit when the value didn't change`, () => {
|
|
423
|
+
const state = new CallState();
|
|
424
|
+
const listener = vi.fn();
|
|
425
|
+
state.e2eeEnabled$.subscribe(listener);
|
|
426
|
+
expect(listener).toHaveBeenCalledTimes(1); // initial value
|
|
427
|
+
|
|
428
|
+
state.updateFromSfuCallState(sfuCallState(true), 'session-id');
|
|
429
|
+
state.updateFromSfuCallState(sfuCallState(true), 'session-id');
|
|
430
|
+
expect(listener).toHaveBeenCalledTimes(2);
|
|
431
|
+
expect(listener).toHaveBeenLastCalledWith(true);
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
|
|
390
435
|
describe('events', () => {
|
|
391
436
|
describe('call.live and backstage events', () => {
|
|
392
437
|
it('handles call.live_started events', () => {
|
|
@@ -1291,6 +1336,42 @@ describe('CallState', () => {
|
|
|
1291
1336
|
state.removeOrphanedTrack(id);
|
|
1292
1337
|
expect(state['orphanedTracks'].length).toBe(0);
|
|
1293
1338
|
});
|
|
1339
|
+
|
|
1340
|
+
it('removes all orphaned tracks at once', () => {
|
|
1341
|
+
const state = new CallState();
|
|
1342
|
+
state.registerOrphanedTrack({
|
|
1343
|
+
id: 'a',
|
|
1344
|
+
track: new MediaStream(),
|
|
1345
|
+
trackLookupPrefix: '1',
|
|
1346
|
+
trackType: TrackType.VIDEO,
|
|
1347
|
+
});
|
|
1348
|
+
state.registerOrphanedTrack({
|
|
1349
|
+
id: 'b',
|
|
1350
|
+
track: new MediaStream(),
|
|
1351
|
+
trackLookupPrefix: '2',
|
|
1352
|
+
trackType: TrackType.AUDIO,
|
|
1353
|
+
});
|
|
1354
|
+
expect(state['orphanedTracks'].length).toBe(2);
|
|
1355
|
+
state.removeAllOrphanedTracks();
|
|
1356
|
+
expect(state['orphanedTracks'].length).toBe(0);
|
|
1357
|
+
});
|
|
1358
|
+
|
|
1359
|
+
it('purges orphaned tracks on dispose (no receiver/PC leak)', () => {
|
|
1360
|
+
// Orphaned tracks can hold an RTCRtpReceiver tied to a now-closed peer
|
|
1361
|
+
// connection; pc.close() does not raise the track `ended` event, so they
|
|
1362
|
+
// are never purged otherwise and leak for the call's lifetime (finding
|
|
1363
|
+
// 15).
|
|
1364
|
+
const state = new CallState();
|
|
1365
|
+
state.registerOrphanedTrack({
|
|
1366
|
+
id: '123:TRACK_TYPE_VIDEO',
|
|
1367
|
+
track: new MediaStream(),
|
|
1368
|
+
trackLookupPrefix: '123',
|
|
1369
|
+
trackType: TrackType.VIDEO,
|
|
1370
|
+
});
|
|
1371
|
+
expect(state['orphanedTracks'].length).toBe(1);
|
|
1372
|
+
state.dispose();
|
|
1373
|
+
expect(state['orphanedTracks'].length).toBe(0);
|
|
1374
|
+
});
|
|
1294
1375
|
});
|
|
1295
1376
|
|
|
1296
1377
|
describe('closed captions', () => {
|
package/src/types.ts
CHANGED
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
JoinCallRequest,
|
|
10
10
|
MemberResponse,
|
|
11
11
|
OwnCapability,
|
|
12
|
-
|
|
12
|
+
VideoReactionResponse,
|
|
13
13
|
StartRecordingRequest,
|
|
14
14
|
StartRecordingResponse,
|
|
15
15
|
} from './gen/coordinator';
|
|
@@ -27,7 +27,7 @@ import { AxiosError } from 'axios';
|
|
|
27
27
|
import type { Call } from './Call';
|
|
28
28
|
|
|
29
29
|
export type StreamReaction = Pick<
|
|
30
|
-
|
|
30
|
+
VideoReactionResponse,
|
|
31
31
|
'type' | 'emoji_code' | 'custom'
|
|
32
32
|
>;
|
|
33
33
|
|
|
@@ -421,9 +421,20 @@ type StreamRNVideoSDKCallManagerRingingParams = {
|
|
|
421
421
|
|
|
422
422
|
type StreamRNVideoSDKCallManagerSetupParams =
|
|
423
423
|
StreamRNVideoSDKCallManagerRingingParams & {
|
|
424
|
+
cid: string;
|
|
424
425
|
defaultDevice: AudioSettingsRequestDefaultDeviceEnum;
|
|
425
426
|
};
|
|
426
427
|
|
|
428
|
+
type StreamRNVideoSDKCallManagerStartParams =
|
|
429
|
+
StreamRNVideoSDKCallManagerRingingParams & {
|
|
430
|
+
cid: string;
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
type StreamRNVideoSDKCallManagerStopParams =
|
|
434
|
+
StreamRNVideoSDKCallManagerRingingParams & {
|
|
435
|
+
shouldStopCallManager: boolean;
|
|
436
|
+
};
|
|
437
|
+
|
|
427
438
|
type StreamRNVideoSDKEndCallReason =
|
|
428
439
|
/** Call ended by the local user (e.g., hanging up). */
|
|
429
440
|
| 'local'
|
|
@@ -453,6 +464,8 @@ type StreamRNVideoSDKCallingX = {
|
|
|
453
464
|
reason?: StreamRNVideoSDKEndCallReason,
|
|
454
465
|
) => Promise<void>;
|
|
455
466
|
registerOutgoingCall: (call: Call) => Promise<void>;
|
|
467
|
+
wireAudioEngineSubscription: () => void;
|
|
468
|
+
unwireAudioEngineSubscription: () => void;
|
|
456
469
|
};
|
|
457
470
|
|
|
458
471
|
export type StreamRNVideoSDKGlobals = {
|
|
@@ -464,6 +477,7 @@ export type StreamRNVideoSDKGlobals = {
|
|
|
464
477
|
setup({
|
|
465
478
|
defaultDevice,
|
|
466
479
|
isRingingTypeCall,
|
|
480
|
+
cid,
|
|
467
481
|
}: StreamRNVideoSDKCallManagerSetupParams): void;
|
|
468
482
|
|
|
469
483
|
/**
|
|
@@ -471,12 +485,16 @@ export type StreamRNVideoSDKGlobals = {
|
|
|
471
485
|
*/
|
|
472
486
|
start({
|
|
473
487
|
isRingingTypeCall,
|
|
474
|
-
|
|
488
|
+
cid,
|
|
489
|
+
}: StreamRNVideoSDKCallManagerStartParams): void;
|
|
475
490
|
|
|
476
491
|
/**
|
|
477
492
|
* Stops the in call manager.
|
|
478
493
|
*/
|
|
479
|
-
stop({
|
|
494
|
+
stop({
|
|
495
|
+
isRingingTypeCall,
|
|
496
|
+
shouldStopCallManager,
|
|
497
|
+
}: StreamRNVideoSDKCallManagerStopParams): void;
|
|
480
498
|
|
|
481
499
|
/**
|
|
482
500
|
* iOS-only. Keeps the audio engine's microphone-input (voice-processing)
|
|
@@ -514,5 +532,5 @@ declare global {
|
|
|
514
532
|
/**
|
|
515
533
|
* The options to pass to {@link Call.join} method.
|
|
516
534
|
*/
|
|
517
|
-
export type JoinCallData = Omit<JoinCallRequest, 'location'>;
|
|
535
|
+
export type JoinCallData = Omit<JoinCallRequest, 'location' | 'e2ee'>;
|
|
518
536
|
export { AxiosError };
|