@memberjunction/ai-realtime-client 6.2.0-edge.3 → 6.2.0-edge.4
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/README.md +156 -29
- package/dist/audio/audioMeter.d.ts +71 -0
- package/dist/audio/audioMeter.d.ts.map +1 -1
- package/dist/audio/audioMeter.js +83 -0
- package/dist/audio/audioMeter.js.map +1 -1
- package/dist/audio/mediaElementAudioRouter.d.ts +41 -0
- package/dist/audio/mediaElementAudioRouter.d.ts.map +1 -0
- package/dist/audio/mediaElementAudioRouter.js +82 -0
- package/dist/audio/mediaElementAudioRouter.js.map +1 -0
- package/dist/audio/micCapture.d.ts +12 -3
- package/dist/audio/micCapture.d.ts.map +1 -1
- package/dist/audio/micCapture.js +15 -1
- package/dist/audio/micCapture.js.map +1 -1
- package/dist/audio/pcmPlayback.d.ts +72 -4
- package/dist/audio/pcmPlayback.d.ts.map +1 -1
- package/dist/audio/pcmPlayback.js +101 -1
- package/dist/audio/pcmPlayback.js.map +1 -1
- package/dist/drivers/assemblyAIRealtimeClient.d.ts +2 -0
- package/dist/drivers/assemblyAIRealtimeClient.d.ts.map +1 -1
- package/dist/drivers/assemblyAIRealtimeClient.js +14 -0
- package/dist/drivers/assemblyAIRealtimeClient.js.map +1 -1
- package/dist/drivers/elevenLabsRealtimeClient.d.ts +2 -0
- package/dist/drivers/elevenLabsRealtimeClient.d.ts.map +1 -1
- package/dist/drivers/elevenLabsRealtimeClient.js +14 -0
- package/dist/drivers/elevenLabsRealtimeClient.js.map +1 -1
- package/dist/drivers/geminiAvatarOutput.d.ts +132 -0
- package/dist/drivers/geminiAvatarOutput.d.ts.map +1 -0
- package/dist/drivers/geminiAvatarOutput.js +310 -0
- package/dist/drivers/geminiAvatarOutput.js.map +1 -0
- package/dist/drivers/geminiEnterpriseRealtimeClient.d.ts +38 -0
- package/dist/drivers/geminiEnterpriseRealtimeClient.d.ts.map +1 -0
- package/dist/drivers/geminiEnterpriseRealtimeClient.js +107 -0
- package/dist/drivers/geminiEnterpriseRealtimeClient.js.map +1 -0
- package/dist/drivers/geminiRealtimeClient.d.ts +314 -48
- package/dist/drivers/geminiRealtimeClient.d.ts.map +1 -1
- package/dist/drivers/geminiRealtimeClient.js +759 -176
- package/dist/drivers/geminiRealtimeClient.js.map +1 -1
- package/dist/drivers/openAILiveClient.d.ts +5 -8
- package/dist/drivers/openAILiveClient.d.ts.map +1 -1
- package/dist/drivers/openAILiveClient.js +19 -32
- package/dist/drivers/openAILiveClient.js.map +1 -1
- package/dist/drivers/openAIRealtimeClient.d.ts +13 -26
- package/dist/drivers/openAIRealtimeClient.d.ts.map +1 -1
- package/dist/drivers/openAIRealtimeClient.js +28 -55
- package/dist/drivers/openAIRealtimeClient.js.map +1 -1
- package/dist/generic/baseRealtimeClient.d.ts +173 -29
- package/dist/generic/baseRealtimeClient.d.ts.map +1 -1
- package/dist/generic/baseRealtimeClient.js +233 -14
- package/dist/generic/baseRealtimeClient.js.map +1 -1
- package/dist/generic/openAIProtocolClient.d.ts +2 -0
- package/dist/generic/openAIProtocolClient.d.ts.map +1 -1
- package/dist/generic/openAIProtocolClient.js +14 -0
- package/dist/generic/openAIProtocolClient.js.map +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/media/attachVideoSource.d.ts +23 -0
- package/dist/media/attachVideoSource.d.ts.map +1 -0
- package/dist/media/attachVideoSource.js +49 -0
- package/dist/media/attachVideoSource.js.map +1 -0
- package/dist/media/channelVideoSource.d.ts +110 -14
- package/dist/media/channelVideoSource.d.ts.map +1 -1
- package/dist/media/channelVideoSource.js +183 -18
- package/dist/media/channelVideoSource.js.map +1 -1
- package/dist/media/decoders/frameScheduler.d.ts +119 -0
- package/dist/media/decoders/frameScheduler.d.ts.map +1 -0
- package/dist/media/decoders/frameScheduler.js +238 -0
- package/dist/media/decoders/frameScheduler.js.map +1 -0
- package/dist/media/decoders/imageFrameDecoder.d.ts +58 -0
- package/dist/media/decoders/imageFrameDecoder.d.ts.map +1 -0
- package/dist/media/decoders/imageFrameDecoder.js +110 -0
- package/dist/media/decoders/imageFrameDecoder.js.map +1 -0
- package/dist/media/decoders/mseFmp4Decoder.d.ts +130 -0
- package/dist/media/decoders/mseFmp4Decoder.d.ts.map +1 -0
- package/dist/media/decoders/mseFmp4Decoder.js +402 -0
- package/dist/media/decoders/mseFmp4Decoder.js.map +1 -0
- package/dist/media/decoders/streamCanvas.d.ts +46 -0
- package/dist/media/decoders/streamCanvas.d.ts.map +1 -0
- package/dist/media/decoders/streamCanvas.js +163 -0
- package/dist/media/decoders/streamCanvas.js.map +1 -0
- package/dist/media/decoders/videoMimeTypes.d.ts +29 -0
- package/dist/media/decoders/videoMimeTypes.d.ts.map +1 -0
- package/dist/media/decoders/videoMimeTypes.js +50 -0
- package/dist/media/decoders/videoMimeTypes.js.map +1 -0
- package/dist/media/decoders/webCodecsChunkDecoder.d.ts +99 -0
- package/dist/media/decoders/webCodecsChunkDecoder.d.ts.map +1 -0
- package/dist/media/decoders/webCodecsChunkDecoder.js +265 -0
- package/dist/media/decoders/webCodecsChunkDecoder.js.map +1 -0
- package/dist/media/displayCapture.d.ts +128 -0
- package/dist/media/displayCapture.d.ts.map +1 -0
- package/dist/media/displayCapture.js +245 -0
- package/dist/media/displayCapture.js.map +1 -0
- package/dist/media/frameCapture.d.ts +25 -8
- package/dist/media/frameCapture.d.ts.map +1 -1
- package/dist/media/frameCapture.js +42 -72
- package/dist/media/frameCapture.js.map +1 -1
- package/dist/media/frameSampler.d.ts +94 -0
- package/dist/media/frameSampler.d.ts.map +1 -0
- package/dist/media/frameSampler.js +134 -0
- package/dist/media/frameSampler.js.map +1 -0
- package/dist/media/index.d.ts +32 -0
- package/dist/media/index.d.ts.map +1 -0
- package/dist/media/index.js +32 -0
- package/dist/media/index.js.map +1 -0
- package/dist/media/localMediaController.d.ts +116 -0
- package/dist/media/localMediaController.d.ts.map +1 -0
- package/dist/media/localMediaController.js +281 -0
- package/dist/media/localMediaController.js.map +1 -0
- package/dist/media/mediaLayout.d.ts +93 -0
- package/dist/media/mediaLayout.d.ts.map +1 -0
- package/dist/media/mediaLayout.js +187 -0
- package/dist/media/mediaLayout.js.map +1 -0
- package/dist/media/mediaPreview.d.ts +94 -0
- package/dist/media/mediaPreview.d.ts.map +1 -0
- package/dist/media/mediaPreview.js +154 -0
- package/dist/media/mediaPreview.js.map +1 -0
- package/dist/media/mediaStage.d.ts +99 -0
- package/dist/media/mediaStage.d.ts.map +1 -0
- package/dist/media/mediaStage.js +171 -0
- package/dist/media/mediaStage.js.map +1 -0
- package/dist/media/model.d.ts +154 -0
- package/dist/media/model.d.ts.map +1 -0
- package/dist/media/model.js +9 -0
- package/dist/media/model.js.map +1 -0
- package/dist/media/playbackClock.d.ts +20 -0
- package/dist/media/playbackClock.d.ts.map +1 -0
- package/dist/media/playbackClock.js +13 -0
- package/dist/media/playbackClock.js.map +1 -0
- package/dist/media/videoFrameDecoder.d.ts +86 -0
- package/dist/media/videoFrameDecoder.d.ts.map +1 -0
- package/dist/media/videoFrameDecoder.js +2 -0
- package/dist/media/videoFrameDecoder.js.map +1 -0
- package/dist/media/videoFrameDecoderRegistry.d.ts +40 -0
- package/dist/media/videoFrameDecoderRegistry.d.ts.map +1 -0
- package/dist/media/videoFrameDecoderRegistry.js +69 -0
- package/dist/media/videoFrameDecoderRegistry.js.map +1 -0
- package/dist/media/videoPacing.d.ts +32 -0
- package/dist/media/videoPacing.d.ts.map +1 -0
- package/dist/media/videoPacing.js +37 -0
- package/dist/media/videoPacing.js.map +1 -0
- package/dist/media/videoPlayout.d.ts +168 -0
- package/dist/media/videoPlayout.d.ts.map +1 -0
- package/dist/media/videoPlayout.js +217 -0
- package/dist/media/videoPlayout.js.map +1 -0
- package/dist/media/videoSourceArbiter.d.ts +250 -0
- package/dist/media/videoSourceArbiter.d.ts.map +1 -0
- package/dist/media/videoSourceArbiter.js +423 -0
- package/dist/media/videoSourceArbiter.js.map +1 -0
- package/dist/testing/conformanceAssertions.d.ts +25 -0
- package/dist/testing/conformanceAssertions.d.ts.map +1 -0
- package/dist/testing/conformanceAssertions.js +64 -0
- package/dist/testing/conformanceAssertions.js.map +1 -0
- package/dist/testing/conformanceFixtures.d.ts +76 -0
- package/dist/testing/conformanceFixtures.d.ts.map +1 -0
- package/dist/testing/conformanceFixtures.js +169 -0
- package/dist/testing/conformanceFixtures.js.map +1 -0
- package/dist/testing/conformanceGates.d.ts +32 -0
- package/dist/testing/conformanceGates.d.ts.map +1 -0
- package/dist/testing/conformanceGates.js +35 -0
- package/dist/testing/conformanceGates.js.map +1 -0
- package/dist/testing/conformanceMicrophone.d.ts +10 -0
- package/dist/testing/conformanceMicrophone.d.ts.map +1 -0
- package/dist/testing/conformanceMicrophone.js +71 -0
- package/dist/testing/conformanceMicrophone.js.map +1 -0
- package/dist/testing/conformanceTimeline.d.ts +128 -0
- package/dist/testing/conformanceTimeline.d.ts.map +1 -0
- package/dist/testing/conformanceTimeline.js +32 -0
- package/dist/testing/conformanceTimeline.js.map +1 -0
- package/dist/testing/conformanceVideoStream.d.ts +29 -0
- package/dist/testing/conformanceVideoStream.d.ts.map +1 -0
- package/dist/testing/conformanceVideoStream.js +39 -0
- package/dist/testing/conformanceVideoStream.js.map +1 -0
- package/dist/testing/index.d.ts +29 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +28 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/realtimeVideoConformance.d.ts +23 -0
- package/dist/testing/realtimeVideoConformance.d.ts.map +1 -0
- package/dist/testing/realtimeVideoConformance.js +139 -0
- package/dist/testing/realtimeVideoConformance.js.map +1 -0
- package/dist/testing/realtimeVideoConformanceChecks.d.ts +4 -0
- package/dist/testing/realtimeVideoConformanceChecks.d.ts.map +1 -0
- package/dist/testing/realtimeVideoConformanceChecks.js +164 -0
- package/dist/testing/realtimeVideoConformanceChecks.js.map +1 -0
- package/dist/testing/realtimeVideoConformanceFrameChecks.d.ts +4 -0
- package/dist/testing/realtimeVideoConformanceFrameChecks.d.ts.map +1 -0
- package/dist/testing/realtimeVideoConformanceFrameChecks.js +63 -0
- package/dist/testing/realtimeVideoConformanceFrameChecks.js.map +1 -0
- package/dist/testing/realtimeVideoConformanceSession.d.ts +108 -0
- package/dist/testing/realtimeVideoConformanceSession.d.ts.map +1 -0
- package/dist/testing/realtimeVideoConformanceSession.js +270 -0
- package/dist/testing/realtimeVideoConformanceSession.js.map +1 -0
- package/dist/testing/realtimeVideoConformanceTurnChecks.d.ts +4 -0
- package/dist/testing/realtimeVideoConformanceTurnChecks.d.ts.map +1 -0
- package/dist/testing/realtimeVideoConformanceTurnChecks.js +248 -0
- package/dist/testing/realtimeVideoConformanceTurnChecks.js.map +1 -0
- package/dist/testing/realtimeVideoConformanceTypes.d.ts +155 -0
- package/dist/testing/realtimeVideoConformanceTypes.d.ts.map +1 -0
- package/dist/testing/realtimeVideoConformanceTypes.js +2 -0
- package/dist/testing/realtimeVideoConformanceTypes.js.map +1 -0
- package/dist/testing/recordingPlayout.d.ts +84 -0
- package/dist/testing/recordingPlayout.d.ts.map +1 -0
- package/dist/testing/recordingPlayout.js +120 -0
- package/dist/testing/recordingPlayout.js.map +1 -0
- package/package.json +29 -4
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview MEDIA PREVIEW: the user's camera and microphone before they join a call or a meeting. It gives a
|
|
3
|
+
* camera to see themselves in, a microphone level, the devices to choose from, and what they chose, for a lobby such
|
|
4
|
+
* as `mj-camera-check` to show. It drives an {@link ILocalMediaController} (the browser's `LocalMediaController`, or a
|
|
5
|
+
* fake in tests) and a microphone meter, owns both, and releases them when disposed, so the call or the meeting opens
|
|
6
|
+
* the chosen devices itself.
|
|
7
|
+
*
|
|
8
|
+
* - **What starts.** The microphone starts on and the camera off, unless the options say otherwise.
|
|
9
|
+
* - **Devices.** Picking a device moves a live kind to it at once; a kind that is off starts on it later. Until the
|
|
10
|
+
* user picks, the choice is the device in use, else the first one listed.
|
|
11
|
+
* - **Failures.** A kind that fails to start is turned off in the choices, with the reason in its state.
|
|
12
|
+
*
|
|
13
|
+
* The realtime call checks the camera inside the call instead (`RealtimeCaptures`), since its stream carries on into
|
|
14
|
+
* the call; this preview is for a lobby whose devices are released before joining.
|
|
15
|
+
*
|
|
16
|
+
* @module @memberjunction/ai-realtime-client/media
|
|
17
|
+
*/
|
|
18
|
+
import { type Observable } from 'rxjs';
|
|
19
|
+
import { type IRealtimeAudioMeter } from '../audio/audioMeter.js';
|
|
20
|
+
import type { ILocalMediaController } from './localMediaController.js';
|
|
21
|
+
import type { LocalTrackState, MediaDevice, MediaDeviceSelection, MediaVideoSource } from './model.js';
|
|
22
|
+
/** What the user chose in the preview, for the call or the meeting to open. */
|
|
23
|
+
export interface MediaPreviewChoices {
|
|
24
|
+
MicrophoneOn: boolean;
|
|
25
|
+
CameraOn: boolean;
|
|
26
|
+
/** The microphone to use, or `null` when none is listed. */
|
|
27
|
+
MicrophoneDeviceID: string | null;
|
|
28
|
+
/** The camera to use, or `null` when none is listed. */
|
|
29
|
+
CameraDeviceID: string | null;
|
|
30
|
+
}
|
|
31
|
+
/** How a preview starts. */
|
|
32
|
+
export interface MediaPreviewOptions {
|
|
33
|
+
/** Whether the microphone starts on. Defaults to `true`. */
|
|
34
|
+
MicrophoneOn?: boolean;
|
|
35
|
+
/** Whether the camera starts on. Defaults to `false`. */
|
|
36
|
+
CameraOn?: boolean;
|
|
37
|
+
/** Meters the microphone's stream. Defaults to `RealtimeAudioMeter.ForMicStream`; a test passes its own. */
|
|
38
|
+
MeterFor?: (stream: MediaStream) => IRealtimeAudioMeter | null;
|
|
39
|
+
}
|
|
40
|
+
/** The preview now: what a lobby shows. */
|
|
41
|
+
export interface MediaPreviewState {
|
|
42
|
+
/** The camera to show, while it is on. The same object across device switches. */
|
|
43
|
+
CameraSource: MediaVideoSource | null;
|
|
44
|
+
/** The microphones and cameras to choose from. */
|
|
45
|
+
Devices: readonly MediaDevice[];
|
|
46
|
+
/** What the user chose. */
|
|
47
|
+
Choices: MediaPreviewChoices;
|
|
48
|
+
/** The camera's capture, for a failure to show. */
|
|
49
|
+
Camera: LocalTrackState;
|
|
50
|
+
/** The microphone's capture, for a failure to show. */
|
|
51
|
+
Microphone: LocalTrackState;
|
|
52
|
+
}
|
|
53
|
+
/** The user's camera and microphone in a lobby: see the file header. */
|
|
54
|
+
export declare class MediaPreview {
|
|
55
|
+
private readonly controller;
|
|
56
|
+
private readonly state;
|
|
57
|
+
private readonly watch;
|
|
58
|
+
private readonly meterFor;
|
|
59
|
+
private meter;
|
|
60
|
+
private cameraSource;
|
|
61
|
+
private choices;
|
|
62
|
+
/**
|
|
63
|
+
* @param controller The camera and microphone. The preview owns it from here, and disposes it with itself.
|
|
64
|
+
* @param options What starts, and how the microphone is metered.
|
|
65
|
+
*/
|
|
66
|
+
constructor(controller: ILocalMediaController, options?: MediaPreviewOptions);
|
|
67
|
+
/** The preview now. */
|
|
68
|
+
get State(): MediaPreviewState;
|
|
69
|
+
/** The preview, now and on every change. Completes on {@link Dispose}. */
|
|
70
|
+
get State$(): Observable<MediaPreviewState>;
|
|
71
|
+
/** The microphone's level now, 0 to 1; 0 while it is off or cannot be metered. Pass it to a meter as its reader. */
|
|
72
|
+
readonly ReadMicrophoneLevel: () => number;
|
|
73
|
+
/** Starts the kinds the user starts with, then lists the devices (their names appear once access is allowed). */
|
|
74
|
+
Start(): Promise<void>;
|
|
75
|
+
/** Turns the camera on or off. */
|
|
76
|
+
SetCameraOn(on: boolean): Promise<void>;
|
|
77
|
+
/** Turns the microphone on or off. */
|
|
78
|
+
SetMicrophoneOn(on: boolean): Promise<void>;
|
|
79
|
+
/** Picks a device. A live kind moves to it at once; a kind that is off starts on it later. Speakers are ignored. */
|
|
80
|
+
SelectDevice(selection: MediaDeviceSelection): Promise<void>;
|
|
81
|
+
/** Stops the camera and the microphone, closes the meter, disposes the controller, and completes {@link State$}. */
|
|
82
|
+
Dispose(): void;
|
|
83
|
+
private setOn;
|
|
84
|
+
/** Starts a kind on the chosen device; a failure turns it off in the choices. */
|
|
85
|
+
private startKind;
|
|
86
|
+
private stopKind;
|
|
87
|
+
private remeter;
|
|
88
|
+
private closeMeter;
|
|
89
|
+
/** Publishes the state; after {@link Dispose} the completed subject ignores it. */
|
|
90
|
+
private publish;
|
|
91
|
+
/** The state from the controller's: the choices fall back to the device in use, else the first one listed. */
|
|
92
|
+
private snapshot;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=mediaPreview.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mediaPreview.d.ts","sourceRoot":"","sources":["../../src/media/mediaPreview.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAmB,KAAK,UAAU,EAAqB,MAAM,MAAM,CAAC;AAC3E,OAAO,EAAsB,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACnF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,KAAK,EAAmC,eAAe,EAAE,WAAW,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAErI,+EAA+E;AAC/E,MAAM,WAAW,mBAAmB;IAChC,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,4DAA4D;IAC5D,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,wDAAwD;IACxD,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,4BAA4B;AAC5B,MAAM,WAAW,mBAAmB;IAChC,4DAA4D;IAC5D,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4GAA4G;IAC5G,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,mBAAmB,GAAG,IAAI,CAAC;CAClE;AAED,2CAA2C;AAC3C,MAAM,WAAW,iBAAiB;IAC9B,kFAAkF;IAClF,YAAY,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACtC,kDAAkD;IAClD,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IAChC,2BAA2B;IAC3B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,mDAAmD;IACnD,MAAM,EAAE,eAAe,CAAC;IACxB,uDAAuD;IACvD,UAAU,EAAE,eAAe,CAAC;CAC/B;AAED,wEAAwE;AACxE,qBAAa,YAAY;IAajB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAZ/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqC;IAC3D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsD;IAC/E,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,OAAO,CAAsB;IAErC;;;OAGG;gBAEkB,UAAU,EAAE,qBAAqB,EAClD,OAAO,GAAE,mBAAwB;IAQrC,uBAAuB;IACvB,IAAW,KAAK,IAAI,iBAAiB,CAEpC;IAED,0EAA0E;IAC1E,IAAW,MAAM,IAAI,UAAU,CAAC,iBAAiB,CAAC,CAEjD;IAED,oHAAoH;IACpH,SAAgB,mBAAmB,QAAO,MAAM,CAA6B;IAE7E,iHAAiH;IACpG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAWnC,kCAAkC;IACrB,WAAW,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpD,sCAAsC;IACzB,eAAe,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxD,oHAAoH;IACvG,YAAY,CAAC,SAAS,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBzE,oHAAoH;IAC7G,OAAO,IAAI,IAAI;YAQR,KAAK;IAUnB,iFAAiF;YACnE,SAAS;IAcvB,OAAO,CAAC,QAAQ;IAShB,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,UAAU;IAKlB,mFAAmF;IACnF,OAAO,CAAC,OAAO;IAIf,8GAA8G;IAC9G,OAAO,CAAC,QAAQ;CAenB"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview MEDIA PREVIEW: the user's camera and microphone before they join a call or a meeting. It gives a
|
|
3
|
+
* camera to see themselves in, a microphone level, the devices to choose from, and what they chose, for a lobby such
|
|
4
|
+
* as `mj-camera-check` to show. It drives an {@link ILocalMediaController} (the browser's `LocalMediaController`, or a
|
|
5
|
+
* fake in tests) and a microphone meter, owns both, and releases them when disposed, so the call or the meeting opens
|
|
6
|
+
* the chosen devices itself.
|
|
7
|
+
*
|
|
8
|
+
* - **What starts.** The microphone starts on and the camera off, unless the options say otherwise.
|
|
9
|
+
* - **Devices.** Picking a device moves a live kind to it at once; a kind that is off starts on it later. Until the
|
|
10
|
+
* user picks, the choice is the device in use, else the first one listed.
|
|
11
|
+
* - **Failures.** A kind that fails to start is turned off in the choices, with the reason in its state.
|
|
12
|
+
*
|
|
13
|
+
* The realtime call checks the camera inside the call instead (`RealtimeCaptures`), since its stream carries on into
|
|
14
|
+
* the call; this preview is for a lobby whose devices are released before joining.
|
|
15
|
+
*
|
|
16
|
+
* @module @memberjunction/ai-realtime-client/media
|
|
17
|
+
*/
|
|
18
|
+
import { BehaviorSubject } from 'rxjs';
|
|
19
|
+
import { RealtimeAudioMeter } from '../audio/audioMeter.js';
|
|
20
|
+
/** The user's camera and microphone in a lobby: see the file header. */
|
|
21
|
+
export class MediaPreview {
|
|
22
|
+
/**
|
|
23
|
+
* @param controller The camera and microphone. The preview owns it from here, and disposes it with itself.
|
|
24
|
+
* @param options What starts, and how the microphone is metered.
|
|
25
|
+
*/
|
|
26
|
+
constructor(controller, options = {}) {
|
|
27
|
+
this.controller = controller;
|
|
28
|
+
this.meter = null;
|
|
29
|
+
this.cameraSource = null;
|
|
30
|
+
/** The microphone's level now, 0 to 1; 0 while it is off or cannot be metered. Pass it to a meter as its reader. */
|
|
31
|
+
this.ReadMicrophoneLevel = () => this.meter?.Level() ?? 0;
|
|
32
|
+
this.meterFor = options.MeterFor ?? ((stream) => RealtimeAudioMeter.ForMicStream(stream));
|
|
33
|
+
this.choices = { MicrophoneOn: options.MicrophoneOn ?? true, CameraOn: options.CameraOn ?? false, MicrophoneDeviceID: null, CameraDeviceID: null };
|
|
34
|
+
this.state = new BehaviorSubject(this.snapshot(controller.State));
|
|
35
|
+
this.watch = controller.State$.subscribe((media) => this.publish(media));
|
|
36
|
+
}
|
|
37
|
+
/** The preview now. */
|
|
38
|
+
get State() {
|
|
39
|
+
return this.state.value;
|
|
40
|
+
}
|
|
41
|
+
/** The preview, now and on every change. Completes on {@link Dispose}. */
|
|
42
|
+
get State$() {
|
|
43
|
+
return this.state.asObservable();
|
|
44
|
+
}
|
|
45
|
+
/** Starts the kinds the user starts with, then lists the devices (their names appear once access is allowed). */
|
|
46
|
+
async Start() {
|
|
47
|
+
if (this.choices.MicrophoneOn) {
|
|
48
|
+
await this.startKind('microphone');
|
|
49
|
+
}
|
|
50
|
+
if (this.choices.CameraOn) {
|
|
51
|
+
await this.startKind('camera');
|
|
52
|
+
}
|
|
53
|
+
await this.controller.RefreshDevices();
|
|
54
|
+
this.publish(this.controller.State);
|
|
55
|
+
}
|
|
56
|
+
/** Turns the camera on or off. */
|
|
57
|
+
async SetCameraOn(on) {
|
|
58
|
+
await this.setOn('camera', on);
|
|
59
|
+
}
|
|
60
|
+
/** Turns the microphone on or off. */
|
|
61
|
+
async SetMicrophoneOn(on) {
|
|
62
|
+
await this.setOn('microphone', on);
|
|
63
|
+
}
|
|
64
|
+
/** Picks a device. A live kind moves to it at once; a kind that is off starts on it later. Speakers are ignored. */
|
|
65
|
+
async SelectDevice(selection) {
|
|
66
|
+
if (selection.Kind === 'speaker') {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const kind = selection.Kind;
|
|
70
|
+
this.choices = kind === 'camera' ? { ...this.choices, CameraDeviceID: selection.DeviceID } : { ...this.choices, MicrophoneDeviceID: selection.DeviceID };
|
|
71
|
+
if (trackOf(this.controller.State, kind).Status === 'on') {
|
|
72
|
+
const result = await this.controller.SwitchDevice(kind, selection.DeviceID);
|
|
73
|
+
// The meter listens to a copy of the old track, so it follows the switch only when rebuilt.
|
|
74
|
+
if (kind === 'microphone' && result.Status === 'started') {
|
|
75
|
+
this.remeter(result.Stream);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
this.publish(this.controller.State);
|
|
79
|
+
}
|
|
80
|
+
/** Stops the camera and the microphone, closes the meter, disposes the controller, and completes {@link State$}. */
|
|
81
|
+
Dispose() {
|
|
82
|
+
this.watch.unsubscribe();
|
|
83
|
+
this.closeMeter();
|
|
84
|
+
this.cameraSource = null;
|
|
85
|
+
this.controller.Dispose();
|
|
86
|
+
this.state.complete();
|
|
87
|
+
}
|
|
88
|
+
async setOn(kind, on) {
|
|
89
|
+
this.choices = kind === 'camera' ? { ...this.choices, CameraOn: on } : { ...this.choices, MicrophoneOn: on };
|
|
90
|
+
if (on) {
|
|
91
|
+
await this.startKind(kind);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
this.stopKind(kind);
|
|
95
|
+
}
|
|
96
|
+
this.publish(this.controller.State);
|
|
97
|
+
}
|
|
98
|
+
/** Starts a kind on the chosen device; a failure turns it off in the choices. */
|
|
99
|
+
async startKind(kind) {
|
|
100
|
+
const deviceId = kind === 'camera' ? this.choices.CameraDeviceID : this.choices.MicrophoneDeviceID;
|
|
101
|
+
const result = await this.controller.Start(kind, deviceId ?? undefined);
|
|
102
|
+
if (result.Status !== 'started') {
|
|
103
|
+
this.choices = kind === 'camera' ? { ...this.choices, CameraOn: false } : { ...this.choices, MicrophoneOn: false };
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (kind === 'camera') {
|
|
107
|
+
this.cameraSource = { Kind: 'stream', Stream: result.Stream };
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
this.remeter(result.Stream);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
stopKind(kind) {
|
|
114
|
+
this.controller.Stop(kind);
|
|
115
|
+
if (kind === 'camera') {
|
|
116
|
+
this.cameraSource = null;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
this.closeMeter();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
remeter(stream) {
|
|
123
|
+
this.closeMeter();
|
|
124
|
+
this.meter = this.meterFor(stream);
|
|
125
|
+
}
|
|
126
|
+
closeMeter() {
|
|
127
|
+
this.meter?.Close();
|
|
128
|
+
this.meter = null;
|
|
129
|
+
}
|
|
130
|
+
/** Publishes the state; after {@link Dispose} the completed subject ignores it. */
|
|
131
|
+
publish(media) {
|
|
132
|
+
this.state.next(this.snapshot(media));
|
|
133
|
+
}
|
|
134
|
+
/** The state from the controller's: the choices fall back to the device in use, else the first one listed. */
|
|
135
|
+
snapshot(media) {
|
|
136
|
+
const devices = media.Devices;
|
|
137
|
+
const firstOf = (kind) => devices.find((d) => d.Kind === kind)?.DeviceID ?? null;
|
|
138
|
+
return {
|
|
139
|
+
CameraSource: this.cameraSource,
|
|
140
|
+
Devices: devices,
|
|
141
|
+
Choices: {
|
|
142
|
+
...this.choices,
|
|
143
|
+
MicrophoneDeviceID: this.choices.MicrophoneDeviceID ?? media.Microphone.DeviceID ?? firstOf('microphone'),
|
|
144
|
+
CameraDeviceID: this.choices.CameraDeviceID ?? media.Camera.DeviceID ?? firstOf('camera'),
|
|
145
|
+
},
|
|
146
|
+
Camera: media.Camera,
|
|
147
|
+
Microphone: media.Microphone,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function trackOf(media, kind) {
|
|
152
|
+
return kind === 'camera' ? media.Camera : media.Microphone;
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=mediaPreview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mediaPreview.js","sourceRoot":"","sources":["../../src/media/mediaPreview.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,eAAe,EAAsC,MAAM,MAAM,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAA4B,MAAM,qBAAqB,CAAC;AAsCnF,wEAAwE;AACxE,MAAM,OAAO,YAAY;IAQrB;;;OAGG;IACH,YACqB,UAAiC,EAClD,UAA+B,EAAE;QADhB,eAAU,GAAV,UAAU,CAAuB;QAT9C,UAAK,GAA+B,IAAI,CAAC;QACzC,iBAAY,GAA4B,IAAI,CAAC;QA2BrD,oHAAoH;QACpG,wBAAmB,GAAG,GAAW,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAjBzE,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,kBAAkB,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;QAC1F,IAAI,CAAC,OAAO,GAAG,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;QACnJ,IAAI,CAAC,KAAK,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;QAClE,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7E,CAAC;IAED,uBAAuB;IACvB,IAAW,KAAK;QACZ,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;IAC5B,CAAC;IAED,0EAA0E;IAC1E,IAAW,MAAM;QACb,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;IACrC,CAAC;IAKD,iHAAiH;IAC1G,KAAK,CAAC,KAAK;QACd,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;YAC5B,MAAM,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QACvC,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACxB,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACnC,CAAC;QACD,MAAM,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC;QACvC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,kCAAkC;IAC3B,KAAK,CAAC,WAAW,CAAC,EAAW;QAChC,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACnC,CAAC;IAED,sCAAsC;IAC/B,KAAK,CAAC,eAAe,CAAC,EAAW;QACpC,MAAM,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,oHAAoH;IAC7G,KAAK,CAAC,YAAY,CAAC,SAA+B;QACrD,IAAI,SAAS,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO;QACX,CAAC;QACD,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC;QAC5B,IAAI,CAAC,OAAO,GAAG,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,kBAAkB,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC;QACzJ,IAAI,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YACvD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;YAC5E,4FAA4F;YAC5F,IAAI,IAAI,KAAK,YAAY,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBACvD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAChC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,oHAAoH;IAC7G,OAAO;QACV,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QACzB,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;QAC1B,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC;IAEO,KAAK,CAAC,KAAK,CAAC,IAAoB,EAAE,EAAW;QACjD,IAAI,CAAC,OAAO,GAAG,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;QAC7G,IAAI,EAAE,EAAE,CAAC;YACL,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,iFAAiF;IACzE,KAAK,CAAC,SAAS,CAAC,IAAoB;QACxC,MAAM,QAAQ,GAAG,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC;QACnG,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,IAAI,SAAS,CAAC,CAAC;QACxE,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC9B,IAAI,CAAC,OAAO,GAAG,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;YACnH,OAAO;QACX,CAAC;QACD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACpB,IAAI,CAAC,YAAY,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QAClE,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC;IACL,CAAC;IAEO,QAAQ,CAAC,IAAoB;QACjC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACpB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QAC7B,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,UAAU,EAAE,CAAC;QACtB,CAAC;IACL,CAAC;IAEO,OAAO,CAAC,MAAmB;QAC/B,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAEO,UAAU;QACd,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC;QACpB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACtB,CAAC;IAED,mFAAmF;IAC3E,OAAO,CAAC,KAAsB;QAClC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED,8GAA8G;IACtG,QAAQ,CAAC,KAAsB;QACnC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAC9B,MAAM,OAAO,GAAG,CAAC,IAAoB,EAAiB,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,QAAQ,IAAI,IAAI,CAAC;QAChH,OAAO;YACH,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,OAAO,EAAE,OAAO;YAChB,OAAO,EAAE;gBACL,GAAG,IAAI,CAAC,OAAO;gBACf,kBAAkB,EAAE,IAAI,CAAC,OAAO,CAAC,kBAAkB,IAAI,KAAK,CAAC,UAAU,CAAC,QAAQ,IAAI,OAAO,CAAC,YAAY,CAAC;gBACzG,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,cAAc,IAAI,KAAK,CAAC,MAAM,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;aAC5F;YACD,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,UAAU,EAAE,KAAK,CAAC,UAAU;SAC/B,CAAC;IACN,CAAC;CACJ;AAED,SAAS,OAAO,CAAC,KAAsB,EAAE,IAAoB;IACzD,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC;AAC/D,CAAC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview MEDIA STAGE: a headless layout model. Participants, placeable surfaces and the user's moves go
|
|
3
|
+
* in; a layout comes out: one stage, a stack of picture-in-picture tiles, tabs, hidden surfaces, the other
|
|
4
|
+
* participants (for a filmstrip or grid), and a screen-share split. It knows nothing about Angular, the DOM,
|
|
5
|
+
* LiveKit or the realtime client, so the realtime overlay and the meeting room lay out the same way.
|
|
6
|
+
*
|
|
7
|
+
* Placement rules:
|
|
8
|
+
* - A surface goes where the user last moved it, if that placement is allowed for it; otherwise to its default.
|
|
9
|
+
* - **One stage.** The surface the user moved to the stage most recently wins it. A surface it displaces goes
|
|
10
|
+
* to its own default placement, or to a PiP when its default is also the stage. With no move, the first
|
|
11
|
+
* surface whose default is the stage keeps it, so a new surface never takes the stage on its own.
|
|
12
|
+
* - **PiPs stack** in one corner, newest first: the latest move first, then surfaces by when they appeared.
|
|
13
|
+
* - When no surface holds the stage, the spotlight participant does: a pin, then the active speaker, then a
|
|
14
|
+
* speaking participant, then the agent, then the first other participant, then the user.
|
|
15
|
+
* - A participant already shown through a surface on the stage or in a PiP (the avatar, the user's camera) is not
|
|
16
|
+
* repeated among the others, and one shown in a PiP does not take the spotlight: the next in line does.
|
|
17
|
+
*
|
|
18
|
+
* A host that lets the user move participants' tiles passes each as a surface ({@link ParticipantTileSurface}), as the
|
|
19
|
+
* meeting room does; a host with channel surfaces passes those, as the realtime call does.
|
|
20
|
+
*
|
|
21
|
+
* @module @memberjunction/ai-realtime-client/media
|
|
22
|
+
*/
|
|
23
|
+
import type { MediaParticipant, MediaPlacement, MediaPlacementMove, MediaSurface } from './model.js';
|
|
24
|
+
/** What the stage is laid out from. */
|
|
25
|
+
export interface MediaStageInput {
|
|
26
|
+
/** Everyone in the session. The local user has `Role: 'self'`. */
|
|
27
|
+
Participants: readonly MediaParticipant[];
|
|
28
|
+
/** Identities the platform reports as speaking, most recent first (a meeting room's active-speaker list). */
|
|
29
|
+
ActiveSpeakers?: readonly string[];
|
|
30
|
+
/** Surfaces that can be placed, in the order they appeared. */
|
|
31
|
+
Surfaces?: readonly MediaSurface[];
|
|
32
|
+
/** The user's moves, oldest first. Only each surface's latest move counts, so a host may keep just those, in order. */
|
|
33
|
+
Moves?: readonly MediaPlacementMove[];
|
|
34
|
+
/** A participant the user pinned to the stage. */
|
|
35
|
+
PinnedIdentity?: string | null;
|
|
36
|
+
/** Whether the user's own tile is among the other participants. Defaults to true. */
|
|
37
|
+
ShowSelfView?: boolean;
|
|
38
|
+
}
|
|
39
|
+
/** One tile: a placed surface, or a participant. */
|
|
40
|
+
export type MediaTile = {
|
|
41
|
+
Kind: 'surface';
|
|
42
|
+
Surface: MediaSurface;
|
|
43
|
+
} | {
|
|
44
|
+
Kind: 'participant';
|
|
45
|
+
Participant: MediaParticipant;
|
|
46
|
+
};
|
|
47
|
+
/** Where everything goes. */
|
|
48
|
+
export interface MediaStageLayout {
|
|
49
|
+
/** What fills the stage: a surface placed there, else the spotlight participant; null for an empty session. */
|
|
50
|
+
Stage: MediaTile | null;
|
|
51
|
+
/** Picture-in-picture surfaces, newest first. */
|
|
52
|
+
Pips: readonly MediaSurface[];
|
|
53
|
+
/** Surfaces shown as tabs, in the order they appeared. */
|
|
54
|
+
Tabs: readonly MediaSurface[];
|
|
55
|
+
/** Surfaces the user hid, so the UI can offer them back. */
|
|
56
|
+
Hidden: readonly MediaSurface[];
|
|
57
|
+
/** Participants not already on screen (on the stage or in a PiP), for a filmstrip or grid; the user first when shown. */
|
|
58
|
+
Others: readonly MediaParticipant[];
|
|
59
|
+
/** The screen being shared and the current speaker, for a split view; null when nobody is sharing. */
|
|
60
|
+
Split: {
|
|
61
|
+
Sharer: MediaParticipant;
|
|
62
|
+
Speaker: MediaParticipant | null;
|
|
63
|
+
} | null;
|
|
64
|
+
}
|
|
65
|
+
/** The key a participant's tile is moved under, so it never collides with a channel's surface key. */
|
|
66
|
+
export declare function ParticipantTileKey(identity: string): string;
|
|
67
|
+
/**
|
|
68
|
+
* A participant's tile as a surface the user can move: among the others (`tab`, a filmstrip or grid) until moved,
|
|
69
|
+
* showing the participant's camera, within the places the host offers (every placement when it names none).
|
|
70
|
+
*/
|
|
71
|
+
export declare function ParticipantTileSurface(participant: MediaParticipant, allowed?: readonly MediaPlacement[]): MediaSurface;
|
|
72
|
+
/** Who fills the stage: the participant a surface on it shows (a tile moved there, an avatar), else the spotlight participant. */
|
|
73
|
+
export declare function StageParticipantIdentity(stage: MediaTile | null): string | null;
|
|
74
|
+
/** Lays out the stage. Pure: the same input always gives the same layout. */
|
|
75
|
+
export declare function LayoutMediaStage(input: MediaStageInput): MediaStageLayout;
|
|
76
|
+
/** Each surface's placement after the user's moves, with the one-stage and PiP-order rules applied. */
|
|
77
|
+
export declare function ResolveSurfacePlacements(surfaces: readonly MediaSurface[], moves: readonly MediaPlacementMove[]): {
|
|
78
|
+
Stage: MediaSurface | null;
|
|
79
|
+
Pips: MediaSurface[];
|
|
80
|
+
Tabs: MediaSurface[];
|
|
81
|
+
Hidden: MediaSurface[];
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* The spotlight participant: a pin, then the active speaker, then a speaking participant, then the agent, then
|
|
85
|
+
* the first other participant, then the user.
|
|
86
|
+
*/
|
|
87
|
+
export declare function SelectSpotlight(participants: readonly MediaParticipant[], activeSpeakers: readonly string[], pinnedIdentity: string | null): MediaParticipant | null;
|
|
88
|
+
/** The participants to show in a filmstrip or grid: the user first, when shown. */
|
|
89
|
+
export declare function SelectDisplayParticipants(participants: readonly MediaParticipant[], showSelfView: boolean): MediaParticipant[];
|
|
90
|
+
/** The first participant sharing a screen, if any. */
|
|
91
|
+
export declare function SelectScreenSharer(participants: readonly MediaParticipant[]): MediaParticipant | null;
|
|
92
|
+
/** The speaker pane beside a shared screen: the active speaker other than the sharer, then the agent, then the first other non-sharer, then the user. */
|
|
93
|
+
export declare function SelectSplitSpeaker(participants: readonly MediaParticipant[], activeSpeakers: readonly string[]): MediaParticipant | null;
|
|
94
|
+
/**
|
|
95
|
+
* Where a surface goes when it leaves the stage, displaced by another or sent off it: its default, or the first allowed of
|
|
96
|
+
* PiP, tab, hidden.
|
|
97
|
+
*/
|
|
98
|
+
export declare function PlacementOffStage(surface: MediaSurface): MediaPlacement;
|
|
99
|
+
//# sourceMappingURL=mediaStage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mediaStage.d.ts","sourceRoot":"","sources":["../../src/media/mediaStage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview MEDIA STAGE: a headless layout model. Participants, placeable surfaces and the user's moves go
|
|
3
|
+
* in; a layout comes out: one stage, a stack of picture-in-picture tiles, tabs, hidden surfaces, the other
|
|
4
|
+
* participants (for a filmstrip or grid), and a screen-share split. It knows nothing about Angular, the DOM,
|
|
5
|
+
* LiveKit or the realtime client, so the realtime overlay and the meeting room lay out the same way.
|
|
6
|
+
*
|
|
7
|
+
* Placement rules:
|
|
8
|
+
* - A surface goes where the user last moved it, if that placement is allowed for it; otherwise to its default.
|
|
9
|
+
* - **One stage.** The surface the user moved to the stage most recently wins it. A surface it displaces goes
|
|
10
|
+
* to its own default placement, or to a PiP when its default is also the stage. With no move, the first
|
|
11
|
+
* surface whose default is the stage keeps it, so a new surface never takes the stage on its own.
|
|
12
|
+
* - **PiPs stack** in one corner, newest first: the latest move first, then surfaces by when they appeared.
|
|
13
|
+
* - When no surface holds the stage, the spotlight participant does: a pin, then the active speaker, then a
|
|
14
|
+
* speaking participant, then the agent, then the first other participant, then the user.
|
|
15
|
+
* - A participant already shown through a surface on the stage or in a PiP (the avatar, the user's camera) is not
|
|
16
|
+
* repeated among the others, and one shown in a PiP does not take the spotlight: the next in line does.
|
|
17
|
+
*
|
|
18
|
+
* A host that lets the user move participants' tiles passes each as a surface ({@link ParticipantTileSurface}), as the
|
|
19
|
+
* meeting room does; a host with channel surfaces passes those, as the realtime call does.
|
|
20
|
+
*
|
|
21
|
+
* @module @memberjunction/ai-realtime-client/media
|
|
22
|
+
*/
|
|
23
|
+
import { MEDIA_PLACEMENTS } from './model.js';
|
|
24
|
+
/** The key a participant's tile is moved under, so it never collides with a channel's surface key. */
|
|
25
|
+
export function ParticipantTileKey(identity) {
|
|
26
|
+
return `participant:${identity}`;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A participant's tile as a surface the user can move: among the others (`tab`, a filmstrip or grid) until moved,
|
|
30
|
+
* showing the participant's camera, within the places the host offers (every placement when it names none).
|
|
31
|
+
*/
|
|
32
|
+
export function ParticipantTileSurface(participant, allowed) {
|
|
33
|
+
return {
|
|
34
|
+
Key: ParticipantTileKey(participant.Identity),
|
|
35
|
+
Label: participant.DisplayName,
|
|
36
|
+
DefaultPlacement: 'tab',
|
|
37
|
+
...(allowed ? { AllowedPlacements: allowed } : {}),
|
|
38
|
+
Video: { ParticipantIdentity: participant.Identity, Kind: 'camera' },
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/** Who fills the stage: the participant a surface on it shows (a tile moved there, an avatar), else the spotlight participant. */
|
|
42
|
+
export function StageParticipantIdentity(stage) {
|
|
43
|
+
if (stage?.Kind === 'surface') {
|
|
44
|
+
return stage.Surface.Video?.ParticipantIdentity ?? null;
|
|
45
|
+
}
|
|
46
|
+
return stage?.Participant.Identity ?? null;
|
|
47
|
+
}
|
|
48
|
+
/** Lays out the stage. Pure: the same input always gives the same layout. */
|
|
49
|
+
export function LayoutMediaStage(input) {
|
|
50
|
+
const placed = ResolveSurfacePlacements(input.Surfaces ?? [], input.Moves ?? []);
|
|
51
|
+
const inPips = new Set(placed.Pips.flatMap((s) => (s.Video ? [s.Video.ParticipantIdentity] : [])));
|
|
52
|
+
const candidates = input.Participants.filter((p) => !inPips.has(p.Identity));
|
|
53
|
+
const spotlight = placed.Stage ? null : SelectSpotlight(candidates, input.ActiveSpeakers ?? [], input.PinnedIdentity ?? null);
|
|
54
|
+
const onScreen = new Set([placed.Stage, ...placed.Pips].flatMap((s) => (s?.Video ? [s.Video.ParticipantIdentity] : [])));
|
|
55
|
+
if (spotlight) {
|
|
56
|
+
onScreen.add(spotlight.Identity);
|
|
57
|
+
}
|
|
58
|
+
const shown = SelectDisplayParticipants(input.Participants, input.ShowSelfView ?? true);
|
|
59
|
+
return {
|
|
60
|
+
Stage: placed.Stage ? { Kind: 'surface', Surface: placed.Stage } : spotlight ? { Kind: 'participant', Participant: spotlight } : null,
|
|
61
|
+
Pips: placed.Pips,
|
|
62
|
+
Tabs: placed.Tabs,
|
|
63
|
+
Hidden: placed.Hidden,
|
|
64
|
+
Others: shown.filter((p) => !onScreen.has(p.Identity)),
|
|
65
|
+
Split: selectSplit(input.Participants, input.ActiveSpeakers ?? []),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/** Each surface's placement after the user's moves, with the one-stage and PiP-order rules applied. */
|
|
69
|
+
export function ResolveSurfacePlacements(surfaces, moves) {
|
|
70
|
+
const latestMove = latestMoves(surfaces, moves);
|
|
71
|
+
const wanted = new Map(surfaces.map((s) => [s.Key, latestMove.get(s.Key)?.Placement ?? s.DefaultPlacement]));
|
|
72
|
+
const stage = pickStage(surfaces, wanted, latestMove);
|
|
73
|
+
const result = { Stage: stage, Pips: [], Tabs: [], Hidden: [] };
|
|
74
|
+
for (const surface of surfaces) {
|
|
75
|
+
if (surface === stage) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const placement = wanted.get(surface.Key) === 'stage' ? PlacementOffStage(surface) : (wanted.get(surface.Key) ?? surface.DefaultPlacement);
|
|
79
|
+
if (placement === 'pip') {
|
|
80
|
+
result.Pips.push(surface);
|
|
81
|
+
}
|
|
82
|
+
else if (placement === 'tab') {
|
|
83
|
+
result.Tabs.push(surface);
|
|
84
|
+
}
|
|
85
|
+
else if (placement === 'hidden') {
|
|
86
|
+
result.Hidden.push(surface);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
result.Pips.sort((a, b) => recency(b, surfaces, latestMove) - recency(a, surfaces, latestMove));
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The spotlight participant: a pin, then the active speaker, then a speaking participant, then the agent, then
|
|
94
|
+
* the first other participant, then the user.
|
|
95
|
+
*/
|
|
96
|
+
export function SelectSpotlight(participants, activeSpeakers, pinnedIdentity) {
|
|
97
|
+
const pinned = pinnedIdentity ? participants.find((p) => p.Identity === pinnedIdentity) : undefined;
|
|
98
|
+
if (pinned) {
|
|
99
|
+
return pinned;
|
|
100
|
+
}
|
|
101
|
+
const others = participants.filter((p) => p.Role !== 'self');
|
|
102
|
+
const speakerId = activeSpeakers.find((id) => others.some((p) => p.Identity === id));
|
|
103
|
+
// The platform's active-speaker list can miss a server-published agent; a participant's own speaking flag
|
|
104
|
+
// catches it.
|
|
105
|
+
const speaking = (speakerId ? others.find((p) => p.Identity === speakerId) : undefined) ?? others.find((p) => p.IsSpeaking);
|
|
106
|
+
return speaking ?? others.find((p) => p.Role === 'agent') ?? others[0] ?? participants.find((p) => p.Role === 'self') ?? null;
|
|
107
|
+
}
|
|
108
|
+
/** The participants to show in a filmstrip or grid: the user first, when shown. */
|
|
109
|
+
export function SelectDisplayParticipants(participants, showSelfView) {
|
|
110
|
+
const self = participants.filter((p) => p.Role === 'self');
|
|
111
|
+
const others = participants.filter((p) => p.Role !== 'self');
|
|
112
|
+
return showSelfView ? [...self, ...others] : others;
|
|
113
|
+
}
|
|
114
|
+
/** The first participant sharing a screen, if any. */
|
|
115
|
+
export function SelectScreenSharer(participants) {
|
|
116
|
+
return participants.find((p) => p.Video.screen !== undefined) ?? null;
|
|
117
|
+
}
|
|
118
|
+
/** The speaker pane beside a shared screen: the active speaker other than the sharer, then the agent, then the first other non-sharer, then the user. */
|
|
119
|
+
export function SelectSplitSpeaker(participants, activeSpeakers) {
|
|
120
|
+
const sharerId = SelectScreenSharer(participants)?.Identity;
|
|
121
|
+
const speakerId = activeSpeakers.find((id) => id !== sharerId && participants.some((p) => p.Identity === id));
|
|
122
|
+
const speaking = (speakerId ? participants.find((p) => p.Identity === speakerId) : undefined) ??
|
|
123
|
+
participants.find((p) => p.IsSpeaking && p.Identity !== sharerId);
|
|
124
|
+
const others = participants.filter((p) => p.Role !== 'self');
|
|
125
|
+
return speaking ?? others.find((p) => p.Role === 'agent') ?? others.find((p) => p.Identity !== sharerId) ?? participants.find((p) => p.Role === 'self') ?? null;
|
|
126
|
+
}
|
|
127
|
+
function selectSplit(participants, activeSpeakers) {
|
|
128
|
+
const sharer = SelectScreenSharer(participants);
|
|
129
|
+
return sharer ? { Sharer: sharer, Speaker: SelectSplitSpeaker(participants, activeSpeakers) } : null;
|
|
130
|
+
}
|
|
131
|
+
/** Whether a placement is allowed for a surface. */
|
|
132
|
+
function allows(surface, placement) {
|
|
133
|
+
return !surface.AllowedPlacements || surface.AllowedPlacements.includes(placement);
|
|
134
|
+
}
|
|
135
|
+
/** Each live surface's latest allowed move, with its position in the move list (its recency). */
|
|
136
|
+
function latestMoves(surfaces, moves) {
|
|
137
|
+
const byKey = new Map(surfaces.map((s) => [s.Key, s]));
|
|
138
|
+
const latest = new Map();
|
|
139
|
+
moves.forEach((move, order) => {
|
|
140
|
+
const surface = byKey.get(move.SurfaceKey);
|
|
141
|
+
if (surface && allows(surface, move.Placement)) {
|
|
142
|
+
latest.set(move.SurfaceKey, { Placement: move.Placement, Order: order });
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
return latest;
|
|
146
|
+
}
|
|
147
|
+
/** The stage holder: the latest move to the stage, else the first surface whose default is the stage. */
|
|
148
|
+
function pickStage(surfaces, wanted, latestMove) {
|
|
149
|
+
const contenders = surfaces.filter((s) => wanted.get(s.Key) === 'stage');
|
|
150
|
+
const moved = contenders.filter((s) => latestMove.get(s.Key)?.Placement === 'stage');
|
|
151
|
+
if (moved.length > 0) {
|
|
152
|
+
return moved.reduce((a, b) => ((latestMove.get(b.Key)?.Order ?? -1) > (latestMove.get(a.Key)?.Order ?? -1) ? b : a));
|
|
153
|
+
}
|
|
154
|
+
return contenders[0] ?? null;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Where a surface goes when it leaves the stage, displaced by another or sent off it: its default, or the first allowed of
|
|
158
|
+
* PiP, tab, hidden.
|
|
159
|
+
*/
|
|
160
|
+
export function PlacementOffStage(surface) {
|
|
161
|
+
if (surface.DefaultPlacement !== 'stage' && allows(surface, surface.DefaultPlacement)) {
|
|
162
|
+
return surface.DefaultPlacement;
|
|
163
|
+
}
|
|
164
|
+
return MEDIA_PLACEMENTS.slice(1).find((p) => allows(surface, p)) ?? 'hidden';
|
|
165
|
+
}
|
|
166
|
+
/** Higher is newer: a move outranks appearance order, and a later move outranks an earlier one. */
|
|
167
|
+
function recency(surface, surfaces, latestMove) {
|
|
168
|
+
const move = latestMove.get(surface.Key);
|
|
169
|
+
return move ? surfaces.length + move.Order : surfaces.indexOf(surface);
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=mediaStage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mediaStage.js","sourceRoot":"","sources":["../../src/media/mediaStage.ts"],"names":[],"mappings":"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"}
|