@pexip/media 21.0.0 → 22.1.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 +66 -0
- package/README.md +20 -32
- package/api-docs/README.mdx +20 -35
- package/api-docs/functions/applyContentHint.mdx +1 -1
- package/api-docs/functions/createAudioMixingProcess.mdx +1 -1
- package/api-docs/functions/createGetDisplayMedia.mdx +3 -3
- package/api-docs/functions/createMediaSignal.mdx +2 -2
- package/api-docs/functions/createMediaSignals.mdx +5 -3
- package/api-docs/functions/deriveInitialPermissionStatus.mdx +4 -2
- package/api-docs/functions/getPermissionStatus.mdx +31 -11
- package/api-docs/functions/toDeniedDevices.mdx +3 -1
- package/api-docs/interfaces/AudioDetectionSignals.mdx +2 -2
- package/api-docs/interfaces/AudioSignalDetectionOptions.mdx +1 -1
- package/api-docs/interfaces/ExtendedMediaTrackSettings.mdx +11 -7
- package/api-docs/interfaces/Media.mdx +4 -4
- package/api-docs/interfaces/MediaAttributes.mdx +2 -2
- package/api-docs/interfaces/MediaChangesSignals.mdx +5 -5
- package/api-docs/interfaces/MediaController.mdx +3 -3
- package/api-docs/interfaces/MediaInit.mdx +1 -1
- package/api-docs/interfaces/MediaOptions.mdx +3 -3
- package/api-docs/interfaces/MediaTrack.mdx +3 -3
- package/api-docs/interfaces/MediaTrackInit.mdx +12 -10
- package/api-docs/interfaces/PreviewControllerProps.mdx +1 -0
- package/api-docs/interfaces/PreviewEventHandler.mdx +7 -7
- package/api-docs/interfaces/PreviewStreamController.mdx +10 -10
- package/api-docs/interfaces/PreviewStreamParams.mdx +7 -6
- package/api-docs/interfaces/VoiceActivityDetectionOptions.mdx +1 -1
- package/api-docs/type-aliases/GetUserMediaProcess.mdx +4 -2
- package/api-docs/type-aliases/Process.mdx +3 -1
- package/api-docs/variables/internalSignals.mdx +1 -1
- package/dist/audioMixingProcessor.d.ts +4 -2
- package/dist/audioMixingProcessor.js +22 -12
- package/dist/audioProcessor.d.ts +7 -2
- package/dist/audioProcessor.js +25 -20
- package/dist/logger.d.ts +0 -2
- package/dist/logger.js +0 -16
- package/dist/media.js +5 -5
- package/dist/previewController.d.ts +3 -1
- package/dist/previewController.js +42 -9
- package/dist/typeGuard.d.ts +1 -2
- package/dist/typeGuard.js +0 -3
- package/dist/types.d.ts +7 -14
- package/dist/utils.js +15 -5
- package/dist/videoProcessor.d.ts +40 -22
- package/dist/videoProcessor.js +227 -247
- package/package.json +11 -11
- package/api-docs/functions/isVideoStreamTrackProcessorAPIs.mdx +0 -13
- package/api-docs/type-aliases/Segmenters.mdx +0 -3
- package/api-docs/type-aliases/VideoStreamTrackProcessorAPIs.mdx +0 -7
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
## Extends
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
```ts
|
|
4
|
+
- Partial<Omit<MediaTrack, "mute">>
|
|
5
|
+
```
|
|
4
6
|
|
|
5
7
|
## Properties
|
|
6
8
|
|
|
@@ -14,16 +16,16 @@
|
|
|
14
16
|
| <a id="track"></a> `track?` | `readonly` | `MediaStreamTrack` | The MediaStreamTrack object representing the track **See** https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack | - | [`MediaTrack`](MediaTrack.mdx).[`track`](MediaTrack.mdx#track) |
|
|
15
17
|
| <a id="muted"></a> `muted?` | `public` | `boolean` | The current mute state of the track. `undefined` means the track is not available | - | [`MediaTrack`](MediaTrack.mdx).[`muted`](MediaTrack.mdx#muted) |
|
|
16
18
|
| <a id="source"></a> `source?` | `readonly` | [`MediaTrack`](MediaTrack.mdx) | The source track that it is originated from | - | [`MediaTrack`](MediaTrack.mdx).[`source`](MediaTrack.mdx#source) |
|
|
17
|
-
| <a id="getsettings"></a> `getSettings?` | `public` | ()
|
|
18
|
-
| <a id="getconstraints"></a> `getConstraints?` | `public` | () =>
|
|
19
|
-
| <a id="applyconstraints"></a> `applyConstraints?` | `public` | (
|
|
20
|
-
| <a id="release"></a> `release?` | `public` | () =>
|
|
21
|
-
| <a id="clone"></a> `clone?` | `public` | (`signals?`, `label?`)
|
|
22
|
-
| <a id="tojson"></a> `toJSON?` | `public` | () =>
|
|
23
|
-
| <a id="kind"></a> `kind` | `public` | `"audioinput"
|
|
24
|
-
| <a id="input"></a> `input` | `public` | `MediaDeviceInfoLike
|
|
19
|
+
| <a id="getsettings"></a> `getSettings?` | `public` | () =\> [`ExtendedMediaTrackSettings`](ExtendedMediaTrackSettings.mdx) | - | - | [`MediaTrack`](MediaTrack.mdx).[`getSettings`](MediaTrack.mdx#getsettings) |
|
|
20
|
+
| <a id="getconstraints"></a> `getConstraints?` | `public` | `() => InputDeviceConstraint` | - | - | [`MediaTrack`](MediaTrack.mdx).[`getConstraints`](MediaTrack.mdx#getconstraints) |
|
|
21
|
+
| <a id="applyconstraints"></a> `applyConstraints?` | `public` | `(constraints) => Promise<void>` | - | - | [`MediaTrack`](MediaTrack.mdx).[`applyConstraints`](MediaTrack.mdx#applyconstraints) |
|
|
22
|
+
| <a id="release"></a> `release?` | `public` | `() => Promise<void>` | - | - | [`MediaTrack`](MediaTrack.mdx).[`release`](MediaTrack.mdx#release) |
|
|
23
|
+
| <a id="clone"></a> `clone?` | `public` | (`signals?`, `label?`) =\> [`MediaTrack`](MediaTrack.mdx) | - | - | [`MediaTrack`](MediaTrack.mdx).[`clone`](MediaTrack.mdx#clone) |
|
|
24
|
+
| <a id="tojson"></a> `toJSON?` | `public` | `() => unknown` | - | - | [`MediaTrack`](MediaTrack.mdx).[`toJSON`](MediaTrack.mdx#tojson) |
|
|
25
|
+
| <a id="kind"></a> `kind` | `public` | `"audioinput" \| "videoinput"` | - | [`MediaTrack`](MediaTrack.mdx).[`kind`](MediaTrack.mdx#kind) | - |
|
|
26
|
+
| <a id="input"></a> `input` | `public` | `MediaDeviceInfoLike \| undefined` | The `MediaDeviceInfo` object representing the device that the track is connected to. **See** https://developer.mozilla.org/en-US/docs/Web/API/MediaDeviceInfo | [`MediaTrack`](MediaTrack.mdx).[`input`](MediaTrack.mdx#input) | - |
|
|
25
27
|
| <a id="expectedinput"></a> `expectedInput?` | `public` | `MediaDeviceInfoLike` | The `MediaDeviceInfo` object representing the device that the track is expected to be connected to. **See** https://developer.mozilla.org/en-US/docs/Web/API/MediaDeviceInfo | [`MediaTrack`](MediaTrack.mdx).[`expectedInput`](MediaTrack.mdx#expectedinput) | - |
|
|
26
28
|
| <a id="constraints"></a> `constraints` | `public` | `InputDeviceConstraint` | - | - | - |
|
|
27
29
|
| <a id="overridemute"></a> `overrideMute?` | `public` | `boolean` | - | - | - |
|
|
28
30
|
| <a id="signals"></a> `signals?` | `public` | [`MediaSignals`](../type-aliases/MediaSignals.mdx) | - | - | - |
|
|
29
|
-
| <a id="mute"></a> `mute?` | `public` | (
|
|
31
|
+
| <a id="mute"></a> `mute?` | `public` | `(toMute, self, soft?) => void` | Overriding Mute the track | - | - |
|
|
@@ -12,3 +12,4 @@
|
|
|
12
12
|
| <a id="discardmedia"></a> `discardMedia` | `boolean` |
|
|
13
13
|
| <a id="initialized"></a> `initialized` | `boolean` |
|
|
14
14
|
| <a id="signals"></a> `signals` | [`MediaSignals`](../type-aliases/MediaSignals.mdx) |
|
|
15
|
+
| <a id="keepvideomuted"></a> `keepVideoMuted` | `boolean` |
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
| <a id="audioinputerror"></a> `audioInputError?` | `EventErrorCallback` |
|
|
10
10
|
| <a id="applychangeserror"></a> `applyChangesError?` | `EventErrorCallback` |
|
|
11
11
|
| <a id="revertchangeserror"></a> `revertChangesError?` | `EventErrorCallback` |
|
|
12
|
-
| <a id="audiomuted"></a> `audioMuted?` | `EventCallback
|
|
13
|
-
| <a id="audiosuspended"></a> `audioSuspended?` | `EventCallback
|
|
14
|
-
| <a id="updatingmain"></a> `updatingMain?` | `EventCallback
|
|
15
|
-
| <a id="updatingpreviewaudio"></a> `updatingPreviewAudio?` | `EventCallback
|
|
16
|
-
| <a id="updatingpreviewvideo"></a> `updatingPreviewVideo?` | `EventCallback
|
|
17
|
-
| <a id="videomuted"></a> `videoMuted?` | `EventCallback
|
|
18
|
-
| <a id="videosuspended"></a> `videoSuspended?` | `EventCallback
|
|
12
|
+
| <a id="audiomuted"></a> `audioMuted?` | `EventCallback<boolean \| undefined>` |
|
|
13
|
+
| <a id="audiosuspended"></a> `audioSuspended?` | `EventCallback<boolean \| undefined>` |
|
|
14
|
+
| <a id="updatingmain"></a> `updatingMain?` | `EventCallback<boolean>` |
|
|
15
|
+
| <a id="updatingpreviewaudio"></a> `updatingPreviewAudio?` | `EventCallback<boolean>` |
|
|
16
|
+
| <a id="updatingpreviewvideo"></a> `updatingPreviewVideo?` | `EventCallback<boolean>` |
|
|
17
|
+
| <a id="videomuted"></a> `videoMuted?` | `EventCallback<boolean \| undefined>` |
|
|
18
|
+
| <a id="videosuspended"></a> `videoSuspended?` | `EventCallback<boolean \| undefined>` |
|
|
19
19
|
| <a id="unsubscribemain"></a> `unsubscribeMain?` | [`Unsubscribe`](../type-aliases/Unsubscribe.mdx) |
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
| <a id="updatingmain"></a> `updatingMain` | `boolean` |
|
|
12
12
|
| <a id="updatingpreviewaudio"></a> `updatingPreviewAudio` | `boolean` |
|
|
13
13
|
| <a id="updatingpreviewvideo"></a> `updatingPreviewVideo` | `boolean` |
|
|
14
|
-
| <a id="cleanup"></a> `cleanup` | () =>
|
|
14
|
+
| <a id="cleanup"></a> `cleanup` | `() => Promise<void>` |
|
|
15
15
|
|
|
16
16
|
## Methods
|
|
17
17
|
|
|
@@ -83,7 +83,7 @@ applyChanges(force?): Promise<void>;
|
|
|
83
83
|
|
|
84
84
|
#### Returns
|
|
85
85
|
|
|
86
|
-
`Promise
|
|
86
|
+
`Promise<void>`
|
|
87
87
|
|
|
88
88
|
***
|
|
89
89
|
|
|
@@ -95,7 +95,7 @@ revertChanges(): Promise<void>;
|
|
|
95
95
|
|
|
96
96
|
#### Returns
|
|
97
97
|
|
|
98
|
-
`Promise
|
|
98
|
+
`Promise<void>`
|
|
99
99
|
|
|
100
100
|
***
|
|
101
101
|
|
|
@@ -163,7 +163,7 @@ onUpdatingPreviewAudio(callback): Unsubscribe;
|
|
|
163
163
|
|
|
164
164
|
| Parameter | Type |
|
|
165
165
|
| ------ | ------ |
|
|
166
|
-
| `callback` | `EventCallback
|
|
166
|
+
| `callback` | `EventCallback<boolean>` |
|
|
167
167
|
|
|
168
168
|
#### Returns
|
|
169
169
|
|
|
@@ -181,7 +181,7 @@ onUpdatingPreviewVideo(callback): Unsubscribe;
|
|
|
181
181
|
|
|
182
182
|
| Parameter | Type |
|
|
183
183
|
| ------ | ------ |
|
|
184
|
-
| `callback` | `EventCallback
|
|
184
|
+
| `callback` | `EventCallback<boolean>` |
|
|
185
185
|
|
|
186
186
|
#### Returns
|
|
187
187
|
|
|
@@ -199,7 +199,7 @@ onUpdatingMain(callback): Unsubscribe;
|
|
|
199
199
|
|
|
200
200
|
| Parameter | Type |
|
|
201
201
|
| ------ | ------ |
|
|
202
|
-
| `callback` | `EventCallback
|
|
202
|
+
| `callback` | `EventCallback<boolean>` |
|
|
203
203
|
|
|
204
204
|
#### Returns
|
|
205
205
|
|
|
@@ -289,7 +289,7 @@ onAudioMuted(callback): Unsubscribe;
|
|
|
289
289
|
|
|
290
290
|
| Parameter | Type |
|
|
291
291
|
| ------ | ------ |
|
|
292
|
-
| `callback` | `EventCallback
|
|
292
|
+
| `callback` | `EventCallback<boolean \| undefined>` |
|
|
293
293
|
|
|
294
294
|
#### Returns
|
|
295
295
|
|
|
@@ -307,7 +307,7 @@ onAudioSuspended(callback): Unsubscribe;
|
|
|
307
307
|
|
|
308
308
|
| Parameter | Type |
|
|
309
309
|
| ------ | ------ |
|
|
310
|
-
| `callback` | `EventCallback
|
|
310
|
+
| `callback` | `EventCallback<boolean \| undefined>` |
|
|
311
311
|
|
|
312
312
|
#### Returns
|
|
313
313
|
|
|
@@ -325,7 +325,7 @@ onVideoMuted(callback): Unsubscribe;
|
|
|
325
325
|
|
|
326
326
|
| Parameter | Type |
|
|
327
327
|
| ------ | ------ |
|
|
328
|
-
| `callback` | `EventCallback
|
|
328
|
+
| `callback` | `EventCallback<boolean \| undefined>` |
|
|
329
329
|
|
|
330
330
|
#### Returns
|
|
331
331
|
|
|
@@ -343,7 +343,7 @@ onVideoSuspended(callback): Unsubscribe;
|
|
|
343
343
|
|
|
344
344
|
| Parameter | Type |
|
|
345
345
|
| ------ | ------ |
|
|
346
|
-
| `callback` | `EventCallback
|
|
346
|
+
| `callback` | `EventCallback<boolean \| undefined>` |
|
|
347
347
|
|
|
348
348
|
#### Returns
|
|
349
349
|
|
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
| Property | Type | Description |
|
|
4
4
|
| ------ | ------ | ------ |
|
|
5
|
-
| <a id="getcurrentdevices"></a> `getCurrentDevices` | () =>
|
|
6
|
-
| <a id="getcurrentmedia"></a> `getCurrentMedia` | ()
|
|
7
|
-
| <a id="updatemainstream"></a> `updateMainStream` | (
|
|
5
|
+
| <a id="getcurrentdevices"></a> `getCurrentDevices` | `() => IndexedDevices` | - |
|
|
6
|
+
| <a id="getcurrentmedia"></a> `getCurrentMedia` | () =\> [`Media`](Media.mdx) \| `undefined` | - |
|
|
7
|
+
| <a id="updatemainstream"></a> `updateMainStream` | `(request) => Promise<void>` | - |
|
|
8
8
|
| <a id="mainmediasignal"></a> `mainMediaSignal` | `Signal`\<[`Media`](Media.mdx) \| `undefined`, [`Media`](Media.mdx) \| `undefined`\> | - |
|
|
9
9
|
| <a id="signals"></a> `signals` | [`MediaSignals`](../type-aliases/MediaSignals.mdx) | - |
|
|
10
|
-
| <a id="onended"></a> `onEnded?` | () =>
|
|
10
|
+
| <a id="onended"></a> `onEnded?` | `() => void` | - |
|
|
11
11
|
| <a id="fftsize"></a> `fftSize?` | `number` | - |
|
|
12
|
-
| <a id="queueoptions"></a> `queueOptions?` | `Partial
|
|
12
|
+
| <a id="queueoptions"></a> `queueOptions?` | `Partial<AsyncQueueOptions>` | - |
|
|
13
13
|
| <a id="audioprocessors"></a> `audioProcessors` | [`TrackProcessor`](../type-aliases/TrackProcessor.mdx)[] | - |
|
|
14
14
|
| <a id="videoprocessors"></a> `videoProcessors` | [`TrackProcessor`](../type-aliases/TrackProcessor.mdx)[] | - |
|
|
15
|
-
| <a id="getdefaultconstraints"></a> `getDefaultConstraints?` | () =>
|
|
15
|
+
| <a id="getdefaultconstraints"></a> `getDefaultConstraints?` | `() => object` | Pass default constraints to use with get media wrappers |
|
|
16
|
+
| <a id="stopvideotrackasmute"></a> `stopVideoTrackAsMute?` | `() => boolean` | - |
|
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
| Property | Type | Description |
|
|
4
4
|
| ------ | ------ | ------ |
|
|
5
5
|
| <a id="vadthrottlems"></a> `vadThrottleMS?` | `number` | Voice Activity Detection in millisecond |
|
|
6
|
-
| <a id="shoulddetectvoiceactivity"></a> `shouldDetectVoiceActivity` | () =>
|
|
6
|
+
| <a id="shoulddetectvoiceactivity"></a> `shouldDetectVoiceActivity` | `() => boolean` | Whether or not to detect voice activity |
|
|
@@ -9,11 +9,13 @@ type GetUserMediaProcess = (request) => Promise<Media>;
|
|
|
9
9
|
| `request` | \{ `constraints`: `MediaDeviceRequest`; `originalConstraints`: `MediaDeviceRequest`; `permission`: \{ `audio`: `PermissionState`; `video`: `PermissionState`; \}; `currentMedia`: [`Media`](../interfaces/Media.mdx) \| `undefined`; \} |
|
|
10
10
|
| `request.constraints` | `MediaDeviceRequest` |
|
|
11
11
|
| `request.originalConstraints` | `MediaDeviceRequest` |
|
|
12
|
-
| `request.permission` |
|
|
12
|
+
| `request.permission` | `{ audio: PermissionState; video: PermissionState; }` |
|
|
13
13
|
| `request.permission.audio` | `PermissionState` |
|
|
14
14
|
| `request.permission.video` | `PermissionState` |
|
|
15
15
|
| `request.currentMedia` | [`Media`](../interfaces/Media.mdx) \| `undefined` |
|
|
16
16
|
|
|
17
17
|
## Returns
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
```ts
|
|
20
|
+
Promise<Media>
|
|
21
|
+
```
|
|
@@ -7,8 +7,10 @@ interface AudioStreamProcessorProps {
|
|
|
7
7
|
displaySource?: AudioNodeInit<MediaStreamAudioSourceNode, MediaStreamAudioSourceNode>;
|
|
8
8
|
audioGraph?: AudioGraph;
|
|
9
9
|
}
|
|
10
|
-
declare const FEATURE_KEYS:
|
|
11
|
-
|
|
10
|
+
declare const FEATURE_KEYS: {
|
|
11
|
+
readonly mixWithAdditionalMedia: "boolean";
|
|
12
|
+
};
|
|
13
|
+
type FeaturePropKeys = keyof typeof FEATURE_KEYS;
|
|
12
14
|
type FeatureProps = Pick<AudioStreamProcessorProps, FeaturePropKeys>;
|
|
13
15
|
export declare const updateFeatureProps: (constraints: MediaDeviceRequest["audio"], props: FeatureProps) => FeatureProps;
|
|
14
16
|
/**
|
|
@@ -1,22 +1,32 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { extractConstraints } from '@pexip/media-control';
|
|
2
2
|
import { isEmpty, assert } from '@pexip/utils';
|
|
3
3
|
import { createAudioGraph, createAudioGraphProxy, createChannelMergerGraphNode, createStreamDestinationGraphNode, createStreamSourceGraphNode, resumeAudioOnUnmute, } from '@pexip/media-processor';
|
|
4
4
|
import { logger } from './logger';
|
|
5
5
|
import { createMediaTrack } from './utils';
|
|
6
6
|
import { PROCESSOR_LABELS } from './constants';
|
|
7
|
-
const FEATURE_KEYS =
|
|
8
|
-
const getAudioConstraints = extractConstraintsWithKeys(FEATURE_KEYS);
|
|
7
|
+
const FEATURE_KEYS = { mixWithAdditionalMedia: 'boolean' };
|
|
9
8
|
export const updateFeatureProps = (constraints, props) => {
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
const features = {};
|
|
10
|
+
if (constraints === undefined || typeof constraints === 'boolean') {
|
|
11
|
+
return features;
|
|
12
|
+
}
|
|
13
|
+
for (const k of Object.keys(constraints)) {
|
|
14
|
+
const key = k;
|
|
15
|
+
if (!FEATURE_KEYS[key]) {
|
|
16
|
+
continue;
|
|
17
17
|
}
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
switch (key) {
|
|
19
|
+
case 'mixWithAdditionalMedia': {
|
|
20
|
+
const [feature] = extractConstraints(key)(constraints);
|
|
21
|
+
if (feature !== undefined && props[key] !== feature) {
|
|
22
|
+
props[key] = feature;
|
|
23
|
+
features[key] = feature;
|
|
24
|
+
}
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return features;
|
|
20
30
|
};
|
|
21
31
|
/**
|
|
22
32
|
* Create an Audio Mixing Processor and will own the stream passed-in
|
package/dist/audioProcessor.d.ts
CHANGED
|
@@ -76,8 +76,13 @@ interface AudioStreamProcessorProps {
|
|
|
76
76
|
contentHint?: AudioContentHint;
|
|
77
77
|
audioGraph?: AudioGraph;
|
|
78
78
|
}
|
|
79
|
-
declare const FEATURE_KEYS:
|
|
80
|
-
|
|
79
|
+
declare const FEATURE_KEYS: {
|
|
80
|
+
readonly denoise: "boolean";
|
|
81
|
+
readonly vad: "boolean";
|
|
82
|
+
readonly asd: "boolean";
|
|
83
|
+
readonly contentHint: "string";
|
|
84
|
+
};
|
|
85
|
+
type FeaturePropKeys = keyof typeof FEATURE_KEYS;
|
|
81
86
|
type FeatureProps = Pick<AudioStreamProcessorProps, FeaturePropKeys>;
|
|
82
87
|
export declare const updateFeatureProps: (constraints: MediaDeviceRequest["audio"], props: FeatureProps) => FeatureProps;
|
|
83
88
|
/**
|
package/dist/audioProcessor.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { extractConstraints } from '@pexip/media-control';
|
|
2
2
|
import { createQueue, isEmpty, assert } from '@pexip/utils';
|
|
3
3
|
import { avg, createAnalyzerSubscribableGraphNode, createAudioGraph, createAudioGraphProxy, createAudioSignalDetector, createDenoiseWorkletGraphNode, createStreamDestinationGraphNode, createStreamSourceGraphNode, createVADetector, createVoiceDetectorFromProbability, createVoiceDetectorFromTimeData, } from '@pexip/media-processor';
|
|
4
4
|
import { PROCESSOR_LABELS } from './constants';
|
|
@@ -17,41 +17,46 @@ const fetchDenoiseWasm = async (denoiseWasm, wasmURL) => {
|
|
|
17
17
|
}
|
|
18
18
|
return await (await fetch(wasmURL)).arrayBuffer();
|
|
19
19
|
};
|
|
20
|
-
const FEATURE_KEYS =
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const getAudioConstraints = extractConstraintsWithKeys(FEATURE_KEYS);
|
|
20
|
+
const FEATURE_KEYS = {
|
|
21
|
+
denoise: 'boolean',
|
|
22
|
+
vad: 'boolean',
|
|
23
|
+
asd: 'boolean',
|
|
24
|
+
contentHint: 'string',
|
|
25
|
+
};
|
|
27
26
|
export const updateFeatureProps = (constraints, props) => {
|
|
28
|
-
const
|
|
29
|
-
|
|
27
|
+
const features = {};
|
|
28
|
+
if (constraints === undefined || typeof constraints === 'boolean') {
|
|
29
|
+
return features;
|
|
30
|
+
}
|
|
31
|
+
for (const k of Object.keys(constraints)) {
|
|
32
|
+
const key = k;
|
|
33
|
+
if (!FEATURE_KEYS[key]) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
30
36
|
switch (key) {
|
|
31
37
|
case 'contentHint': {
|
|
32
|
-
const [[feature] = []] =
|
|
38
|
+
const [[feature] = []] = extractConstraints(key)(constraints);
|
|
33
39
|
if (isAudioContentHint(feature) && props[key] !== feature) {
|
|
34
40
|
props[key] = feature;
|
|
35
|
-
|
|
36
|
-
return accm;
|
|
41
|
+
features[key] = feature;
|
|
37
42
|
}
|
|
38
|
-
|
|
43
|
+
break;
|
|
39
44
|
}
|
|
40
45
|
case 'denoise':
|
|
41
46
|
case 'asd':
|
|
42
47
|
case 'vad': {
|
|
43
|
-
const [feature] =
|
|
48
|
+
const [feature] = extractConstraints(key)(constraints);
|
|
44
49
|
if (feature !== undefined && props[key] !== feature) {
|
|
45
50
|
props[key] = feature;
|
|
46
|
-
|
|
47
|
-
return accm;
|
|
51
|
+
features[key] = feature;
|
|
48
52
|
}
|
|
49
|
-
|
|
53
|
+
break;
|
|
50
54
|
}
|
|
51
55
|
default:
|
|
52
|
-
|
|
56
|
+
break;
|
|
53
57
|
}
|
|
54
|
-
}
|
|
58
|
+
}
|
|
59
|
+
return features;
|
|
55
60
|
};
|
|
56
61
|
/**
|
|
57
62
|
* Create an Audio Stream Processor and will own the stream passed-in
|
package/dist/logger.d.ts
CHANGED
|
@@ -7,5 +7,3 @@ export declare function setLogger(newLogger: Logger): void;
|
|
|
7
7
|
* @param metaBase - The meta data which will always be included into the log
|
|
8
8
|
*/
|
|
9
9
|
export declare const createModuleLogger: (metaBase: unknown) => Logger;
|
|
10
|
-
export declare const createLogProxyHandler: <T extends object>(logger: Logger, name: string, scope: string) => ProxyHandler<T>;
|
|
11
|
-
export declare const proxyWithLog: (logger: Logger, scope: string) => <T extends object>(obj: T, name: string) => T;
|
package/dist/logger.js
CHANGED
|
@@ -23,19 +23,3 @@ export const createModuleLogger = (metaBase) => {
|
|
|
23
23
|
return log;
|
|
24
24
|
}, {});
|
|
25
25
|
};
|
|
26
|
-
export const createLogProxyHandler = (logger, name, scope) => {
|
|
27
|
-
return {
|
|
28
|
-
get: (target, p, receiver) => {
|
|
29
|
-
const value = Reflect.get(target, p, receiver);
|
|
30
|
-
logger.debug({ scope, name, prop: p, value }, `called get ${name}[${String(p)}]`);
|
|
31
|
-
return value;
|
|
32
|
-
},
|
|
33
|
-
set: (target, p, value, receiver) => {
|
|
34
|
-
logger.info({ scope, name, prop: p, value }, `called set ${name}[${String(p)}]`);
|
|
35
|
-
return Reflect.set(target, p, value, receiver);
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
};
|
|
39
|
-
export const proxyWithLog = (logger, scope) => (obj, name) => {
|
|
40
|
-
return new Proxy(obj, createLogProxyHandler(logger, name, scope));
|
|
41
|
-
};
|
package/dist/media.js
CHANGED
|
@@ -7,7 +7,7 @@ import { createGetUserMediaProcess, requestUserMediaWithRetry, } from './userMed
|
|
|
7
7
|
import { AUDIO_SETTINGS_KEYS, MIXING_SETTINGS_KEYS, PAN_TILT_ZOOM_SETTINGS_KEYS, VIDEO_SETTINGS_KEYS, buildMedia, createMediaProcessor, diffSettings, getDevicesChanges, getSettingsFromKeys, hasPtzFeature, isApplyingRenderEffect, mergeSettings, refineMediaConstraints, } from './utils';
|
|
8
8
|
import { getPermissionStatus, isRequestPermissionNeeded } from './status';
|
|
9
9
|
import { isMedia } from './typeGuard';
|
|
10
|
-
import { updateFeatureProps as getVideoFeatures } from './videoProcessor';
|
|
10
|
+
import { updateFeatureProps as getVideoFeatures, mapFeatureToSettings, mapSettingsToFeatures, } from './videoProcessor';
|
|
11
11
|
import { updateFeatureProps as getAudioFeatures } from './audioProcessor';
|
|
12
12
|
import { updateFeatureProps as getMixingFeatures } from './audioMixingProcessor';
|
|
13
13
|
import { GET_USER_MEDIA_TIMEOUT_MS, DEVICE_CHANGE_DEBOUNCE_TIMEOUT_MS, } from './constants';
|
|
@@ -59,7 +59,7 @@ export const createMediaUpdater = ({ getUserMedia, getCurrentDevices, shouldDisc
|
|
|
59
59
|
const defaultVideoSettings = getSettingsFromKeys(VIDEO_SETTINGS_KEYS, getDefaultConstraints?.().video);
|
|
60
60
|
const videoFeaturesChanged = defaultVideoSettings === false
|
|
61
61
|
? undefined
|
|
62
|
-
: diffSettings(VIDEO_SETTINGS_KEYS)(prevVideoSettings ?? defaultVideoSettings, videoFeatures);
|
|
62
|
+
: diffSettings(VIDEO_SETTINGS_KEYS)(prevVideoSettings ?? defaultVideoSettings, mapFeatureToSettings(videoFeatures));
|
|
63
63
|
const defaultMixingSettings = getSettingsFromKeys(MIXING_SETTINGS_KEYS, getDefaultConstraints?.().audio);
|
|
64
64
|
const mixingFeaturesChanged = defaultMixingSettings === false
|
|
65
65
|
? undefined
|
|
@@ -68,7 +68,7 @@ export const createMediaUpdater = ({ getUserMedia, getCurrentDevices, shouldDisc
|
|
|
68
68
|
const ptzFeaturesChanges = defaultPTZSettings === false
|
|
69
69
|
? undefined
|
|
70
70
|
: hasPtzFeature() &&
|
|
71
|
-
diffSettings(PAN_TILT_ZOOM_SETTINGS_KEYS)(prevVideoSettings ?? defaultPTZSettings, videoFeatures);
|
|
71
|
+
diffSettings(PAN_TILT_ZOOM_SETTINGS_KEYS)(prevVideoSettings ?? defaultPTZSettings, mapFeatureToSettings(videoFeatures));
|
|
72
72
|
const audioRequest = refineMediaConstraints({
|
|
73
73
|
kind: 'audioinput',
|
|
74
74
|
request: constraints.audio,
|
|
@@ -154,8 +154,8 @@ export const createMediaUpdater = ({ getUserMedia, getCurrentDevices, shouldDisc
|
|
|
154
154
|
: undefined;
|
|
155
155
|
if (audioDiff || videoDiff) {
|
|
156
156
|
await currentMedia?.applyConstraints({
|
|
157
|
-
audio: audioDiff,
|
|
158
|
-
video: videoDiff,
|
|
157
|
+
audio: audioDiff && mapSettingsToFeatures(audioDiff),
|
|
158
|
+
video: videoDiff && mapSettingsToFeatures(videoDiff),
|
|
159
159
|
});
|
|
160
160
|
}
|
|
161
161
|
};
|
|
@@ -39,6 +39,7 @@ export interface PreviewStreamParams {
|
|
|
39
39
|
audio?: InputConstraintSet | false;
|
|
40
40
|
video?: InputConstraintSet | false;
|
|
41
41
|
};
|
|
42
|
+
stopVideoTrackAsMute?: () => boolean;
|
|
42
43
|
}
|
|
43
44
|
export interface PreviewControllerProps {
|
|
44
45
|
media: Media | undefined;
|
|
@@ -51,6 +52,7 @@ export interface PreviewControllerProps {
|
|
|
51
52
|
discardMedia: boolean;
|
|
52
53
|
initialized: boolean;
|
|
53
54
|
signals: MediaSignals;
|
|
55
|
+
keepVideoMuted: boolean;
|
|
54
56
|
}
|
|
55
57
|
export interface PreviewStreamController {
|
|
56
58
|
media: Media | undefined;
|
|
@@ -83,6 +85,6 @@ export interface PreviewStreamController {
|
|
|
83
85
|
onVideoMuted(callback: EventCallback<boolean | undefined>): Unsubscribe;
|
|
84
86
|
onVideoSuspended(callback: EventCallback<boolean | undefined>): Unsubscribe;
|
|
85
87
|
}
|
|
86
|
-
export declare const createPreviewStreamController: ({ getCurrentDevices, getCurrentMedia, updateMainStream, onEnded, mainMediaSignal, queueOptions, audioProcessors, videoProcessors, getDefaultConstraints, signals, }: PreviewStreamParams) => PreviewStreamController;
|
|
88
|
+
export declare const createPreviewStreamController: ({ getCurrentDevices, getCurrentMedia, updateMainStream, onEnded, mainMediaSignal, queueOptions, audioProcessors, videoProcessors, getDefaultConstraints, signals, stopVideoTrackAsMute, }: PreviewStreamParams) => PreviewStreamController;
|
|
87
89
|
export type CreatePreviewStreamController = typeof createPreviewStreamController;
|
|
88
90
|
export {};
|
|
@@ -51,7 +51,7 @@ export const createPreviewStreamController = ({ getCurrentDevices, getCurrentMed
|
|
|
51
51
|
throttleInMS: DEFAULT_QUEUE_THROTTLE_MS,
|
|
52
52
|
delayInMS: DEFAULT_QUEUE_DELAY_MS,
|
|
53
53
|
dropLast: DEFAULT_QUEUE_DROP_LAST,
|
|
54
|
-
}, audioProcessors, videoProcessors, getDefaultConstraints = () => ({}), signals, }) => {
|
|
54
|
+
}, audioProcessors, videoProcessors, getDefaultConstraints = () => ({}), signals, stopVideoTrackAsMute = () => false, }) => {
|
|
55
55
|
const queue = createAsyncQueue(queueOptions);
|
|
56
56
|
const eventHandlers = {};
|
|
57
57
|
const internalProps = {
|
|
@@ -62,6 +62,7 @@ export const createPreviewStreamController = ({ getCurrentDevices, getCurrentMed
|
|
|
62
62
|
discardMedia: false,
|
|
63
63
|
initialized: false,
|
|
64
64
|
signals,
|
|
65
|
+
keepVideoMuted: false,
|
|
65
66
|
};
|
|
66
67
|
const logger = createModuleLogger({
|
|
67
68
|
module: 'PreviewStreamController',
|
|
@@ -125,7 +126,7 @@ export const createPreviewStreamController = ({ getCurrentDevices, getCurrentMed
|
|
|
125
126
|
eventHandlers.audioMuted?.(track.muted);
|
|
126
127
|
}
|
|
127
128
|
else {
|
|
128
|
-
eventHandlers.videoMuted?.(track.muted);
|
|
129
|
+
eventHandlers.videoMuted?.(props.keepVideoMuted || track.muted);
|
|
129
130
|
}
|
|
130
131
|
}),
|
|
131
132
|
props.signals.onMediaTrackSuspended?.add(track => {
|
|
@@ -151,7 +152,9 @@ export const createPreviewStreamController = ({ getCurrentDevices, getCurrentMed
|
|
|
151
152
|
break;
|
|
152
153
|
}
|
|
153
154
|
case 'video': {
|
|
154
|
-
eventHandlers.videoMuted?.(
|
|
155
|
+
eventHandlers.videoMuted?.(props.keepVideoMuted ||
|
|
156
|
+
isTrackMuted(track) ||
|
|
157
|
+
isTrackEnded(track));
|
|
155
158
|
break;
|
|
156
159
|
}
|
|
157
160
|
}
|
|
@@ -163,7 +166,9 @@ export const createPreviewStreamController = ({ getCurrentDevices, getCurrentMed
|
|
|
163
166
|
break;
|
|
164
167
|
}
|
|
165
168
|
case 'video': {
|
|
166
|
-
eventHandlers.videoMuted?.(
|
|
169
|
+
eventHandlers.videoMuted?.(props.keepVideoMuted ||
|
|
170
|
+
isTrackMuted(track) ||
|
|
171
|
+
isTrackEnded(track));
|
|
167
172
|
break;
|
|
168
173
|
}
|
|
169
174
|
}
|
|
@@ -173,7 +178,7 @@ export const createPreviewStreamController = ({ getCurrentDevices, getCurrentMed
|
|
|
173
178
|
getUserMedia: requestUserMediaWithRetry(() => Promise.resolve(getCurrentDevices())),
|
|
174
179
|
signals: props.signals,
|
|
175
180
|
getCurrentDevices: () => Promise.resolve(getCurrentDevices()),
|
|
176
|
-
stopVideoTrackAsMute
|
|
181
|
+
stopVideoTrackAsMute,
|
|
177
182
|
updateMedia: constraints => updateMedia(constraints),
|
|
178
183
|
});
|
|
179
184
|
const mergeMediaConstraints = (constraints) => {
|
|
@@ -223,6 +228,14 @@ export const createPreviewStreamController = ({ getCurrentDevices, getCurrentMed
|
|
|
223
228
|
getCurrentDevices: () => Promise.resolve(getCurrentDevices()),
|
|
224
229
|
shouldDiscardMedia: () => props.discardMedia,
|
|
225
230
|
onMediaTracksChanged: (media, tracks) => {
|
|
231
|
+
if (props.keepVideoMuted) {
|
|
232
|
+
for (const track of tracks) {
|
|
233
|
+
if (track.kind === 'videoinput') {
|
|
234
|
+
track.mute(true);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
props.keepVideoMuted = false;
|
|
238
|
+
}
|
|
226
239
|
props.media = media;
|
|
227
240
|
queue.enqueue(async () => {
|
|
228
241
|
await processAndUpdateMedia(media, tracks, false);
|
|
@@ -328,14 +341,16 @@ export const createPreviewStreamController = ({ getCurrentDevices, getCurrentMed
|
|
|
328
341
|
props.updatingPreviewAudio = false;
|
|
329
342
|
}
|
|
330
343
|
};
|
|
331
|
-
const updateVideoInput = async (input) => {
|
|
344
|
+
const updateVideoInput = async (input, syncMuteState = true) => {
|
|
332
345
|
try {
|
|
333
346
|
props.videoInput = input;
|
|
334
347
|
props.updatingPreviewVideo = true;
|
|
335
348
|
if (input === undefined) {
|
|
336
349
|
return await releaseVideo();
|
|
337
350
|
}
|
|
338
|
-
|
|
351
|
+
props.keepVideoMuted = syncMuteState && !!props.media?.videoMuted;
|
|
352
|
+
await updatePreviewMedia({ video: { device: { exact: input } } });
|
|
353
|
+
return;
|
|
339
354
|
}
|
|
340
355
|
catch (error) {
|
|
341
356
|
if (error instanceof Error) {
|
|
@@ -350,7 +365,25 @@ export const createPreviewStreamController = ({ getCurrentDevices, getCurrentMed
|
|
|
350
365
|
};
|
|
351
366
|
const cleanup = async () => {
|
|
352
367
|
logger.debug('Cleanup preview controller');
|
|
353
|
-
|
|
368
|
+
// Drop pending jobs, then enqueue release so it runs after any
|
|
369
|
+
// in-flight `processAndUpdateMedia`. Releasing concurrently with an
|
|
370
|
+
// in-flight `videoProcessor.process()` would tear down the worker
|
|
371
|
+
// pipeline mid-flight.
|
|
372
|
+
queue.empty();
|
|
373
|
+
const media = props.media;
|
|
374
|
+
if (media) {
|
|
375
|
+
await new Promise((resolve, reject) => {
|
|
376
|
+
queue.enqueue(async () => {
|
|
377
|
+
try {
|
|
378
|
+
await media.release();
|
|
379
|
+
resolve();
|
|
380
|
+
}
|
|
381
|
+
catch (error) {
|
|
382
|
+
reject(error);
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
}
|
|
354
387
|
cleanUpMainSubscription();
|
|
355
388
|
for (const unsub of subscriptions) {
|
|
356
389
|
unsub?.();
|
|
@@ -475,7 +508,7 @@ export const createPreviewStreamController = ({ getCurrentDevices, getCurrentMed
|
|
|
475
508
|
return updateAudioInput(input);
|
|
476
509
|
}
|
|
477
510
|
case 'videoinput': {
|
|
478
|
-
return updateVideoInput(input);
|
|
511
|
+
return updateVideoInput(input, false);
|
|
479
512
|
}
|
|
480
513
|
}
|
|
481
514
|
},
|
package/dist/typeGuard.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AnalyzerNodeInit } from '@pexip/media-processor';
|
|
2
|
-
import type { AudioContentHint, Media, VideoContentHint
|
|
2
|
+
import type { AudioContentHint, Media, VideoContentHint } from './types';
|
|
3
3
|
import { UserMediaStatus } from './types';
|
|
4
4
|
export declare const isNonNullObject: (value: unknown) => value is Record<string, unknown>;
|
|
5
5
|
export declare const isUserMediaStatus: (value: unknown) => value is UserMediaStatus;
|
|
@@ -7,4 +7,3 @@ export declare const isMedia: (value: unknown) => value is Media;
|
|
|
7
7
|
export declare const isAnalyzerNodeInitProp: (value: unknown) => value is AnalyzerNodeInit | undefined;
|
|
8
8
|
export declare const isAudioContentHint: (value: unknown) => value is AudioContentHint;
|
|
9
9
|
export declare const isVideoContentHint: (value: unknown) => value is VideoContentHint;
|
|
10
|
-
export declare const isVideoStreamTrackProcessorAPIs: (value: unknown) => value is VideoStreamTrackProcessorAPIs;
|