@memberjunction/ai-realtime-client 6.2.0-edge.2 → 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 +23 -26
- package/dist/drivers/openAIRealtimeClient.d.ts.map +1 -1
- package/dist/drivers/openAIRealtimeClient.js +42 -57
- package/dist/drivers/openAIRealtimeClient.js.map +1 -1
- package/dist/generic/baseRealtimeClient.d.ts +188 -30
- package/dist/generic/baseRealtimeClient.d.ts.map +1 -1
- package/dist/generic/baseRealtimeClient.js +250 -14
- package/dist/generic/baseRealtimeClient.js.map +1 -1
- package/dist/generic/openAIProtocolClient.d.ts +57 -1
- package/dist/generic/openAIProtocolClient.d.ts.map +1 -1
- package/dist/generic/openAIProtocolClient.js +89 -4
- 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,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview DISPLAY CAPTURE: asks the browser to share a screen, a window, a tab or one panel of this
|
|
3
|
+
* page, and reports what the user actually shared.
|
|
4
|
+
*
|
|
5
|
+
* Sharing works wherever `getDisplayMedia` exists: desktop Chrome, Edge, Firefox and Safari (no mobile browser
|
|
6
|
+
* has it). The picker hints sent with it (`displaySurface`, `selfBrowserSurface`, `surfaceSwitching`,
|
|
7
|
+
* `preferCurrentTab`, `monitorTypeSurfaces`, `systemAudio`) are read only by Chromium browsers; others ignore
|
|
8
|
+
* them.
|
|
9
|
+
*
|
|
10
|
+
* A PANEL capture shares one element of this page. The user picks this tab in the picker, and the stream is
|
|
11
|
+
* then narrowed to the element with Element Capture (`restrictTo`, Chromium 132+: the element alone, without
|
|
12
|
+
* anything drawn over it) or, failing that, Region Capture (`cropTo`, Chromium 104+: the element's rectangle,
|
|
13
|
+
* including anything over it). Element Capture emits frames only while the element is its own stacking
|
|
14
|
+
* context, so the element gets `isolation: isolate` for the share and its own value back when the share ends.
|
|
15
|
+
* Firefox and Safari have neither; {@link GetDisplayCaptureSupport} says so, and the caller shows the panel to
|
|
16
|
+
* the agent another way (its channel frames). If the user shares something other than this tab, the capture is
|
|
17
|
+
* stopped rather than sharing more than the panel.
|
|
18
|
+
*
|
|
19
|
+
* The browser's picker is the user's consent: it opens on every request, with no remembered grant. Like the
|
|
20
|
+
* picker itself, {@link RequestDisplayCapture} must be called from a user gesture (a click handler).
|
|
21
|
+
*
|
|
22
|
+
* Capture runs at the surface's native frame rate; pace what the model receives with a `FrameSampler`.
|
|
23
|
+
*
|
|
24
|
+
* @module @memberjunction/ai-realtime-client/media
|
|
25
|
+
*/
|
|
26
|
+
/** The picker's `displaySurface` value for each surface. */
|
|
27
|
+
const PICKER_SURFACE = { screen: 'monitor', window: 'window', tab: 'browser' };
|
|
28
|
+
/** What the user is told when a panel share got something other than this tab (without the closing period). */
|
|
29
|
+
const WRONG_SURFACE_MESSAGE = "To share only the panel, choose this tab in the browser's picker";
|
|
30
|
+
/** What this browser can capture. */
|
|
31
|
+
export function GetDisplayCaptureSupport() {
|
|
32
|
+
const scope = globalThis;
|
|
33
|
+
return {
|
|
34
|
+
Display: typeof navigator !== 'undefined' && typeof navigator.mediaDevices?.getDisplayMedia === 'function',
|
|
35
|
+
ElementCapture: typeof scope.RestrictionTarget?.fromElement === 'function',
|
|
36
|
+
RegionCapture: typeof scope.CropTarget?.fromElement === 'function',
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Opens the browser's share picker and starts sharing what the user picks. Call it from a user gesture.
|
|
41
|
+
*
|
|
42
|
+
* @param options What to offer, whether to share only a panel, and whether to include audio.
|
|
43
|
+
* @returns `started` with the live capture, `cancelled` when the user closed the picker, or `failed` with a reason.
|
|
44
|
+
*/
|
|
45
|
+
export async function RequestDisplayCapture(options = {}) {
|
|
46
|
+
const support = GetDisplayCaptureSupport();
|
|
47
|
+
if (!support.Display) {
|
|
48
|
+
return failure('unsupported', 'This browser cannot share a screen.');
|
|
49
|
+
}
|
|
50
|
+
if (options.Panel && !support.ElementCapture && !support.RegionCapture) {
|
|
51
|
+
return failure('panel-unsupported', 'This browser cannot share a single panel; show it through its channel instead.');
|
|
52
|
+
}
|
|
53
|
+
let stream;
|
|
54
|
+
try {
|
|
55
|
+
stream = await navigator.mediaDevices.getDisplayMedia(pickerOptions(options));
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
return pickerFailure(err);
|
|
59
|
+
}
|
|
60
|
+
const track = stream.getVideoTracks()[0];
|
|
61
|
+
if (!track) {
|
|
62
|
+
stopTracks(stream);
|
|
63
|
+
return failure('error', 'The shared stream has no video track.');
|
|
64
|
+
}
|
|
65
|
+
if (!options.Panel) {
|
|
66
|
+
return { Status: 'started', Capture: new ActiveDisplayCapture(stream, track) };
|
|
67
|
+
}
|
|
68
|
+
const narrowed = await narrowToPanel(track, options.Panel, support);
|
|
69
|
+
if ('Status' in narrowed) {
|
|
70
|
+
stopTracks(stream);
|
|
71
|
+
return narrowed;
|
|
72
|
+
}
|
|
73
|
+
const panel = options.PanelLabel ? { ...narrowed, Label: options.PanelLabel } : narrowed;
|
|
74
|
+
return { Status: 'started', Capture: new ActiveDisplayCapture(stream, track, panel) };
|
|
75
|
+
}
|
|
76
|
+
/** The picker request: this tab for a panel; otherwise any surface but this tab, with the preferred kind first. */
|
|
77
|
+
function pickerOptions(options) {
|
|
78
|
+
const audio = options.IncludeAudio ?? false;
|
|
79
|
+
if (options.Panel) {
|
|
80
|
+
return {
|
|
81
|
+
video: { displaySurface: PICKER_SURFACE.tab },
|
|
82
|
+
audio,
|
|
83
|
+
preferCurrentTab: true,
|
|
84
|
+
selfBrowserSurface: 'include',
|
|
85
|
+
// Switching to another surface would leave the panel narrowing behind.
|
|
86
|
+
surfaceSwitching: 'exclude',
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
video: options.PreferredSurface ? { displaySurface: PICKER_SURFACE[options.PreferredSurface] } : true,
|
|
91
|
+
audio,
|
|
92
|
+
// Sharing this page would show the agent its own call UI, mirrored without end.
|
|
93
|
+
selfBrowserSurface: 'exclude',
|
|
94
|
+
surfaceSwitching: 'include',
|
|
95
|
+
monitorTypeSurfaces: 'include',
|
|
96
|
+
systemAudio: audio ? 'include' : 'exclude',
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Narrows a self-capture to the panel: with Element Capture where the browser has it, else with Region Capture.
|
|
101
|
+
*
|
|
102
|
+
* @returns How it was narrowed, or a failure when the user shared something other than this tab.
|
|
103
|
+
*/
|
|
104
|
+
async function narrowToPanel(track, panel, support) {
|
|
105
|
+
if (track.getSettings().displaySurface !== PICKER_SURFACE.tab) {
|
|
106
|
+
return failure('panel-wrong-surface', `${WRONG_SURFACE_MESSAGE}.`);
|
|
107
|
+
}
|
|
108
|
+
const scope = globalThis;
|
|
109
|
+
const narrowable = track;
|
|
110
|
+
if (support.ElementCapture && scope.RestrictionTarget && narrowable.restrictTo) {
|
|
111
|
+
// Isolated first, so the restricted track has frames to emit from the start.
|
|
112
|
+
const release = isolatePanel(panel);
|
|
113
|
+
try {
|
|
114
|
+
await narrowable.restrictTo(await scope.RestrictionTarget.fromElement(panel));
|
|
115
|
+
return { Method: 'element', Release: release };
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
release();
|
|
119
|
+
return wrongSurface(err);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (scope.CropTarget && narrowable.cropTo) {
|
|
123
|
+
try {
|
|
124
|
+
await narrowable.cropTo(await scope.CropTarget.fromElement(panel));
|
|
125
|
+
return { Method: 'region', Release: () => undefined };
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
return wrongSurface(err);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return failure('panel-unsupported', 'This browser cannot narrow a share to a single panel.');
|
|
132
|
+
}
|
|
133
|
+
/** The browser refuses to narrow a capture of any tab but this one. */
|
|
134
|
+
function wrongSurface(err) {
|
|
135
|
+
return failure('panel-wrong-surface', `${WRONG_SURFACE_MESSAGE} (${errorMessage(err)}).`);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Makes the panel its own stacking context, which Element Capture needs to emit frames, unless it already is
|
|
139
|
+
* one through `isolation`. Set inline and marked important, so no style sheet undoes it during the share.
|
|
140
|
+
*
|
|
141
|
+
* @returns A function that puts the panel's own inline `isolation` back; the share calls it once, as it ends.
|
|
142
|
+
*/
|
|
143
|
+
function isolatePanel(panel) {
|
|
144
|
+
const style = panel.style;
|
|
145
|
+
if (!style || (typeof getComputedStyle === 'function' && getComputedStyle(panel).isolation === 'isolate')) {
|
|
146
|
+
return () => undefined;
|
|
147
|
+
}
|
|
148
|
+
const value = style.getPropertyValue('isolation');
|
|
149
|
+
const priority = style.getPropertyPriority('isolation');
|
|
150
|
+
style.setProperty('isolation', 'isolate', 'important');
|
|
151
|
+
return () => {
|
|
152
|
+
if (value) {
|
|
153
|
+
style.setProperty('isolation', value, priority);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
style.removeProperty('isolation');
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Turns a picker rejection into a result. Closing the picker rejects with `NotAllowedError`, and so does an
|
|
162
|
+
* operating-system refusal, which Chromium words "Permission denied by system".
|
|
163
|
+
*/
|
|
164
|
+
function pickerFailure(err) {
|
|
165
|
+
const name = err instanceof Error ? err.name : '';
|
|
166
|
+
const message = errorMessage(err);
|
|
167
|
+
if (name === 'NotAllowedError') {
|
|
168
|
+
return /system|policy/i.test(message) ? failure('denied', message) : { Status: 'cancelled' };
|
|
169
|
+
}
|
|
170
|
+
return failure('error', message);
|
|
171
|
+
}
|
|
172
|
+
function failure(reason, message) {
|
|
173
|
+
return { Status: 'failed', Reason: reason, Message: message };
|
|
174
|
+
}
|
|
175
|
+
function errorMessage(err) {
|
|
176
|
+
return err instanceof Error ? err.message : String(err);
|
|
177
|
+
}
|
|
178
|
+
function stopTracks(stream) {
|
|
179
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* The kind of surface a captured track shows, from the browser's `displaySurface` setting. It reads any display
|
|
183
|
+
* track, including one captured elsewhere, such as a LiveKit screen share.
|
|
184
|
+
*/
|
|
185
|
+
export function CapturedSurfaceOf(track) {
|
|
186
|
+
switch (track.getSettings().displaySurface) {
|
|
187
|
+
case 'monitor':
|
|
188
|
+
return 'screen';
|
|
189
|
+
case 'window':
|
|
190
|
+
return 'window';
|
|
191
|
+
case 'browser':
|
|
192
|
+
return 'tab';
|
|
193
|
+
default:
|
|
194
|
+
return 'unknown';
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/** A share in progress. */
|
|
198
|
+
class ActiveDisplayCapture {
|
|
199
|
+
constructor(Stream, Track, panel) {
|
|
200
|
+
this.Stream = Stream;
|
|
201
|
+
this.Track = Track;
|
|
202
|
+
this.panel = panel;
|
|
203
|
+
this.endedHandlers = new Set();
|
|
204
|
+
this.ended = false;
|
|
205
|
+
// `ended` fires when the user stops sharing from the browser's bar or the surface closes.
|
|
206
|
+
Track.addEventListener('ended', () => this.end());
|
|
207
|
+
}
|
|
208
|
+
get Surface() {
|
|
209
|
+
return CapturedSurfaceOf(this.Track);
|
|
210
|
+
}
|
|
211
|
+
get Label() {
|
|
212
|
+
return this.Track.label;
|
|
213
|
+
}
|
|
214
|
+
get PanelMethod() {
|
|
215
|
+
return this.panel?.Method;
|
|
216
|
+
}
|
|
217
|
+
get PanelLabel() {
|
|
218
|
+
return this.panel?.Label;
|
|
219
|
+
}
|
|
220
|
+
OnEnded(handler) {
|
|
221
|
+
if (this.ended) {
|
|
222
|
+
handler();
|
|
223
|
+
return () => undefined;
|
|
224
|
+
}
|
|
225
|
+
this.endedHandlers.add(handler);
|
|
226
|
+
return () => this.endedHandlers.delete(handler);
|
|
227
|
+
}
|
|
228
|
+
Stop() {
|
|
229
|
+
stopTracks(this.Stream);
|
|
230
|
+
// A track stopped by the page fires no `ended` event, so report the end here.
|
|
231
|
+
this.end();
|
|
232
|
+
}
|
|
233
|
+
end() {
|
|
234
|
+
if (this.ended) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
this.ended = true;
|
|
238
|
+
// The panel's own style comes back before anyone hears that the share ended.
|
|
239
|
+
this.panel?.Release();
|
|
240
|
+
for (const handler of [...this.endedHandlers]) {
|
|
241
|
+
handler();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=displayCapture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"displayCapture.js","sourceRoot":"","sources":["../../src/media/displayCapture.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview FRAME CAPTURE for realtime video tracks — camera and screen capture pipelines.
|
|
3
3
|
*
|
|
4
|
-
* Patterned beside `micCapture.ts
|
|
5
|
-
* - `CreateCameraCapture
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Patterned beside `micCapture.ts`. Every exported function here is deprecated; new code uses the `/media` modules:
|
|
5
|
+
* - `CreateCameraCapture` (deprecated): prompts via `getUserMedia` (consent-gated via
|
|
6
|
+
* {@link RealtimeTrackDescriptor.RequiresConsent}). New code starts the camera with `LocalMediaController` and samples
|
|
7
|
+
* its stream with {@link FrameSampler}.
|
|
8
|
+
* - `CreateScreenCapture` (deprecated): prompts via `getDisplayMedia` (consent-gated via
|
|
9
|
+
* {@link RealtimeTrackDescriptor.RequiresConsent}). New code shares with `RequestDisplayCapture` and samples with
|
|
10
|
+
* {@link FrameSampler}.
|
|
11
|
+
* - `CreateStreamFrameCapture` (deprecated): extracts periodic JPEG frames from an already-acquired
|
|
12
|
+
* `MediaStream`. It is now a thin wrapper over {@link FrameSampler}, which new code uses directly.
|
|
8
13
|
*
|
|
9
|
-
*
|
|
14
|
+
* The two capture helpers keep their own `getUserMedia` and `getDisplayMedia` calls rather than wrapping the new
|
|
15
|
+
* modules: those differ in what they offer (the screen picker leaves out the current tab, for one) and in how they
|
|
16
|
+
* report a failure, so a caller of a helper keeps the behaviour it was written against.
|
|
17
|
+
*
|
|
18
|
+
* Capture runs at the device's native frame rate; only the sampling is paced, at the rate the caller passes
|
|
19
|
+
* (the negotiated track rate). There is no 1 fps ceiling here.
|
|
10
20
|
*
|
|
11
21
|
* @module @memberjunction/ai-realtime-client
|
|
12
22
|
* @author MemberJunction.com
|
|
@@ -33,8 +43,8 @@ export interface FrameCaptureOptions {
|
|
|
33
43
|
*/
|
|
34
44
|
ConsentGranted?: boolean;
|
|
35
45
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
46
|
+
* Frames per second to sample. No ceiling: pass the negotiated track rate. Defaults to
|
|
47
|
+
* `Descriptor?.Rate ?? 1`.
|
|
38
48
|
*/
|
|
39
49
|
Rate?: number;
|
|
40
50
|
/** Output image format ('image/jpeg' or 'image/png'). Defaults to 'image/jpeg'. */
|
|
@@ -50,6 +60,8 @@ export interface FrameCaptureOptions {
|
|
|
50
60
|
/**
|
|
51
61
|
* Creates a frame capture pump over an already-acquired {@link MediaStream}.
|
|
52
62
|
*
|
|
63
|
+
* @deprecated Use {@link FrameSampler}, which reports whether it started and returns frame sizes and
|
|
64
|
+
* timestamps. This wrapper passes `Rate` through unchanged; it no longer caps it at 1 fps.
|
|
53
65
|
* @param stream The media stream containing one or more video tracks.
|
|
54
66
|
* @param options Frame capture options (cadence, format, frame callback).
|
|
55
67
|
*/
|
|
@@ -58,6 +70,9 @@ export declare function CreateStreamFrameCapture(stream: MediaStream, options: F
|
|
|
58
70
|
* Requests user camera video capture via `navigator.mediaDevices.getUserMedia`.
|
|
59
71
|
* Gated on {@link FrameCaptureOptions.ConsentGranted} when consent is required.
|
|
60
72
|
*
|
|
73
|
+
* @deprecated Start the camera with `LocalMediaController` (in `localMediaController.ts`), which lists and switches
|
|
74
|
+
* devices and reports failures as a state, then sample its stream (`GetStream('camera')`) with a
|
|
75
|
+
* {@link FrameSampler}.
|
|
61
76
|
* @param options Frame capture options.
|
|
62
77
|
* @param constraints Video track constraints.
|
|
63
78
|
*/
|
|
@@ -66,11 +81,13 @@ export declare function CreateCameraCapture(options: FrameCaptureOptions, constr
|
|
|
66
81
|
* Requests screen share video capture via `navigator.mediaDevices.getDisplayMedia`.
|
|
67
82
|
* Gated on {@link FrameCaptureOptions.ConsentGranted} when consent is required.
|
|
68
83
|
*
|
|
84
|
+
* @deprecated Use `RequestDisplayCapture` (in `displayCapture.ts`), which offers surface hints and panel
|
|
85
|
+
* capture and reports what was shared, then a {@link FrameSampler} on its stream.
|
|
69
86
|
* @param options Frame capture options.
|
|
70
87
|
* @param displayMediaOptions Display media options.
|
|
71
88
|
*/
|
|
72
89
|
export declare function CreateScreenCapture(options: FrameCaptureOptions, displayMediaOptions?: DisplayMediaStreamOptions): Promise<IFrameCapture>;
|
|
73
|
-
/** @deprecated Use {@link
|
|
90
|
+
/** @deprecated Use {@link FrameSampler}. */
|
|
74
91
|
export declare function createStreamFrameCapture(stream: MediaStream, options: FrameCaptureOptions): IFrameCapture;
|
|
75
92
|
/** @deprecated Use {@link CreateCameraCapture}. */
|
|
76
93
|
export declare function createCameraCapture(options: FrameCaptureOptions, constraints?: MediaTrackConstraints): Promise<IFrameCapture>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frameCapture.d.ts","sourceRoot":"","sources":["../../src/media/frameCapture.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"frameCapture.d.ts","sourceRoot":"","sources":["../../src/media/frameCapture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAGlE;;GAEG;AACH,MAAM,WAAW,aAAa;IAC1B,yFAAyF;IACzF,IAAI,IAAI,IAAI,CAAC;IACb,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAChC,+CAA+C;IAC/C,UAAU,CAAC,EAAE,uBAAuB,CAAC;IACrC;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mFAAmF;IACnF,QAAQ,CAAC,EAAE,YAAY,GAAG,WAAW,CAAC;IACtC,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,OAAO,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAChE;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACpC,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,mBAAmB,GAC7B,aAAa,CAEf;AAmBD;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACrC,OAAO,EAAE,mBAAmB,EAC5B,WAAW,CAAC,EAAE,qBAAqB,GACpC,OAAO,CAAC,aAAa,CAAC,CAsBxB;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACrC,OAAO,EAAE,mBAAmB,EAC5B,mBAAmB,CAAC,EAAE,yBAAyB,GAChD,OAAO,CAAC,aAAa,CAAC,CAoBxB;AAED,4CAA4C;AAC5C,wBAAgB,wBAAwB,CACpC,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,mBAAmB,GAC7B,aAAa,CAEf;AAED,mDAAmD;AACnD,wBAAsB,mBAAmB,CACrC,OAAO,EAAE,mBAAmB,EAC5B,WAAW,CAAC,EAAE,qBAAqB,GACpC,OAAO,CAAC,aAAa,CAAC,CAExB;AAED,mDAAmD;AACnD,wBAAsB,mBAAmB,CACrC,OAAO,EAAE,mBAAmB,EAC5B,mBAAmB,CAAC,EAAE,yBAAyB,GAChD,OAAO,CAAC,aAAa,CAAC,CAExB"}
|
|
@@ -1,86 +1,49 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview FRAME CAPTURE for realtime video tracks — camera and screen capture pipelines.
|
|
3
3
|
*
|
|
4
|
-
* Patterned beside `micCapture.ts
|
|
5
|
-
* - `CreateCameraCapture
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Patterned beside `micCapture.ts`. Every exported function here is deprecated; new code uses the `/media` modules:
|
|
5
|
+
* - `CreateCameraCapture` (deprecated): prompts via `getUserMedia` (consent-gated via
|
|
6
|
+
* {@link RealtimeTrackDescriptor.RequiresConsent}). New code starts the camera with `LocalMediaController` and samples
|
|
7
|
+
* its stream with {@link FrameSampler}.
|
|
8
|
+
* - `CreateScreenCapture` (deprecated): prompts via `getDisplayMedia` (consent-gated via
|
|
9
|
+
* {@link RealtimeTrackDescriptor.RequiresConsent}). New code shares with `RequestDisplayCapture` and samples with
|
|
10
|
+
* {@link FrameSampler}.
|
|
11
|
+
* - `CreateStreamFrameCapture` (deprecated): extracts periodic JPEG frames from an already-acquired
|
|
12
|
+
* `MediaStream`. It is now a thin wrapper over {@link FrameSampler}, which new code uses directly.
|
|
8
13
|
*
|
|
9
|
-
*
|
|
14
|
+
* The two capture helpers keep their own `getUserMedia` and `getDisplayMedia` calls rather than wrapping the new
|
|
15
|
+
* modules: those differ in what they offer (the screen picker leaves out the current tab, for one) and in how they
|
|
16
|
+
* report a failure, so a caller of a helper keeps the behaviour it was written against.
|
|
17
|
+
*
|
|
18
|
+
* Capture runs at the device's native frame rate; only the sampling is paced, at the rate the caller passes
|
|
19
|
+
* (the negotiated track rate). There is no 1 fps ceiling here.
|
|
10
20
|
*
|
|
11
21
|
* @module @memberjunction/ai-realtime-client
|
|
12
22
|
* @author MemberJunction.com
|
|
13
23
|
*/
|
|
24
|
+
import { FrameSampler } from './frameSampler.js';
|
|
14
25
|
/**
|
|
15
26
|
* Creates a frame capture pump over an already-acquired {@link MediaStream}.
|
|
16
27
|
*
|
|
28
|
+
* @deprecated Use {@link FrameSampler}, which reports whether it started and returns frame sizes and
|
|
29
|
+
* timestamps. This wrapper passes `Rate` through unchanged; it no longer caps it at 1 fps.
|
|
17
30
|
* @param stream The media stream containing one or more video tracks.
|
|
18
31
|
* @param options Frame capture options (cadence, format, frame callback).
|
|
19
32
|
*/
|
|
20
33
|
export function CreateStreamFrameCapture(stream, options) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
videoEl = document.createElement('video');
|
|
34
|
-
videoEl.muted = true;
|
|
35
|
-
videoEl.playsInline = true;
|
|
36
|
-
videoEl.srcObject = stream;
|
|
37
|
-
void videoEl.play().catch(() => {
|
|
38
|
-
// Autoplay may be restricted without user interaction; non-fatal for capture
|
|
39
|
-
});
|
|
40
|
-
canvasEl = document.createElement('canvas');
|
|
41
|
-
}
|
|
42
|
-
catch (err) {
|
|
43
|
-
console.error('[FrameCapture] Failed to initialize DOM elements for video capture:', err);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
const captureTick = () => {
|
|
47
|
-
if (stopped) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
if (videoEl && canvasEl && videoEl.videoWidth > 0 && videoEl.videoHeight > 0) {
|
|
51
|
-
canvasEl.width = videoEl.videoWidth;
|
|
52
|
-
canvasEl.height = videoEl.videoHeight;
|
|
53
|
-
const ctx = canvasEl.getContext('2d');
|
|
54
|
-
if (ctx) {
|
|
55
|
-
ctx.drawImage(videoEl, 0, 0);
|
|
56
|
-
const dataUrl = canvasEl.toDataURL(mimeType, quality);
|
|
57
|
-
const base64 = dataUrl.split(',')[1] ?? '';
|
|
58
|
-
if (base64.length > 0) {
|
|
59
|
-
options.OnFrame({ data: base64, mimeType });
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
if (videoEl && canvasEl) {
|
|
65
|
-
timer = setInterval(captureTick, intervalMs);
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
console.warn('[FrameCapture] No video/canvas element available (no DOM, or element construction failed) — ' +
|
|
69
|
-
'this capture will emit no frames.');
|
|
70
|
-
}
|
|
34
|
+
return startSampler(stream, options);
|
|
35
|
+
}
|
|
36
|
+
/** Samples a stream with a {@link FrameSampler}, behind the older {@link IFrameCapture} handle. */
|
|
37
|
+
function startSampler(stream, options) {
|
|
38
|
+
const sampler = new FrameSampler(stream, {
|
|
39
|
+
Rate: options.Rate ?? options.Descriptor?.Rate ?? 1,
|
|
40
|
+
MimeType: options.MimeType,
|
|
41
|
+
Quality: options.Quality,
|
|
42
|
+
OnFrame: (frame) => options.OnFrame({ data: frame.Data, mimeType: frame.MimeType }),
|
|
43
|
+
});
|
|
44
|
+
sampler.Start();
|
|
71
45
|
return {
|
|
72
|
-
Stop: () =>
|
|
73
|
-
stopped = true;
|
|
74
|
-
if (timer) {
|
|
75
|
-
clearInterval(timer);
|
|
76
|
-
timer = null;
|
|
77
|
-
}
|
|
78
|
-
if (videoEl) {
|
|
79
|
-
videoEl.srcObject = null;
|
|
80
|
-
videoEl = null;
|
|
81
|
-
}
|
|
82
|
-
canvasEl = null;
|
|
83
|
-
},
|
|
46
|
+
Stop: () => sampler.Stop(),
|
|
84
47
|
get Stream() {
|
|
85
48
|
return stream;
|
|
86
49
|
},
|
|
@@ -90,6 +53,9 @@ export function CreateStreamFrameCapture(stream, options) {
|
|
|
90
53
|
* Requests user camera video capture via `navigator.mediaDevices.getUserMedia`.
|
|
91
54
|
* Gated on {@link FrameCaptureOptions.ConsentGranted} when consent is required.
|
|
92
55
|
*
|
|
56
|
+
* @deprecated Start the camera with `LocalMediaController` (in `localMediaController.ts`), which lists and switches
|
|
57
|
+
* devices and reports failures as a state, then sample its stream (`GetStream('camera')`) with a
|
|
58
|
+
* {@link FrameSampler}.
|
|
93
59
|
* @param options Frame capture options.
|
|
94
60
|
* @param constraints Video track constraints.
|
|
95
61
|
*/
|
|
@@ -101,10 +67,11 @@ export async function CreateCameraCapture(options, constraints) {
|
|
|
101
67
|
if (typeof navigator === 'undefined' || !navigator.mediaDevices?.getUserMedia) {
|
|
102
68
|
throw new Error('Camera capture is unavailable: navigator.mediaDevices.getUserMedia not supported in this environment.');
|
|
103
69
|
}
|
|
70
|
+
// No frameRate cap: the camera runs at its native rate (a smooth self-view); only sampling is paced.
|
|
104
71
|
const stream = await navigator.mediaDevices.getUserMedia({
|
|
105
|
-
video: constraints ?? { width: { ideal: 1280 }, height: { ideal: 720 }
|
|
72
|
+
video: constraints ?? { width: { ideal: 1280 }, height: { ideal: 720 } },
|
|
106
73
|
});
|
|
107
|
-
const capture =
|
|
74
|
+
const capture = startSampler(stream, options);
|
|
108
75
|
return {
|
|
109
76
|
Stop: () => {
|
|
110
77
|
capture.Stop();
|
|
@@ -119,6 +86,8 @@ export async function CreateCameraCapture(options, constraints) {
|
|
|
119
86
|
* Requests screen share video capture via `navigator.mediaDevices.getDisplayMedia`.
|
|
120
87
|
* Gated on {@link FrameCaptureOptions.ConsentGranted} when consent is required.
|
|
121
88
|
*
|
|
89
|
+
* @deprecated Use `RequestDisplayCapture` (in `displayCapture.ts`), which offers surface hints and panel
|
|
90
|
+
* capture and reports what was shared, then a {@link FrameSampler} on its stream.
|
|
122
91
|
* @param options Frame capture options.
|
|
123
92
|
* @param displayMediaOptions Display media options.
|
|
124
93
|
*/
|
|
@@ -130,8 +99,9 @@ export async function CreateScreenCapture(options, displayMediaOptions) {
|
|
|
130
99
|
if (typeof navigator === 'undefined' || !navigator.mediaDevices?.getDisplayMedia) {
|
|
131
100
|
throw new Error('Screen capture is unavailable: navigator.mediaDevices.getDisplayMedia not supported in this environment.');
|
|
132
101
|
}
|
|
133
|
-
|
|
134
|
-
const
|
|
102
|
+
// No frameRate cap: the share runs at its native rate; only sampling is paced.
|
|
103
|
+
const stream = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions ?? { video: true });
|
|
104
|
+
const capture = startSampler(stream, options);
|
|
135
105
|
return {
|
|
136
106
|
Stop: () => {
|
|
137
107
|
capture.Stop();
|
|
@@ -142,7 +112,7 @@ export async function CreateScreenCapture(options, displayMediaOptions) {
|
|
|
142
112
|
},
|
|
143
113
|
};
|
|
144
114
|
}
|
|
145
|
-
/** @deprecated Use {@link
|
|
115
|
+
/** @deprecated Use {@link FrameSampler}. */
|
|
146
116
|
export function createStreamFrameCapture(stream, options) {
|
|
147
117
|
return CreateStreamFrameCapture(stream, options);
|
|
148
118
|
}
|
|
@@ -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"}
|