@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frameCapture.js","sourceRoot":"","sources":["../../src/media/frameCapture.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"frameCapture.js","sourceRoot":"","sources":["../../src/media/frameCapture.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview FRAME SAMPLER: takes still frames from any `MediaStream` at the rate the caller asks
|
|
3
|
+
* for, and returns each as a base64 JPEG or PNG.
|
|
4
|
+
*
|
|
5
|
+
* The rate is the caller's: pass the rate the inbound video track negotiated
|
|
6
|
+
* (`BaseRealtimeClient.InboundVideoRate`). The sampler applies no ceiling of its own, so the stream itself
|
|
7
|
+
* can run at its native frame rate (a smooth self-view) while the model receives only the frames it can
|
|
8
|
+
* take. An absent or invalid rate means one frame per second, like every pacer in this package
|
|
9
|
+
* ({@link NominalVideoFrameIntervalMs}).
|
|
10
|
+
*
|
|
11
|
+
* Frames are drawn from a hidden `<video>` onto a `<canvas>`. Without a DOM (Node, SSR) the sampler emits
|
|
12
|
+
* nothing, and {@link FrameSampler.Start} says so by returning `false`.
|
|
13
|
+
*
|
|
14
|
+
* @module @memberjunction/ai-realtime-client/media
|
|
15
|
+
*/
|
|
16
|
+
/** Image formats a frame can be encoded as. */
|
|
17
|
+
export type SampledFrameMimeType = 'image/jpeg' | 'image/png';
|
|
18
|
+
/** A width and height in pixels. */
|
|
19
|
+
export interface FrameSize {
|
|
20
|
+
Width: number;
|
|
21
|
+
Height: number;
|
|
22
|
+
}
|
|
23
|
+
/** One frame taken from the stream. */
|
|
24
|
+
export interface SampledFrame {
|
|
25
|
+
/** The encoded image, base64 (no `data:` prefix). */
|
|
26
|
+
Data: string;
|
|
27
|
+
MimeType: SampledFrameMimeType;
|
|
28
|
+
/** The encoded image's width in pixels, after any {@link FrameSamplerOptions.MaxDimension} scaling. */
|
|
29
|
+
Width: number;
|
|
30
|
+
/** The encoded image's height in pixels, after any scaling. */
|
|
31
|
+
Height: number;
|
|
32
|
+
/** Epoch milliseconds when the frame was taken. */
|
|
33
|
+
TimestampMs: number;
|
|
34
|
+
}
|
|
35
|
+
export interface FrameSamplerOptions {
|
|
36
|
+
/**
|
|
37
|
+
* Frames per second. Pass the rate the inbound video track negotiated; there is no ceiling. An
|
|
38
|
+
* absent, zero, negative or non-finite rate means one frame per second.
|
|
39
|
+
*/
|
|
40
|
+
Rate: number;
|
|
41
|
+
/** Defaults to `'image/jpeg'`. */
|
|
42
|
+
MimeType?: SampledFrameMimeType;
|
|
43
|
+
/** JPEG quality from 0 to 1. Defaults to 0.8. Ignored for PNG. */
|
|
44
|
+
Quality?: number;
|
|
45
|
+
/**
|
|
46
|
+
* Caps the longer side of each frame, in pixels, keeping the aspect ratio. A smaller frame is never
|
|
47
|
+
* enlarged. Defaults to no cap: frames are encoded at the stream's own size.
|
|
48
|
+
*/
|
|
49
|
+
MaxDimension?: number;
|
|
50
|
+
/** Receives each frame. */
|
|
51
|
+
OnFrame: (frame: SampledFrame) => void;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The size a frame is encoded at: its own size, or scaled down so the longer side is at most
|
|
55
|
+
* `maxDimension` pixels. Never enlarges, and never returns a side smaller than 1. The math is
|
|
56
|
+
* `@memberjunction/ai`'s `ScaleRealtimeVideoFrame`, shared with the meeting bot.
|
|
57
|
+
*
|
|
58
|
+
* @param size The frame's own size.
|
|
59
|
+
* @param maxDimension The cap on the longer side; `undefined` or a non-positive value means no cap.
|
|
60
|
+
*/
|
|
61
|
+
export declare function ScaleToMaxDimension(size: FrameSize, maxDimension?: number): FrameSize;
|
|
62
|
+
/**
|
|
63
|
+
* Samples still frames from a `MediaStream`. The caller owns the stream: {@link FrameSampler.Stop}
|
|
64
|
+
* releases the sampler's elements and timer but never stops the stream's tracks.
|
|
65
|
+
*/
|
|
66
|
+
export declare class FrameSampler {
|
|
67
|
+
private readonly stream;
|
|
68
|
+
private readonly options;
|
|
69
|
+
private readonly intervalMs;
|
|
70
|
+
private timer;
|
|
71
|
+
private video;
|
|
72
|
+
private canvas;
|
|
73
|
+
/**
|
|
74
|
+
* @param stream The stream to sample. Its first video track is drawn.
|
|
75
|
+
* @param options Rate, format, size cap and the frame callback.
|
|
76
|
+
*/
|
|
77
|
+
constructor(stream: MediaStream, options: FrameSamplerOptions);
|
|
78
|
+
/** The stream being sampled. */
|
|
79
|
+
get Stream(): MediaStream;
|
|
80
|
+
/** Whether the sampler is taking frames. */
|
|
81
|
+
get IsRunning(): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Starts taking frames. Calling it while running does nothing.
|
|
84
|
+
*
|
|
85
|
+
* @returns `false` when there is no DOM to draw frames in, so no frames will come.
|
|
86
|
+
*/
|
|
87
|
+
Start(): boolean;
|
|
88
|
+
/** Stops taking frames and releases the elements. The stream's tracks keep running. */
|
|
89
|
+
Stop(): void;
|
|
90
|
+
private createElements;
|
|
91
|
+
/** Draws and encodes the current frame. Skips the tick until the video has a frame to draw. */
|
|
92
|
+
private sampleFrame;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=frameSampler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frameSampler.d.ts","sourceRoot":"","sources":["../../src/media/frameSampler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,+CAA+C;AAC/C,MAAM,MAAM,oBAAoB,GAAG,YAAY,GAAG,WAAW,CAAC;AAE9D,oCAAoC;AACpC,MAAM,WAAW,SAAS;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,uCAAuC;AACvC,MAAM,WAAW,YAAY;IACzB,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,uGAAuG;IACvG,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAChC;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2BAA2B;IAC3B,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;CAC1C;AAKD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAErF;AAED;;;GAGG;AACH,qBAAa,YAAY;IAWjB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAX5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,MAAM,CAAkC;IAEhD;;;OAGG;gBAEkB,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,mBAAmB;IAKjD,gCAAgC;IAChC,IAAW,MAAM,IAAI,WAAW,CAE/B;IAED,4CAA4C;IAC5C,IAAW,SAAS,IAAI,OAAO,CAE9B;IAED;;;;OAIG;IACI,KAAK,IAAI,OAAO;IAYvB,uFAAuF;IAChF,IAAI,IAAI,IAAI;IAkBnB,OAAO,CAAC,cAAc;IAsBtB,+FAA+F;IAC/F,OAAO,CAAC,WAAW;CAoBtB"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview FRAME SAMPLER: takes still frames from any `MediaStream` at the rate the caller asks
|
|
3
|
+
* for, and returns each as a base64 JPEG or PNG.
|
|
4
|
+
*
|
|
5
|
+
* The rate is the caller's: pass the rate the inbound video track negotiated
|
|
6
|
+
* (`BaseRealtimeClient.InboundVideoRate`). The sampler applies no ceiling of its own, so the stream itself
|
|
7
|
+
* can run at its native frame rate (a smooth self-view) while the model receives only the frames it can
|
|
8
|
+
* take. An absent or invalid rate means one frame per second, like every pacer in this package
|
|
9
|
+
* ({@link NominalVideoFrameIntervalMs}).
|
|
10
|
+
*
|
|
11
|
+
* Frames are drawn from a hidden `<video>` onto a `<canvas>`. Without a DOM (Node, SSR) the sampler emits
|
|
12
|
+
* nothing, and {@link FrameSampler.Start} says so by returning `false`.
|
|
13
|
+
*
|
|
14
|
+
* @module @memberjunction/ai-realtime-client/media
|
|
15
|
+
*/
|
|
16
|
+
import { ScaleRealtimeVideoFrame } from '@memberjunction/ai';
|
|
17
|
+
import { NominalVideoFrameIntervalMs } from './videoPacing.js';
|
|
18
|
+
/** JPEG quality when the caller doesn't set one. */
|
|
19
|
+
const DEFAULT_JPEG_QUALITY = 0.8;
|
|
20
|
+
/**
|
|
21
|
+
* The size a frame is encoded at: its own size, or scaled down so the longer side is at most
|
|
22
|
+
* `maxDimension` pixels. Never enlarges, and never returns a side smaller than 1. The math is
|
|
23
|
+
* `@memberjunction/ai`'s `ScaleRealtimeVideoFrame`, shared with the meeting bot.
|
|
24
|
+
*
|
|
25
|
+
* @param size The frame's own size.
|
|
26
|
+
* @param maxDimension The cap on the longer side; `undefined` or a non-positive value means no cap.
|
|
27
|
+
*/
|
|
28
|
+
export function ScaleToMaxDimension(size, maxDimension) {
|
|
29
|
+
return ScaleRealtimeVideoFrame(size, maxDimension);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Samples still frames from a `MediaStream`. The caller owns the stream: {@link FrameSampler.Stop}
|
|
33
|
+
* releases the sampler's elements and timer but never stops the stream's tracks.
|
|
34
|
+
*/
|
|
35
|
+
export class FrameSampler {
|
|
36
|
+
/**
|
|
37
|
+
* @param stream The stream to sample. Its first video track is drawn.
|
|
38
|
+
* @param options Rate, format, size cap and the frame callback.
|
|
39
|
+
*/
|
|
40
|
+
constructor(stream, options) {
|
|
41
|
+
this.stream = stream;
|
|
42
|
+
this.options = options;
|
|
43
|
+
this.timer = null;
|
|
44
|
+
this.video = null;
|
|
45
|
+
this.canvas = null;
|
|
46
|
+
this.intervalMs = NominalVideoFrameIntervalMs(options.Rate);
|
|
47
|
+
}
|
|
48
|
+
/** The stream being sampled. */
|
|
49
|
+
get Stream() {
|
|
50
|
+
return this.stream;
|
|
51
|
+
}
|
|
52
|
+
/** Whether the sampler is taking frames. */
|
|
53
|
+
get IsRunning() {
|
|
54
|
+
return this.timer !== null;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Starts taking frames. Calling it while running does nothing.
|
|
58
|
+
*
|
|
59
|
+
* @returns `false` when there is no DOM to draw frames in, so no frames will come.
|
|
60
|
+
*/
|
|
61
|
+
Start() {
|
|
62
|
+
if (this.timer) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
if (!this.createElements()) {
|
|
66
|
+
console.warn('[FrameSampler] No DOM to draw frames in, or element creation failed: this sampler emits no frames.');
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
this.timer = setInterval(() => this.sampleFrame(), this.intervalMs);
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
/** Stops taking frames and releases the elements. The stream's tracks keep running. */
|
|
73
|
+
Stop() {
|
|
74
|
+
if (this.timer) {
|
|
75
|
+
clearInterval(this.timer);
|
|
76
|
+
this.timer = null;
|
|
77
|
+
}
|
|
78
|
+
if (this.video) {
|
|
79
|
+
this.video.pause();
|
|
80
|
+
this.video.srcObject = null;
|
|
81
|
+
this.video = null;
|
|
82
|
+
}
|
|
83
|
+
if (this.canvas) {
|
|
84
|
+
// A zero-size canvas lets the browser free the backing store now rather than at collection.
|
|
85
|
+
this.canvas.width = 0;
|
|
86
|
+
this.canvas.height = 0;
|
|
87
|
+
this.canvas = null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
createElements() {
|
|
91
|
+
if (typeof document === 'undefined' || typeof document.createElement !== 'function') {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
const video = document.createElement('video');
|
|
96
|
+
video.muted = true;
|
|
97
|
+
video.playsInline = true;
|
|
98
|
+
video.srcObject = this.stream;
|
|
99
|
+
void video.play().catch(() => {
|
|
100
|
+
// Autoplay can wait for a user gesture; frames start once the video plays.
|
|
101
|
+
});
|
|
102
|
+
this.video = video;
|
|
103
|
+
this.canvas = document.createElement('canvas');
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
console.error('[FrameSampler] Failed to create the video and canvas elements:', err);
|
|
108
|
+
this.Stop();
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/** Draws and encodes the current frame. Skips the tick until the video has a frame to draw. */
|
|
113
|
+
sampleFrame() {
|
|
114
|
+
const video = this.video;
|
|
115
|
+
const canvas = this.canvas;
|
|
116
|
+
if (!video || !canvas || video.videoWidth <= 0 || video.videoHeight <= 0) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const size = ScaleToMaxDimension({ Width: video.videoWidth, Height: video.videoHeight }, this.options.MaxDimension);
|
|
120
|
+
canvas.width = size.Width;
|
|
121
|
+
canvas.height = size.Height;
|
|
122
|
+
const context = canvas.getContext('2d');
|
|
123
|
+
if (!context) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
context.drawImage(video, 0, 0, size.Width, size.Height);
|
|
127
|
+
const mimeType = this.options.MimeType ?? 'image/jpeg';
|
|
128
|
+
const data = canvas.toDataURL(mimeType, this.options.Quality ?? DEFAULT_JPEG_QUALITY).split(',')[1] ?? '';
|
|
129
|
+
if (data.length > 0) {
|
|
130
|
+
this.options.OnFrame({ Data: data, MimeType: mimeType, Width: size.Width, Height: size.Height, TimestampMs: Date.now() });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=frameSampler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frameSampler.js","sourceRoot":"","sources":["../../src/media/frameSampler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The `@memberjunction/ai-realtime-client/media` entry point: the browser media code that
|
|
3
|
+
* no provider driver sits behind (frame capture and sampling, display capture, the local camera and
|
|
4
|
+
* microphone controller, the video source arbiter, frame pacing, the channel video bridge, video playout and its
|
|
5
|
+
* decoder registry, the audio meter), and the media stage's layout model with the user's placement moves in their saved
|
|
6
|
+
* form.
|
|
7
|
+
*
|
|
8
|
+
* A consumer that only needs media, such as the LiveKit room, imports this entry and bundles no driver
|
|
9
|
+
* and no `@google/genai`. Everything reachable from here may import only other `/media` modules,
|
|
10
|
+
* `audio/audioMeter`, `@memberjunction/ai`, `@memberjunction/global` and `rxjs`; `media-entry-boundary.test.ts`
|
|
11
|
+
* fails the build otherwise. The main entry exports all of this too.
|
|
12
|
+
*
|
|
13
|
+
* @module @memberjunction/ai-realtime-client/media
|
|
14
|
+
*/
|
|
15
|
+
export * from './attachVideoSource.js';
|
|
16
|
+
export * from './frameCapture.js';
|
|
17
|
+
export * from './frameSampler.js';
|
|
18
|
+
export * from './localMediaController.js';
|
|
19
|
+
export * from './mediaStage.js';
|
|
20
|
+
export * from './mediaLayout.js';
|
|
21
|
+
export * from './mediaPreview.js';
|
|
22
|
+
export * from './model.js';
|
|
23
|
+
export * from './channelVideoSource.js';
|
|
24
|
+
export * from './displayCapture.js';
|
|
25
|
+
export * from './videoPacing.js';
|
|
26
|
+
export * from './videoPlayout.js';
|
|
27
|
+
export * from './playbackClock.js';
|
|
28
|
+
export * from './videoFrameDecoder.js';
|
|
29
|
+
export * from './videoFrameDecoderRegistry.js';
|
|
30
|
+
export * from './videoSourceArbiter.js';
|
|
31
|
+
export * from '../audio/audioMeter.js';
|
|
32
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/media/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,SAAS,CAAC;AACxB,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The `@memberjunction/ai-realtime-client/media` entry point: the browser media code that
|
|
3
|
+
* no provider driver sits behind (frame capture and sampling, display capture, the local camera and
|
|
4
|
+
* microphone controller, the video source arbiter, frame pacing, the channel video bridge, video playout and its
|
|
5
|
+
* decoder registry, the audio meter), and the media stage's layout model with the user's placement moves in their saved
|
|
6
|
+
* form.
|
|
7
|
+
*
|
|
8
|
+
* A consumer that only needs media, such as the LiveKit room, imports this entry and bundles no driver
|
|
9
|
+
* and no `@google/genai`. Everything reachable from here may import only other `/media` modules,
|
|
10
|
+
* `audio/audioMeter`, `@memberjunction/ai`, `@memberjunction/global` and `rxjs`; `media-entry-boundary.test.ts`
|
|
11
|
+
* fails the build otherwise. The main entry exports all of this too.
|
|
12
|
+
*
|
|
13
|
+
* @module @memberjunction/ai-realtime-client/media
|
|
14
|
+
*/
|
|
15
|
+
export * from './attachVideoSource.js';
|
|
16
|
+
export * from './frameCapture.js';
|
|
17
|
+
export * from './frameSampler.js';
|
|
18
|
+
export * from './localMediaController.js';
|
|
19
|
+
export * from './mediaStage.js';
|
|
20
|
+
export * from './mediaLayout.js';
|
|
21
|
+
export * from './mediaPreview.js';
|
|
22
|
+
export * from './model.js';
|
|
23
|
+
export * from './channelVideoSource.js';
|
|
24
|
+
export * from './displayCapture.js';
|
|
25
|
+
export * from './videoPacing.js';
|
|
26
|
+
export * from './videoPlayout.js';
|
|
27
|
+
export * from './playbackClock.js';
|
|
28
|
+
export * from './videoFrameDecoder.js';
|
|
29
|
+
export * from './videoFrameDecoderRegistry.js';
|
|
30
|
+
export * from './videoSourceArbiter.js';
|
|
31
|
+
export * from '../audio/audioMeter.js';
|
|
32
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/media/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,SAAS,CAAC;AACxB,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview LOCAL MEDIA CONTROLLER: the user's camera and microphone. It lists devices, starts and stops
|
|
3
|
+
* each kind, moves a live kind to another device, follows device changes, and reports all of it through
|
|
4
|
+
* {@link LocalMediaController.State$}.
|
|
5
|
+
*
|
|
6
|
+
* - **It never starts on its own.** Every capture begins with an explicit {@link LocalMediaController.Start}.
|
|
7
|
+
* Whether frames or audio reach the model is decided where they are sent (the runtime, after the camera
|
|
8
|
+
* check), not here.
|
|
9
|
+
* - **A device switch keeps the stream.** The new track replaces the old one inside the `MediaStream` that
|
|
10
|
+
* {@link LocalMediaController.GetStream} handed out, so a `<video>` self-view or a `FrameSampler` keeps
|
|
11
|
+
* working. Consumers bound to a track rather than a stream (a Web Audio source node, a WebRTC sender) must
|
|
12
|
+
* rebind when `State$` reports the new device; a realtime client does it in `ReplaceMicrophone`. The new
|
|
13
|
+
* track keeps the old one's `enabled` flag, so a muted microphone stays muted. The current device is
|
|
14
|
+
* released before the new one opens, because mobile browsers open one camera at a time; if the new one
|
|
15
|
+
* fails, the previous one is reopened.
|
|
16
|
+
* - **A lost device falls back to the default.** When the device in use goes away (unplugged, Bluetooth
|
|
17
|
+
* dropped), the kind restarts on the system default device. Only when none is left does it report `failed`.
|
|
18
|
+
* - **Capture runs at the device's native frame rate**; pace what the model receives with a `FrameSampler`.
|
|
19
|
+
*
|
|
20
|
+
* Screen sharing is `RequestDisplayCapture`'s job, not this controller's.
|
|
21
|
+
*
|
|
22
|
+
* @module @memberjunction/ai-realtime-client/media
|
|
23
|
+
*/
|
|
24
|
+
import { type Observable } from 'rxjs';
|
|
25
|
+
import type { LocalMediaKind, LocalMediaResult, LocalMediaState, MediaDevice } from './model.js';
|
|
26
|
+
export interface LocalMediaControllerOptions {
|
|
27
|
+
/** Camera constraints other than the device. Defaults to 1280×720 (ideal) at the camera's native frame rate. */
|
|
28
|
+
CameraConstraints?: MediaTrackConstraints;
|
|
29
|
+
/** Microphone constraints other than the device. Defaults to echo cancellation, noise suppression and auto gain. */
|
|
30
|
+
MicrophoneConstraints?: MediaTrackConstraints;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* What a camera-and-microphone controller offers. {@link LocalMediaController} is the browser's; a host on
|
|
34
|
+
* another platform, or a test, can supply its own.
|
|
35
|
+
*/
|
|
36
|
+
export interface ILocalMediaController {
|
|
37
|
+
/** The current state. */
|
|
38
|
+
readonly State: LocalMediaState;
|
|
39
|
+
/** The state, now and on every change. Completes on {@link Dispose}. */
|
|
40
|
+
readonly State$: Observable<LocalMediaState>;
|
|
41
|
+
/** The live stream of a kind, or `null` while it is off. The same object across device switches. */
|
|
42
|
+
GetStream(kind: LocalMediaKind): MediaStream | null;
|
|
43
|
+
/** Lists the input devices. */
|
|
44
|
+
RefreshDevices(): Promise<MediaDevice[]>;
|
|
45
|
+
/** Starts capturing a kind, on `deviceId` when it is available. Always resolves; a failure is a result. */
|
|
46
|
+
Start(kind: LocalMediaKind, deviceId?: string): Promise<LocalMediaResult>;
|
|
47
|
+
/** Moves a live kind to another device, keeping the same stream and the track's mute. */
|
|
48
|
+
SwitchDevice(kind: LocalMediaKind, deviceId: string): Promise<LocalMediaResult>;
|
|
49
|
+
/** Stops a kind and releases its device. */
|
|
50
|
+
Stop(kind: LocalMediaKind): void;
|
|
51
|
+
/** Stops both kinds and completes {@link State$}. */
|
|
52
|
+
Dispose(): void;
|
|
53
|
+
}
|
|
54
|
+
/** The camera and microphone of one browser session. */
|
|
55
|
+
export declare class LocalMediaController implements ILocalMediaController {
|
|
56
|
+
private readonly options;
|
|
57
|
+
private readonly state;
|
|
58
|
+
private readonly live;
|
|
59
|
+
private readonly pending;
|
|
60
|
+
/** Bumped by every Stop, so a start that resolves after it knows it was cancelled. */
|
|
61
|
+
private readonly generation;
|
|
62
|
+
private readonly onDeviceChange;
|
|
63
|
+
private disposed;
|
|
64
|
+
constructor(options?: LocalMediaControllerOptions);
|
|
65
|
+
/** The current state. */
|
|
66
|
+
get State(): LocalMediaState;
|
|
67
|
+
/** The state, now and on every change. Completes on {@link Dispose}. */
|
|
68
|
+
get State$(): Observable<LocalMediaState>;
|
|
69
|
+
/** The live stream of a kind, or `null` while it is off. The same object across device switches. */
|
|
70
|
+
GetStream(kind: LocalMediaKind): MediaStream | null;
|
|
71
|
+
/**
|
|
72
|
+
* Lists the input devices. Labels stay empty until the user has allowed this site that kind of device. If
|
|
73
|
+
* the browser cannot list them, the last list is kept.
|
|
74
|
+
*/
|
|
75
|
+
RefreshDevices(): Promise<MediaDevice[]>;
|
|
76
|
+
/**
|
|
77
|
+
* Starts capturing a kind: on `deviceId` when it is available, otherwise on the system default. If the
|
|
78
|
+
* kind is already on, returns its stream.
|
|
79
|
+
*/
|
|
80
|
+
Start(kind: LocalMediaKind, deviceId?: string): Promise<LocalMediaResult>;
|
|
81
|
+
/**
|
|
82
|
+
* Moves a live kind to another device, keeping the same stream. The current device is released first; if
|
|
83
|
+
* the new device fails, the previous one is reopened. A kind that is off is started on that device instead.
|
|
84
|
+
*/
|
|
85
|
+
SwitchDevice(kind: LocalMediaKind, deviceId: string): Promise<LocalMediaResult>;
|
|
86
|
+
/** Stops a kind and releases its device. */
|
|
87
|
+
Stop(kind: LocalMediaKind): void;
|
|
88
|
+
/** Stops both kinds, stops following device changes, and completes {@link State$}. */
|
|
89
|
+
Dispose(): void;
|
|
90
|
+
private startCapture;
|
|
91
|
+
/** Asks the browser for one track of a kind. */
|
|
92
|
+
private acquire;
|
|
93
|
+
private constraintsFor;
|
|
94
|
+
/**
|
|
95
|
+
* Releases a live capture's device ahead of opening another one, and reports the kind as starting.
|
|
96
|
+
*
|
|
97
|
+
* @returns The change's generation: a later change, or a Stop, makes it stale.
|
|
98
|
+
*/
|
|
99
|
+
private beginChange;
|
|
100
|
+
/** Whether a change is still the latest for its kind. If not, the device it opened is released. */
|
|
101
|
+
private isLatest;
|
|
102
|
+
/**
|
|
103
|
+
* Puts a track in the stream of the capture it replaces and reports its device. The track takes over the
|
|
104
|
+
* old one's `enabled` flag, so a muted microphone stays muted on the new device.
|
|
105
|
+
*/
|
|
106
|
+
private insertTrack;
|
|
107
|
+
/** Opens a device in place of a released capture; if that fails, stops the kind and reports why. */
|
|
108
|
+
private reopenOrFail;
|
|
109
|
+
/** Follows a live track: when it ends without being stopped here, its device went away. */
|
|
110
|
+
private watch;
|
|
111
|
+
/** Restarts a kind whose device went away on the system default, or reports that none is left. */
|
|
112
|
+
private recoverFromLostDevice;
|
|
113
|
+
private publishTrack;
|
|
114
|
+
private publish;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=localMediaController.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localMediaController.d.ts","sourceRoot":"","sources":["../../src/media/localMediaController.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AACxD,OAAO,KAAK,EAAqB,cAAc,EAAE,gBAAgB,EAAE,eAAe,EAAmB,WAAW,EAAE,MAAM,SAAS,CAAC;AAElI,MAAM,WAAW,2BAA2B;IACxC,gHAAgH;IAChH,iBAAiB,CAAC,EAAE,qBAAqB,CAAC;IAC1C,oHAAoH;IACpH,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;CACjD;AAiBD;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IAClC,yBAAyB;IACzB,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,wEAAwE;IACxE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,eAAe,CAAC,CAAC;IAC7C,oGAAoG;IACpG,SAAS,CAAC,IAAI,EAAE,cAAc,GAAG,WAAW,GAAG,IAAI,CAAC;IACpD,+BAA+B;IAC/B,cAAc,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IACzC,2GAA2G;IAC3G,KAAK,CAAC,IAAI,EAAE,cAAc,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC1E,yFAAyF;IACzF,YAAY,CAAC,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAChF,4CAA4C;IAC5C,IAAI,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IACjC,qDAAqD;IACrD,OAAO,IAAI,IAAI,CAAC;CACnB;AAED,wDAAwD;AACxD,qBAAa,oBAAqB,YAAW,qBAAqB;IASlD,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuF;IAC7G,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAkF;IACvG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgG;IACxH,sFAAsF;IACtF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgE;IAC3F,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA0C;IACzE,OAAO,CAAC,QAAQ,CAAS;gBAEI,OAAO,GAAE,2BAAgC;IAItE,yBAAyB;IACzB,IAAW,KAAK,IAAI,eAAe,CAElC;IAED,wEAAwE;IACxE,IAAW,MAAM,IAAI,UAAU,CAAC,eAAe,CAAC,CAE/C;IAED,oGAAoG;IAC7F,SAAS,CAAC,IAAI,EAAE,cAAc,GAAG,WAAW,GAAG,IAAI;IAI1D;;;OAGG;IACU,cAAc,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAmBrD;;;OAGG;IACI,KAAK,CAAC,IAAI,EAAE,cAAc,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAehF;;;OAGG;IACU,YAAY,CAAC,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAmB5F,4CAA4C;IACrC,IAAI,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAWvC,sFAAsF;IAC/E,OAAO,IAAI,IAAI;YAWR,YAAY;IAmB1B,gDAAgD;YAClC,OAAO;IAmBrB,OAAO,CAAC,cAAc;IAMtB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAQnB,mGAAmG;IACnG,OAAO,CAAC,QAAQ;IAUhB;;;OAGG;IACH,OAAO,CAAC,WAAW;IAOnB,oGAAoG;YACtF,YAAY;IAa1B,2FAA2F;IAC3F,OAAO,CAAC,KAAK;IAMb,kGAAkG;YACpF,qBAAqB;IASnC,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,OAAO;CAKlB"}
|