@pexip/media 18.5.0 → 19.0.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/dist/userMedia.js CHANGED
@@ -1,9 +1,10 @@
1
- import { MediaDeviceFailure, applyConstraints, findMediaInputFromMediaStreamTrack, getDevices, getUserMedia, isExactDeviceConstraint, isRequestedResolution, isStreamingRequestedDevices, muteStreamTrack, stopMediaStream, isAudioInput, isVideoInput, hasAnyInputs, hasAnyGrantedInput, } from '@pexip/media-control';
2
- import { isEmpty } from '@pexip/utils';
1
+ import { MediaDeviceFailure, extractConstraintsWithKeys, findMediaInputFromMediaStreamTrack, getUserMedia, isExactDeviceConstraint, isStreamingRequestedDevices, } from '@pexip/media-control';
2
+ import { assert } from '@pexip/utils';
3
3
  import { UserMediaStatus } from './types';
4
- import { shallowCopy, makeDeriveDeviceStatus, createMemorizedGetExpectedInput, isMuted, wrapToJSON, } from './utils';
4
+ import { makeDeriveDeviceStatus, buildMedia, createMediaTrack, findExpectedInput, } from './utils';
5
5
  import { logger } from './logger';
6
6
  import { isUnknownError } from './status';
7
+ import { PROCESSOR_LABELS } from './constants';
7
8
  export const toErrorDeviceStatus = (error, deriveDeviceStatus) => {
8
9
  switch (error.message) {
9
10
  case MediaDeviceFailure.AudioInputDeviceNotFoundError:
@@ -13,7 +14,6 @@ export const toErrorDeviceStatus = (error, deriveDeviceStatus) => {
13
14
  case MediaDeviceFailure.AudioAndVideoDeviceNotFoundError:
14
15
  return UserMediaStatus.AudioVideoDevicesNotFound;
15
16
  case MediaDeviceFailure.NotAllowedError:
16
- case MediaDeviceFailure.NotFoundError:
17
17
  case MediaDeviceFailure.SecurityError:
18
18
  case MediaDeviceFailure.PermissionDeniedError:
19
19
  return deriveDeviceStatus(UserMediaStatus.PermissionsRejectedAudioInput, UserMediaStatus.PermissionsRejectedVideoInput, UserMediaStatus.PermissionsRejected);
@@ -22,9 +22,9 @@ export const toErrorDeviceStatus = (error, deriveDeviceStatus) => {
22
22
  case MediaDeviceFailure.AbortError:
23
23
  return deriveDeviceStatus(UserMediaStatus.AudioDeviceInUse, UserMediaStatus.VideoDeviceInUse, UserMediaStatus.DevicesInUse);
24
24
  case MediaDeviceFailure.MissingConstraintsError:
25
- return deriveDeviceStatus(UserMediaStatus.NoAudioDevicesFound, UserMediaStatus.NoVideoDevicesFound, UserMediaStatus.NoDevicesFound);
26
25
  case MediaDeviceFailure.OverconstrainedError:
27
- return deriveDeviceStatus(UserMediaStatus.AudioOverconstrained, UserMediaStatus.VideoOverconstrained, UserMediaStatus.Overconstrained);
26
+ case MediaDeviceFailure.NotFoundError:
27
+ return deriveDeviceStatus(UserMediaStatus.NoAudioDevicesFound, UserMediaStatus.NoVideoDevicesFound, UserMediaStatus.NoDevicesFound);
28
28
  case MediaDeviceFailure.TypeError:
29
29
  return deriveDeviceStatus(UserMediaStatus.InvalidAudioConstraints, UserMediaStatus.InvalidVideoConstraints, UserMediaStatus.InvalidConstraints);
30
30
  case MediaDeviceFailure.NotSupportedError:
@@ -34,7 +34,10 @@ export const toErrorDeviceStatus = (error, deriveDeviceStatus) => {
34
34
  }
35
35
  };
36
36
  export const mapErrorStatus = (status) => (constraints) => {
37
- const toStatus = makeDeriveDeviceStatus(constraints);
37
+ const toStatus = makeDeriveDeviceStatus({
38
+ audio: constraints.audio ?? false,
39
+ video: constraints.video ?? false,
40
+ });
38
41
  switch (status) {
39
42
  case UserMediaStatus.AudioVideoDevicesNotFound:
40
43
  return toStatus(UserMediaStatus.AudioDeviceNotFound, UserMediaStatus.VideoDeviceNotFound, status);
@@ -69,12 +72,7 @@ export const toSameDeviceStatus = ({ audio, video, }) => {
69
72
  return UserMediaStatus.PermissionsGrantedFallback;
70
73
  };
71
74
  export const toOnlyDeviceStatus = (kind, matched, devices) => {
72
- const hasRelatedDevices = devices.some(d => {
73
- if (kind === 'audioinput') {
74
- return d.kind === 'videoinput';
75
- }
76
- return d.kind === 'audioinput';
77
- });
75
+ const hasRelatedDevices = devices.size(kind) > 0;
78
76
  if (matched) {
79
77
  if (hasRelatedDevices) {
80
78
  return kind === 'audioinput'
@@ -117,14 +115,11 @@ export const deriveErrorLevel = (error, status, constraints) => {
117
115
  ? 'error'
118
116
  : 'warn';
119
117
  };
120
- export const requestUserMedia = (currentDevices, getMedia = getUserMedia) => async (constraints) => {
118
+ export const requestUserMedia = (getCurrentDevices, getMedia = getUserMedia) => async (constraints) => {
121
119
  const deriveDeviceStatus = makeDeriveDeviceStatus(constraints);
122
- const devices = currentDevices ?? (await getDevices());
123
120
  try {
124
121
  const stream = await getMedia(constraints);
125
- const grantedDevices = hasAnyGrantedInput(devices)
126
- ? devices
127
- : await getDevices();
122
+ const grantedDevices = await getCurrentDevices();
128
123
  const { audio, video } = isStreamingRequestedDevices(constraints, stream, grantedDevices);
129
124
  const onlyAudioStatus = toOnlyDeviceStatus('audioinput', audio, grantedDevices);
130
125
  const onlyVideoStatus = toOnlyDeviceStatus('videoinput', video, grantedDevices);
@@ -155,179 +150,128 @@ export const mergeNoDeviceStatus = (constraints, anyDevices, status) => {
155
150
  }
156
151
  return status;
157
152
  };
158
- export const requestUserMediaWithRetry = (currentDevices, createRequestUserMedia = requestUserMedia) => async (constraints) => {
159
- const devices = isEmpty(currentDevices)
160
- ? await getDevices()
161
- : currentDevices;
162
- const [anyAudioDevices, anyVideoDevices] = hasAnyInputs(devices);
163
- const request = (constraints, devices) => createRequestUserMedia(devices)(constraints);
164
- if (anyAudioDevices && anyVideoDevices) {
165
- const [stream, status] = await request(constraints, devices);
166
- if (stream) {
167
- return [stream, status];
168
- }
169
- const mapStatus = mapErrorStatus(status);
170
- if (constraints.video) {
171
- const [audioStream] = await request({
172
- ...constraints,
173
- video: false,
174
- }, devices);
175
- if (audioStream) {
176
- // When success, we know it is video related error
177
- const videoStatus = mapStatus({ video: true });
178
- return [audioStream, videoStatus];
179
- }
180
- }
181
- if (constraints.audio) {
182
- const [videoStream] = await request({
183
- ...constraints,
184
- audio: false,
185
- }, devices);
186
- if (videoStream) {
187
- // When success, we know it is audio related error
188
- return [videoStream, mapStatus({ audio: true })];
189
- }
190
- }
191
- return [stream, status];
192
- }
193
- else {
194
- const [stream, status] = await request({
195
- audio: anyAudioDevices && constraints.audio,
196
- video: anyVideoDevices && constraints.video,
197
- }, devices);
153
+ export const requestUserMediaWithRetry = (getCurrentDevices, createRequestUserMedia = requestUserMedia, gUM = getUserMedia) => {
154
+ const request = createRequestUserMedia(getCurrentDevices, gUM);
155
+ return async (constraints) => {
156
+ const [stream, status] = await request(constraints);
157
+ const devices = await getCurrentDevices();
158
+ const anyAudioDevices = devices.size('audioinput') > 0;
159
+ const anyVideoDevices = devices.size('videoinput') > 0;
198
160
  return [
199
161
  stream,
200
162
  mergeNoDeviceStatus(constraints, { audio: anyAudioDevices, video: anyVideoDevices }, status),
201
163
  ];
202
- }
164
+ };
203
165
  };
204
166
  /**
205
167
  * A process to get user media
206
168
  */
207
- export const createGetUserMediaProcess = (getUserMedia, getCurrentDevices, { initialMedia, scope = 'media' }) => {
208
- const props = {
209
- unsubscribe: undefined,
210
- currentDevices: getCurrentDevices(),
211
- cachedAudioTrackId: '',
212
- cachedVideoTrackId: '',
213
- cachedAudioInput: undefined,
214
- cachedVideoInput: undefined,
215
- };
216
- const getExpectedAudioInput = createMemorizedGetExpectedInput();
217
- const getExpectedVideoInput = createMemorizedGetExpectedInput();
218
- /**
219
- * Memorized get media input
220
- */
221
- const getInput = ([track] = []) => {
222
- if (!track) {
223
- return undefined;
169
+ export const createGetUserMediaProcess = ({ getUserMedia, getCurrentDevices, signals, scope = 'media', }) => {
170
+ return async ({ constraints, permission, originalConstraints, currentMedia, }) => {
171
+ // Release the current track(s)
172
+ if (currentMedia) {
173
+ await Promise.all(currentMedia.getTracks().map(track => {
174
+ switch (track.kind) {
175
+ case 'audioinput':
176
+ // When the constraints is undefined we should do nothing
177
+ if (constraints.audio !== undefined) {
178
+ // There is only one audio track, so we can safely assign it
179
+ currentMedia.removeTrack(track);
180
+ return track.release();
181
+ }
182
+ return Promise.resolve();
183
+ case 'videoinput':
184
+ // When the constraints is undefined we should do nothing
185
+ if (constraints.video !== undefined) {
186
+ // There is only one video track, so we can safely assign it
187
+ currentMedia.removeTrack(track);
188
+ return track.release();
189
+ }
190
+ return Promise.resolve();
191
+ default:
192
+ assert(false, `Undexpected track kind: ${track.kind}`);
193
+ }
194
+ }));
224
195
  }
225
- const isAudio = track.kind === 'audio';
226
- const cacheKey = isAudio ? 'cachedAudioInput' : 'cachedVideoInput';
227
- const cachedTrackId = isAudio
228
- ? 'cachedAudioTrackId'
229
- : 'cachedVideoTrackId';
230
- const trackId = track.label;
231
- const { width, height } = track.getSettings();
232
- if (trackId === props[cachedTrackId] &&
233
- track.readyState === 'live' &&
234
- (isAudio ||
235
- (!isAudio &&
236
- isRequestedResolution({ width, height }, props[cacheKey])))) {
237
- return props[cacheKey];
196
+ const currentDevices = await getCurrentDevices();
197
+ logger.debug({
198
+ scope,
199
+ originalConstraints,
200
+ constraints,
201
+ currentDevices,
202
+ currentMedia,
203
+ }, 'pre getUserMedia');
204
+ if (!constraints.audio && !constraints.video) {
205
+ currentMedia?.setOriginalConstraints(originalConstraints);
206
+ return (currentMedia ??
207
+ buildMedia({
208
+ constraints,
209
+ permission,
210
+ originalConstraints,
211
+ devices: currentDevices,
212
+ status: UserMediaStatus.PermissionsGranted,
213
+ stream: undefined,
214
+ signals,
215
+ tracks: [],
216
+ }));
238
217
  }
239
- const devices = getCurrentDevices();
240
- const findTrack = findMediaInputFromMediaStreamTrack(devices);
241
- const input = findTrack(track);
242
- // Update cache
243
- props[cacheKey] = input;
244
- props[cachedTrackId] = trackId;
245
- return input;
246
- };
247
- return async (constraints) => {
248
218
  const [stream, status] = await getUserMedia(constraints);
249
- logger.debug({ scope, stream, status }, 'getUserMedia');
250
- props.currentDevices = await getDevices();
251
- const deriveDeviceStatus = makeDeriveDeviceStatus(constraints);
252
- const muteTrack = muteStreamTrack(stream);
253
- const muteAudio = (mute) => muteTrack(mute, 'audio');
254
- const muteVideo = (mute) => muteTrack(mute, 'video');
255
- return wrapToJSON(shallowCopy(initialMedia ?? {}, {
219
+ logger.debug({ scope, stream, status }, 'post getUserMedia');
220
+ const devices = await getCurrentDevices();
221
+ const findInput = findMediaInputFromMediaStreamTrack(devices);
222
+ let audioMediaTrack;
223
+ let videoMediaTrack;
224
+ const extractContentHint = extractConstraintsWithKeys(['contentHint']);
225
+ if (constraints.audio !== undefined) {
226
+ const audioTrack = stream?.getAudioTracks().at(0);
227
+ const audioInput = findInput(audioTrack);
228
+ const { contentHint: [[contentHint] = []], } = extractContentHint(constraints.audio);
229
+ if (audioTrack) {
230
+ audioTrack.contentHint = contentHint ?? '';
231
+ }
232
+ audioMediaTrack = createMediaTrack({
233
+ label: PROCESSOR_LABELS.GetUserMedia,
234
+ kind: 'audioinput',
235
+ track: audioTrack,
236
+ input: audioInput,
237
+ expectedInput: findExpectedInput(devices, constraints.audio, audioInput, 'audioinput'),
238
+ constraints: constraints.audio,
239
+ signals,
240
+ });
241
+ currentMedia?.addTrack(audioMediaTrack);
242
+ }
243
+ if (constraints.video !== undefined) {
244
+ const videoTrack = stream?.getVideoTracks().at(0);
245
+ const videoInput = findInput(videoTrack);
246
+ const { contentHint: [[contentHint] = []], } = extractContentHint(constraints.video);
247
+ if (videoTrack) {
248
+ videoTrack.contentHint = contentHint ?? '';
249
+ }
250
+ videoMediaTrack = createMediaTrack({
251
+ label: PROCESSOR_LABELS.GetUserMedia,
252
+ kind: 'videoinput',
253
+ track: videoTrack,
254
+ input: videoInput,
255
+ expectedInput: findExpectedInput(devices, constraints.video, videoInput, 'videoinput'),
256
+ constraints: constraints.video,
257
+ signals,
258
+ });
259
+ currentMedia?.addTrack(videoMediaTrack);
260
+ }
261
+ if (currentMedia) {
262
+ currentMedia.status = status;
263
+ currentMedia.setOriginalConstraints(originalConstraints);
264
+ return currentMedia;
265
+ }
266
+ return buildMedia({
256
267
  constraints,
257
- rawStream: stream,
268
+ permission,
269
+ originalConstraints,
270
+ devices,
258
271
  stream,
259
272
  status,
260
- get devices() {
261
- return props.currentDevices;
262
- },
263
- set devices(newDevices) {
264
- props.currentDevices = newDevices;
265
- },
266
- get audioInput() {
267
- return getInput(stream?.getAudioTracks());
268
- },
269
- get videoInput() {
270
- return getInput(stream?.getVideoTracks());
271
- },
272
- get expectedAudioInput() {
273
- return getExpectedAudioInput(constraints.audio, () => ({
274
- devices: getCurrentDevices().filter(isAudioInput),
275
- input: getInput(stream?.getAudioTracks()),
276
- }));
277
- },
278
- get expectedVideoInput() {
279
- return getExpectedVideoInput(constraints.video, () => ({
280
- devices: getCurrentDevices().filter(isVideoInput),
281
- input: getInput(stream?.getVideoTracks()),
282
- }));
283
- },
284
- muteAudio,
285
- muteVideo,
286
- get audioMuted() {
287
- return isMuted(stream?.getAudioTracks());
288
- },
289
- get videoMuted() {
290
- return isMuted(stream?.getVideoTracks());
291
- },
292
- applyConstraints: async (constraints) => {
293
- try {
294
- logger.debug({ scope, constraints: constraints }, 'apply native constraints');
295
- return await applyConstraints(stream?.getTracks(), constraints);
296
- }
297
- catch (error) {
298
- if (error instanceof Error) {
299
- const status = toErrorDeviceStatus(error, deriveDeviceStatus);
300
- logger.error({
301
- scope,
302
- status,
303
- error,
304
- constraints: constraints,
305
- }, 'fail to apply native constraints');
306
- initialMedia.status = status;
307
- }
308
- throw error;
309
- }
310
- },
311
- getSettings: () => {
312
- const settings = {
313
- audio: stream
314
- ?.getAudioTracks()
315
- .map(track => track.getSettings()) ?? [],
316
- video: stream
317
- ?.getVideoTracks()
318
- .map(track => track.getSettings()) ?? [],
319
- };
320
- logger.debug({ settings, scope }, 'get native settings');
321
- return settings;
322
- },
323
- release: () => {
324
- stopMediaStream(stream);
325
- if (props.unsubscribe) {
326
- props.unsubscribe();
327
- props.unsubscribe = undefined;
328
- }
329
- return Promise.resolve();
330
- },
331
- }));
273
+ signals,
274
+ tracks: [audioMediaTrack, videoMediaTrack].flatMap(track => track ? [track] : []),
275
+ });
332
276
  };
333
277
  };
package/dist/utils.d.ts CHANGED
@@ -1,26 +1,14 @@
1
- import type { MediaDeviceInfoLike, MediaDeviceRequest } from '@pexip/media-control';
2
- import { UserMediaStatus } from './types';
3
- import type { Media, MediaAttributes, Pipeline, Process, ProcessMedia, ExtendedMediaTrackSettingsKey, ExtendedMediaTrackSettings } from './types';
1
+ import type { IndexedDevices, InputDeviceConstraint, MediaDeviceInfoLike, MediaDeviceRequest } from '@pexip/media-control';
2
+ import type { ExtendedMediaTrackSettings, ExtendedMediaTrackSettingsKey, Media, MediaInit, MediaTrack, MediaTrackInit, TrackProcessor, UserMediaStatus } from './types';
4
3
  export declare const makeDeriveDeviceStatus: (constraints: MediaDeviceRequest) => (audio: UserMediaStatus, video: UserMediaStatus, both: UserMediaStatus) => UserMediaStatus;
5
- export declare const createMediaProcess: (process: ProcessMedia) => Process<Promise<Media>>;
6
- export declare const createMediaPipeline: <T = MediaDeviceRequest>(init: Pipeline<T> | (() => Pipeline<T>)) => {
7
- pipe: (process: Process<Promise<Media>>) => void;
8
- execute: (m: T) => Promise<Media>;
9
- };
4
+ export declare const createMediaTrack: (trackInit: MediaTrackInit) => MediaTrack;
5
+ export declare const createTrackProcessingPipeline: (processors: TrackProcessor[]) => (track: MediaTrack) => Promise<MediaTrack>;
10
6
  /**
11
7
  * Interpret provided input to resolve to a MediaDeviceInfoLike when possible
12
8
  * otherwise `undefined`
13
9
  */
14
10
  export declare const interpretInput: (input: boolean | MediaDeviceInfoLike | undefined, getCurrentInput: () => MediaDeviceInfoLike | undefined) => MediaDeviceInfoLike | undefined;
15
- type InputConstraints = MediaDeviceRequest['audio'];
16
- interface MediaInputInfo {
17
- devices: MediaDeviceInfoLike[];
18
- input: MediaDeviceInfoLike | undefined;
19
- }
20
- /**
21
- * Memorized Expected Input
22
- */
23
- export declare const createMemorizedGetExpectedInput: () => (constraints: InputConstraints, getInfo: () => MediaInputInfo) => ExpectedInput;
11
+ export declare const findExpectedInput: (devices: IndexedDevices, constraints: InputDeviceConstraint | undefined, input: MediaDeviceInfoLike | undefined, kind: 'audioinput' | 'videoinput') => MediaDeviceInfoLike | undefined;
24
12
  /**
25
13
  * A utility function to check if the provided track is muted. There are
26
14
  * 2 factors to be considered: `MediaStreamTrack['muted']` and `MediaStreamTrack['enabled']`.
@@ -32,19 +20,14 @@ export declare const createMemorizedGetExpectedInput: () => (constraints: InputC
32
20
  * | false | false | true |
33
21
  * ```
34
22
  *
35
- * @param tracks - The tracks can be got from `MediaStream['getAudioStats']` or
23
+ * @param track - The tracks can be got from `MediaStream['getAudioStats']` or
36
24
  * `MediaStream['getVideoTracks']`
37
25
  *
38
26
  * @returns `true` means muted, `false` means not muted and `undefined` means
39
27
  * there is no track to check
40
28
  */
41
- export declare const isMuted: (tracks: MediaStreamTrack[] | undefined) => boolean | undefined;
42
- type ExpectedInput = MediaDeviceInfoLike | undefined;
43
- export declare const buildMedia: (getMedia: () => Partial<Media>, onSetStatus?: ((status: UserMediaStatus) => void) | undefined) => Media;
44
- /**
45
- * Clone the media from the rawStream (if any), otherwise, stream
46
- */
47
- export declare const cloneMedia: (media: Media) => Promise<Media>;
29
+ export declare const isTrackMuted: (track: MediaStreamTrack | undefined) => boolean | undefined;
30
+ export declare const buildMedia: (mediaInit: MediaInit, onDevicesChanged?: import("@pexip/signal").Signal<IndexedDevices>) => Media;
48
31
  /**
49
32
  * Shallow copy the provided object and override with provided overriding
50
33
  *
@@ -61,32 +44,12 @@ export declare const getDevicesChanges: (prev: MediaDeviceInfoLike[], next: Medi
61
44
  lost: MediaDeviceInfoLike[];
62
45
  devices: MediaDeviceInfoLike[];
63
46
  };
64
- /**
65
- * Apply Extended constraints on top of the original
66
- *
67
- * @param media - The media from the media pipeline
68
- * @param applyExtended - The function to be called when the previous
69
- * `applyConstraints` is done
70
- */
71
- export declare const applyExtendedConstraints: (media: Media, applyExtended: (constraints: MediaDeviceRequest) => Promise<void>) => (constraints: MediaDeviceRequest) => Promise<void>;
72
47
  export declare const AUDIO_SETTINGS_KEYS: ExtendedMediaTrackSettingsKey[];
73
48
  export declare const VIDEO_SETTINGS_KEYS: ExtendedMediaTrackSettingsKey[];
74
49
  export declare const MIXING_SETTINGS_KEYS: ExtendedMediaTrackSettingsKey[];
75
50
  export declare const hasSettingsChanged: (keysToLookFor: ExtendedMediaTrackSettingsKey[]) => (settingsA: ExtendedMediaTrackSettings | undefined, settingsB: ExtendedMediaTrackSettings | undefined) => boolean;
76
- export declare const toJSON: (media: Partial<MediaAttributes>) => {
77
- constraints: MediaDeviceRequest | undefined;
78
- devices: MediaDeviceInfoLike[] | undefined;
79
- stream: MediaStream | undefined;
80
- rawStream: MediaStream | undefined;
81
- audioInput: MediaDeviceInfoLike | undefined;
82
- videoInput: MediaDeviceInfoLike | undefined;
83
- expectedAudioInput: MediaDeviceInfoLike | undefined;
84
- expectedVideoInput: MediaDeviceInfoLike | undefined;
85
- status: UserMediaStatus | undefined;
86
- audioMuted: boolean | undefined;
87
- videoMuted: boolean | undefined;
88
- };
89
- export declare const wrapToJSON: (media: Media) => Media;
51
+ export declare const diffSettings: (keysToLookFor: ExtendedMediaTrackSettingsKey[]) => (settingsA: ExtendedMediaTrackSettings | undefined, settingsB: ExtendedMediaTrackSettings | undefined) => ExtendedMediaTrackSettings | undefined;
52
+ export declare const mergeSettings: (settingsA: ExtendedMediaTrackSettings | undefined, settingsB: ExtendedMediaTrackSettings | undefined) => ExtendedMediaTrackSettings | undefined;
90
53
  /**
91
54
  * A function to get the blur kernel size of image height
92
55
  *
@@ -110,4 +73,19 @@ export declare const applyContentHint: <T extends "" | "speech" | "speech-recogn
110
73
  * @returns true if the browser supports PTZ feature, otherwise false
111
74
  */
112
75
  export declare const hasPtzFeature: () => boolean;
76
+ interface RequestState {
77
+ kind: 'audioinput' | 'videoinput';
78
+ permission: PermissionState;
79
+ currentDevices: IndexedDevices;
80
+ request: InputDeviceConstraint | undefined;
81
+ currentMediaTracks: MediaTrack[];
82
+ force?: boolean;
83
+ }
84
+ export declare const refineMediaConstraints: (state: RequestState) => InputDeviceConstraint | undefined;
85
+ interface ProcessorParams {
86
+ audioProcessors: TrackProcessor[];
87
+ videoProcessors: TrackProcessor[];
88
+ onProcessingError(error: Error, track: MediaTrack): void;
89
+ }
90
+ export declare const createMediaProcessor: ({ audioProcessors, videoProcessors, onProcessingError, }: ProcessorParams) => (newTracks: MediaTrack[]) => Promise<MediaTrack[]>;
113
91
  export {};