@pexip/media 21.0.0 → 22.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.
@@ -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?.(isTrackMuted(track) || isTrackEnded(track));
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?.(isTrackMuted(track) || isTrackEnded(track));
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: () => false,
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
- return await updatePreviewMedia({ video: { device: { exact: input } } });
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) {
@@ -475,7 +490,7 @@ export const createPreviewStreamController = ({ getCurrentDevices, getCurrentMed
475
490
  return updateAudioInput(input);
476
491
  }
477
492
  case 'videoinput': {
478
- return updateVideoInput(input);
493
+ return updateVideoInput(input, false);
479
494
  }
480
495
  }
481
496
  },
@@ -1,5 +1,5 @@
1
1
  import type { AnalyzerNodeInit } from '@pexip/media-processor';
2
- import type { AudioContentHint, Media, VideoContentHint, VideoStreamTrackProcessorAPIs } from './types';
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;
package/dist/typeGuard.js CHANGED
@@ -38,6 +38,3 @@ export const isVideoContentHint = (value) => {
38
38
  }
39
39
  return false;
40
40
  };
41
- export const isVideoStreamTrackProcessorAPIs = (value) => {
42
- return (typeof value === 'string' && (value === 'stream' || value === 'canvas'));
43
- };
package/dist/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { IndexedDevices, InputConstraintSet, InputDeviceConstraint, MediaDeviceInfoLike, MediaDeviceRequest } from '@pexip/media-control';
2
- import type { RendererOptions, RenderEffects, Segmenter, SegmentationModel } from '@pexip/media-processor';
2
+ import type { RendererOptions, RenderEffects } from '@pexip/media-processor';
3
3
  import type { Signal } from '@pexip/signal';
4
4
  export type Unsubscribe = () => void;
5
5
  export interface ExtendedMediaTrackSettings extends MediaTrackSettings {
@@ -14,10 +14,12 @@ export interface ExtendedMediaTrackSettings extends MediaTrackSettings {
14
14
  maskCombineRatio?: number;
15
15
  foregroundThreshold?: number;
16
16
  videoSegmentation?: RenderEffects;
17
- videoSegmentationModel?: SegmentationModel;
18
- pan?: boolean;
19
- tilt?: boolean;
20
- zoom?: boolean;
17
+ panEnabled?: boolean;
18
+ tiltEnabled?: boolean;
19
+ zoomEnabled?: boolean;
20
+ pan?: number;
21
+ tilt?: number;
22
+ zoom?: number;
21
23
  contentHint?: AudioContentHint | VideoContentHint;
22
24
  }
23
25
  export type ExtendedMediaTrackSettingsKey = keyof ExtendedMediaTrackSettings;
@@ -230,12 +232,6 @@ export type GetUserMediaProcess = (request: {
230
232
  };
231
233
  currentMedia: Media | undefined;
232
234
  }) => Promise<Media>;
233
- /**
234
- * Use which processor API to process the stream track
235
- * `stream` - Use `MediaStreamTrackProcessor`, when available
236
- * `canvas` - Use Canvas
237
- */
238
- export type VideoStreamTrackProcessorAPIs = 'stream' | 'canvas';
239
235
  export declare enum UserMediaStatus {
240
236
  /**
241
237
  * The initial status
@@ -573,9 +569,6 @@ export declare enum DeniedDevices {
573
569
  Camera = "camera",
574
570
  Both = "microphone-and-camera"
575
571
  }
576
- export type Segmenters = {
577
- [Property in SegmentationModel]: Segmenter;
578
- };
579
572
  /**
580
573
  * Audio content hints are only applicable when the MediaStreamTrack contains an
581
574
  * audio track
package/dist/utils.js CHANGED
@@ -3,6 +3,7 @@ import { calculateMaxBlurPass, clamping, } from '@pexip/media-processor';
3
3
  import { hasOwn, assert, isEmpty } from '@pexip/utils';
4
4
  import { internalSignals } from './signals';
5
5
  import { MAX_TENT_BLUR_SIZE } from './constants';
6
+ import { mapFeatureToSettings } from './videoProcessor';
6
7
  export const makeDeriveDeviceStatus = (constraints) => (audio, video, both) => {
7
8
  if (constraints.audio) {
8
9
  if (constraints.video) {
@@ -571,7 +572,6 @@ export const AUDIO_SETTINGS_KEYS = [
571
572
  export const VIDEO_SETTINGS_KEYS = [
572
573
  'frameRate',
573
574
  'videoSegmentation',
574
- 'videoSegmentationModel',
575
575
  'foregroundThreshold',
576
576
  'backgroundBlurAmount',
577
577
  'edgeBlurAmount',
@@ -629,10 +629,11 @@ export const getSettingsFromKeys = (keys, settings) => {
629
629
  return settings;
630
630
  }
631
631
  const result = {};
632
+ const mapped = mapFeatureToSettings(settings);
632
633
  for (const key of keys) {
633
- if (settings[key] !== undefined) {
634
+ if (mapped[key] !== undefined) {
634
635
  // @ts-expect-error --- Type issue and need to be fixed when we have time
635
- result[key] = settings[key];
636
+ result[key] = mapped[key];
636
637
  }
637
638
  }
638
639
  return result;
@@ -1,27 +1,15 @@
1
- import type { RenderBackend, SegmentationModel, SegmentationTransform, VideoProcessor } from '@pexip/media-processor';
2
- import type { MediaDeviceRequest } from '@pexip/media-control';
3
- import type { MediaSignals, Segmenters, TrackProcessor, VideoContentHint, VideoRenderParams, VideoStreamTrackProcessorAPIs } from './types';
4
- interface ProcessorDeps {
5
- segmenters: Partial<Segmenters>;
6
- transformer?: SegmentationTransform;
7
- videoProcessor?: () => VideoProcessor;
8
- videoSegmentationModel?: SegmentationModel;
9
- }
10
- interface VideoStreamProcessOptions extends Partial<VideoRenderParams>, Omit<ProcessorDeps, 'videoProcessor'> {
11
- /**
12
- * What API to use for processing the MediaStreamTrack
13
- * `stream` - Use MediaStreamTrackProcessor, when available
14
- * `canvas` - Use Canvas
15
- */
16
- trackProcessorAPI?: () => VideoStreamTrackProcessorAPIs;
1
+ import type { RenderBackend, VideoProcessor } from '@pexip/media-processor';
2
+ import type { InputConstraintSet, MediaDeviceRequest } from '@pexip/media-control';
3
+ import type { ExtendedMediaTrackSettings, MediaSignals, TrackProcessor, VideoContentHint, VideoRenderParams } from './types';
4
+ interface VideoStreamProcessOptions extends Partial<VideoRenderParams> {
17
5
  /**
18
6
  * Whether or to enable this processor
19
7
  */
20
8
  shouldEnable: () => boolean;
9
+ getVideoProcessor: () => VideoProcessor;
21
10
  referenceProcessingHeight?: number;
22
11
  processingWidth: number;
23
12
  processingHeight: number;
24
- hasInitializedDeps?: boolean;
25
13
  width?: number;
26
14
  height?: number;
27
15
  label?: string;
@@ -30,13 +18,43 @@ interface VideoStreamProcessOptions extends Partial<VideoRenderParams>, Omit<Pro
30
18
  gpuAPI?: () => RenderBackend;
31
19
  signals?: MediaSignals;
32
20
  }
33
- interface VideoStreamProcessProps extends Partial<VideoRenderParams>, Required<ProcessorDeps> {
34
- hasInitialized: boolean;
21
+ interface VideoStreamProcessProps extends Partial<VideoRenderParams> {
35
22
  contentHint?: VideoContentHint;
36
23
  }
37
- declare const FEATURE_KEYS: readonly ["backgroundBlurAmount", "backgroundImageUrl", "backgroundThreshold", "maskCombineRatio", "edgeBlurAmount", "foregroundThreshold", "frameRate", "videoSegmentation", "videoSegmentationModel", "width", "height", "pan", "tilt", "zoom", "contentHint", "sigmaSpace", "sigmaRangeLo", "sigmaRangeHi", "excludeBystanders", "personCenterX", "personCenterY", "morphErodeRadiusPx", "morphPass", "morphDilateRadiusPx", "lightWrapIntensity", "lightWrapTightness", "lightWrapEdgeBand", "lightWrapBlurAmount", "downSampleFactor"];
38
- type FeaturePropKeys = (typeof FEATURE_KEYS)[number];
24
+ declare const FEATURE_KEYS: {
25
+ readonly backgroundBlurAmount: "number";
26
+ readonly backgroundImageUrl: "string";
27
+ readonly backgroundThreshold: "number";
28
+ readonly maskCombineRatio: "number";
29
+ readonly edgeBlurAmount: "number";
30
+ readonly foregroundThreshold: "number";
31
+ readonly frameRate: "number";
32
+ readonly videoSegmentation: "string";
33
+ readonly width: "number";
34
+ readonly height: "number";
35
+ readonly pan: "boolean";
36
+ readonly tilt: "boolean";
37
+ readonly zoom: "boolean";
38
+ readonly contentHint: "string";
39
+ readonly sigmaSpace: "number";
40
+ readonly sigmaRangeLo: "number";
41
+ readonly sigmaRangeHi: "number";
42
+ readonly excludeBystanders: "boolean";
43
+ readonly personCenterX: "number";
44
+ readonly personCenterY: "number";
45
+ readonly morphErodeRadiusPx: "number";
46
+ readonly morphPass: "number";
47
+ readonly morphDilateRadiusPx: "number";
48
+ readonly lightWrapIntensity: "number";
49
+ readonly lightWrapTightness: "number";
50
+ readonly lightWrapEdgeBand: "number";
51
+ readonly lightWrapBlurAmount: "number";
52
+ readonly downSampleFactor: "number";
53
+ };
54
+ type FeaturePropKeys = keyof typeof FEATURE_KEYS;
39
55
  type FeatureProps = Pick<Partial<VideoStreamProcessProps>, FeaturePropKeys>;
40
56
  export declare const updateFeatureProps: (constraints: MediaDeviceRequest["video"], props: FeatureProps) => FeatureProps;
41
- export declare const createVideoStreamProcess: ({ backgroundImageUrl, dynamicProcessingDimensions, backgroundThreshold, downSampleFactor, foregroundThreshold, lightWrapEdgeBand, lightWrapIntensity, lightWrapTightness, morphDilateRadiusPx, morphErodeRadiusPx, morphPass, personCenterX, personCenterY, sigmaSpace, sigmaRangeHi, sigmaRangeLo, frameRate, gpuAPI, label, referenceProcessingHeight, maskCombineRatio, processingHeight, processingWidth, shouldEnable, stopAsMute, trackProcessorAPI, videoSegmentation, signals, ...options }: VideoStreamProcessOptions) => TrackProcessor;
57
+ export declare const mapFeatureToSettings: (props: InputConstraintSet) => ExtendedMediaTrackSettings;
58
+ export declare const mapSettingsToFeatures: (settings: ExtendedMediaTrackSettings) => InputConstraintSet;
59
+ export declare const createVideoStreamProcess: ({ backgroundImageUrl, dynamicProcessingDimensions, backgroundThreshold, downSampleFactor, foregroundThreshold, lightWrapEdgeBand, lightWrapIntensity, lightWrapTightness, morphDilateRadiusPx, morphErodeRadiusPx, morphPass, personCenterX, personCenterY, sigmaSpace, sigmaRangeHi, sigmaRangeLo, frameRate, gpuAPI, label, referenceProcessingHeight, maskCombineRatio, processingHeight, processingWidth, shouldEnable, stopAsMute, videoSegmentation, signals, getVideoProcessor, ...options }: VideoStreamProcessOptions) => TrackProcessor;
42
60
  export {};