@memberjunction/ai-realtime-client 6.2.0-edge.3 → 6.2.0-edge.5

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.
Files changed (209) hide show
  1. package/README.md +156 -29
  2. package/dist/audio/audioMeter.d.ts +71 -0
  3. package/dist/audio/audioMeter.d.ts.map +1 -1
  4. package/dist/audio/audioMeter.js +83 -0
  5. package/dist/audio/audioMeter.js.map +1 -1
  6. package/dist/audio/mediaElementAudioRouter.d.ts +41 -0
  7. package/dist/audio/mediaElementAudioRouter.d.ts.map +1 -0
  8. package/dist/audio/mediaElementAudioRouter.js +82 -0
  9. package/dist/audio/mediaElementAudioRouter.js.map +1 -0
  10. package/dist/audio/micCapture.d.ts +12 -3
  11. package/dist/audio/micCapture.d.ts.map +1 -1
  12. package/dist/audio/micCapture.js +15 -1
  13. package/dist/audio/micCapture.js.map +1 -1
  14. package/dist/audio/pcmPlayback.d.ts +72 -4
  15. package/dist/audio/pcmPlayback.d.ts.map +1 -1
  16. package/dist/audio/pcmPlayback.js +101 -1
  17. package/dist/audio/pcmPlayback.js.map +1 -1
  18. package/dist/drivers/assemblyAIRealtimeClient.d.ts +2 -0
  19. package/dist/drivers/assemblyAIRealtimeClient.d.ts.map +1 -1
  20. package/dist/drivers/assemblyAIRealtimeClient.js +14 -0
  21. package/dist/drivers/assemblyAIRealtimeClient.js.map +1 -1
  22. package/dist/drivers/elevenLabsRealtimeClient.d.ts +2 -0
  23. package/dist/drivers/elevenLabsRealtimeClient.d.ts.map +1 -1
  24. package/dist/drivers/elevenLabsRealtimeClient.js +14 -0
  25. package/dist/drivers/elevenLabsRealtimeClient.js.map +1 -1
  26. package/dist/drivers/geminiAvatarOutput.d.ts +132 -0
  27. package/dist/drivers/geminiAvatarOutput.d.ts.map +1 -0
  28. package/dist/drivers/geminiAvatarOutput.js +310 -0
  29. package/dist/drivers/geminiAvatarOutput.js.map +1 -0
  30. package/dist/drivers/geminiEnterpriseRealtimeClient.d.ts +38 -0
  31. package/dist/drivers/geminiEnterpriseRealtimeClient.d.ts.map +1 -0
  32. package/dist/drivers/geminiEnterpriseRealtimeClient.js +99 -0
  33. package/dist/drivers/geminiEnterpriseRealtimeClient.js.map +1 -0
  34. package/dist/drivers/geminiRealtimeClient.d.ts +325 -50
  35. package/dist/drivers/geminiRealtimeClient.d.ts.map +1 -1
  36. package/dist/drivers/geminiRealtimeClient.js +782 -184
  37. package/dist/drivers/geminiRealtimeClient.js.map +1 -1
  38. package/dist/drivers/openAILiveClient.d.ts +5 -8
  39. package/dist/drivers/openAILiveClient.d.ts.map +1 -1
  40. package/dist/drivers/openAILiveClient.js +19 -32
  41. package/dist/drivers/openAILiveClient.js.map +1 -1
  42. package/dist/drivers/openAIRealtimeClient.d.ts +13 -26
  43. package/dist/drivers/openAIRealtimeClient.d.ts.map +1 -1
  44. package/dist/drivers/openAIRealtimeClient.js +28 -55
  45. package/dist/drivers/openAIRealtimeClient.js.map +1 -1
  46. package/dist/drivers/xaiRealtimeClient.d.ts.map +1 -1
  47. package/dist/drivers/xaiRealtimeClient.js +19 -14
  48. package/dist/drivers/xaiRealtimeClient.js.map +1 -1
  49. package/dist/generic/baseRealtimeClient.d.ts +183 -29
  50. package/dist/generic/baseRealtimeClient.d.ts.map +1 -1
  51. package/dist/generic/baseRealtimeClient.js +246 -14
  52. package/dist/generic/baseRealtimeClient.js.map +1 -1
  53. package/dist/generic/openAIProtocolClient.d.ts +2 -0
  54. package/dist/generic/openAIProtocolClient.d.ts.map +1 -1
  55. package/dist/generic/openAIProtocolClient.js +17 -0
  56. package/dist/generic/openAIProtocolClient.js.map +1 -1
  57. package/dist/index.d.ts +2 -3
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +3 -3
  60. package/dist/index.js.map +1 -1
  61. package/dist/media/attachVideoSource.d.ts +23 -0
  62. package/dist/media/attachVideoSource.d.ts.map +1 -0
  63. package/dist/media/attachVideoSource.js +49 -0
  64. package/dist/media/attachVideoSource.js.map +1 -0
  65. package/dist/media/channelVideoSource.d.ts +110 -14
  66. package/dist/media/channelVideoSource.d.ts.map +1 -1
  67. package/dist/media/channelVideoSource.js +183 -18
  68. package/dist/media/channelVideoSource.js.map +1 -1
  69. package/dist/media/decoders/frameScheduler.d.ts +119 -0
  70. package/dist/media/decoders/frameScheduler.d.ts.map +1 -0
  71. package/dist/media/decoders/frameScheduler.js +238 -0
  72. package/dist/media/decoders/frameScheduler.js.map +1 -0
  73. package/dist/media/decoders/imageFrameDecoder.d.ts +58 -0
  74. package/dist/media/decoders/imageFrameDecoder.d.ts.map +1 -0
  75. package/dist/media/decoders/imageFrameDecoder.js +110 -0
  76. package/dist/media/decoders/imageFrameDecoder.js.map +1 -0
  77. package/dist/media/decoders/mseFmp4Decoder.d.ts +130 -0
  78. package/dist/media/decoders/mseFmp4Decoder.d.ts.map +1 -0
  79. package/dist/media/decoders/mseFmp4Decoder.js +402 -0
  80. package/dist/media/decoders/mseFmp4Decoder.js.map +1 -0
  81. package/dist/media/decoders/streamCanvas.d.ts +46 -0
  82. package/dist/media/decoders/streamCanvas.d.ts.map +1 -0
  83. package/dist/media/decoders/streamCanvas.js +163 -0
  84. package/dist/media/decoders/streamCanvas.js.map +1 -0
  85. package/dist/media/decoders/videoMimeTypes.d.ts +29 -0
  86. package/dist/media/decoders/videoMimeTypes.d.ts.map +1 -0
  87. package/dist/media/decoders/videoMimeTypes.js +50 -0
  88. package/dist/media/decoders/videoMimeTypes.js.map +1 -0
  89. package/dist/media/decoders/webCodecsChunkDecoder.d.ts +99 -0
  90. package/dist/media/decoders/webCodecsChunkDecoder.d.ts.map +1 -0
  91. package/dist/media/decoders/webCodecsChunkDecoder.js +265 -0
  92. package/dist/media/decoders/webCodecsChunkDecoder.js.map +1 -0
  93. package/dist/media/displayCapture.d.ts +128 -0
  94. package/dist/media/displayCapture.d.ts.map +1 -0
  95. package/dist/media/displayCapture.js +245 -0
  96. package/dist/media/displayCapture.js.map +1 -0
  97. package/dist/media/frameCapture.d.ts +25 -8
  98. package/dist/media/frameCapture.d.ts.map +1 -1
  99. package/dist/media/frameCapture.js +42 -72
  100. package/dist/media/frameCapture.js.map +1 -1
  101. package/dist/media/frameSampler.d.ts +94 -0
  102. package/dist/media/frameSampler.d.ts.map +1 -0
  103. package/dist/media/frameSampler.js +134 -0
  104. package/dist/media/frameSampler.js.map +1 -0
  105. package/dist/media/index.d.ts +32 -0
  106. package/dist/media/index.d.ts.map +1 -0
  107. package/dist/media/index.js +32 -0
  108. package/dist/media/index.js.map +1 -0
  109. package/dist/media/localMediaController.d.ts +116 -0
  110. package/dist/media/localMediaController.d.ts.map +1 -0
  111. package/dist/media/localMediaController.js +281 -0
  112. package/dist/media/localMediaController.js.map +1 -0
  113. package/dist/media/mediaLayout.d.ts +93 -0
  114. package/dist/media/mediaLayout.d.ts.map +1 -0
  115. package/dist/media/mediaLayout.js +187 -0
  116. package/dist/media/mediaLayout.js.map +1 -0
  117. package/dist/media/mediaPreview.d.ts +94 -0
  118. package/dist/media/mediaPreview.d.ts.map +1 -0
  119. package/dist/media/mediaPreview.js +154 -0
  120. package/dist/media/mediaPreview.js.map +1 -0
  121. package/dist/media/mediaStage.d.ts +99 -0
  122. package/dist/media/mediaStage.d.ts.map +1 -0
  123. package/dist/media/mediaStage.js +171 -0
  124. package/dist/media/mediaStage.js.map +1 -0
  125. package/dist/media/model.d.ts +154 -0
  126. package/dist/media/model.d.ts.map +1 -0
  127. package/dist/media/model.js +9 -0
  128. package/dist/media/model.js.map +1 -0
  129. package/dist/media/playbackClock.d.ts +20 -0
  130. package/dist/media/playbackClock.d.ts.map +1 -0
  131. package/dist/media/playbackClock.js +13 -0
  132. package/dist/media/playbackClock.js.map +1 -0
  133. package/dist/media/videoFrameDecoder.d.ts +86 -0
  134. package/dist/media/videoFrameDecoder.d.ts.map +1 -0
  135. package/dist/media/videoFrameDecoder.js +2 -0
  136. package/dist/media/videoFrameDecoder.js.map +1 -0
  137. package/dist/media/videoFrameDecoderRegistry.d.ts +40 -0
  138. package/dist/media/videoFrameDecoderRegistry.d.ts.map +1 -0
  139. package/dist/media/videoFrameDecoderRegistry.js +69 -0
  140. package/dist/media/videoFrameDecoderRegistry.js.map +1 -0
  141. package/dist/media/videoPacing.d.ts +32 -0
  142. package/dist/media/videoPacing.d.ts.map +1 -0
  143. package/dist/media/videoPacing.js +37 -0
  144. package/dist/media/videoPacing.js.map +1 -0
  145. package/dist/media/videoPlayout.d.ts +168 -0
  146. package/dist/media/videoPlayout.d.ts.map +1 -0
  147. package/dist/media/videoPlayout.js +217 -0
  148. package/dist/media/videoPlayout.js.map +1 -0
  149. package/dist/media/videoSourceArbiter.d.ts +250 -0
  150. package/dist/media/videoSourceArbiter.d.ts.map +1 -0
  151. package/dist/media/videoSourceArbiter.js +423 -0
  152. package/dist/media/videoSourceArbiter.js.map +1 -0
  153. package/dist/testing/conformanceAssertions.d.ts +25 -0
  154. package/dist/testing/conformanceAssertions.d.ts.map +1 -0
  155. package/dist/testing/conformanceAssertions.js +64 -0
  156. package/dist/testing/conformanceAssertions.js.map +1 -0
  157. package/dist/testing/conformanceFixtures.d.ts +76 -0
  158. package/dist/testing/conformanceFixtures.d.ts.map +1 -0
  159. package/dist/testing/conformanceFixtures.js +169 -0
  160. package/dist/testing/conformanceFixtures.js.map +1 -0
  161. package/dist/testing/conformanceGates.d.ts +32 -0
  162. package/dist/testing/conformanceGates.d.ts.map +1 -0
  163. package/dist/testing/conformanceGates.js +35 -0
  164. package/dist/testing/conformanceGates.js.map +1 -0
  165. package/dist/testing/conformanceMicrophone.d.ts +10 -0
  166. package/dist/testing/conformanceMicrophone.d.ts.map +1 -0
  167. package/dist/testing/conformanceMicrophone.js +71 -0
  168. package/dist/testing/conformanceMicrophone.js.map +1 -0
  169. package/dist/testing/conformanceTimeline.d.ts +128 -0
  170. package/dist/testing/conformanceTimeline.d.ts.map +1 -0
  171. package/dist/testing/conformanceTimeline.js +32 -0
  172. package/dist/testing/conformanceTimeline.js.map +1 -0
  173. package/dist/testing/conformanceVideoStream.d.ts +29 -0
  174. package/dist/testing/conformanceVideoStream.d.ts.map +1 -0
  175. package/dist/testing/conformanceVideoStream.js +39 -0
  176. package/dist/testing/conformanceVideoStream.js.map +1 -0
  177. package/dist/testing/index.d.ts +29 -0
  178. package/dist/testing/index.d.ts.map +1 -0
  179. package/dist/testing/index.js +28 -0
  180. package/dist/testing/index.js.map +1 -0
  181. package/dist/testing/realtimeVideoConformance.d.ts +23 -0
  182. package/dist/testing/realtimeVideoConformance.d.ts.map +1 -0
  183. package/dist/testing/realtimeVideoConformance.js +139 -0
  184. package/dist/testing/realtimeVideoConformance.js.map +1 -0
  185. package/dist/testing/realtimeVideoConformanceChecks.d.ts +4 -0
  186. package/dist/testing/realtimeVideoConformanceChecks.d.ts.map +1 -0
  187. package/dist/testing/realtimeVideoConformanceChecks.js +164 -0
  188. package/dist/testing/realtimeVideoConformanceChecks.js.map +1 -0
  189. package/dist/testing/realtimeVideoConformanceFrameChecks.d.ts +4 -0
  190. package/dist/testing/realtimeVideoConformanceFrameChecks.d.ts.map +1 -0
  191. package/dist/testing/realtimeVideoConformanceFrameChecks.js +63 -0
  192. package/dist/testing/realtimeVideoConformanceFrameChecks.js.map +1 -0
  193. package/dist/testing/realtimeVideoConformanceSession.d.ts +108 -0
  194. package/dist/testing/realtimeVideoConformanceSession.d.ts.map +1 -0
  195. package/dist/testing/realtimeVideoConformanceSession.js +270 -0
  196. package/dist/testing/realtimeVideoConformanceSession.js.map +1 -0
  197. package/dist/testing/realtimeVideoConformanceTurnChecks.d.ts +4 -0
  198. package/dist/testing/realtimeVideoConformanceTurnChecks.d.ts.map +1 -0
  199. package/dist/testing/realtimeVideoConformanceTurnChecks.js +248 -0
  200. package/dist/testing/realtimeVideoConformanceTurnChecks.js.map +1 -0
  201. package/dist/testing/realtimeVideoConformanceTypes.d.ts +155 -0
  202. package/dist/testing/realtimeVideoConformanceTypes.d.ts.map +1 -0
  203. package/dist/testing/realtimeVideoConformanceTypes.js +2 -0
  204. package/dist/testing/realtimeVideoConformanceTypes.js.map +1 -0
  205. package/dist/testing/recordingPlayout.d.ts +84 -0
  206. package/dist/testing/recordingPlayout.d.ts.map +1 -0
  207. package/dist/testing/recordingPlayout.js +120 -0
  208. package/dist/testing/recordingPlayout.js.map +1 -0
  209. package/package.json +29 -4
@@ -0,0 +1,128 @@
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
+ /** What the user is asked to share. */
27
+ export type DisplayCaptureSurface = 'screen' | 'window' | 'tab';
28
+ /** What a capture turned out to be; `'unknown'` when the browser doesn't say. */
29
+ export type CapturedDisplaySurface = DisplayCaptureSurface | 'unknown';
30
+ /** How a panel capture was narrowed to its element. */
31
+ export type PanelCaptureMethod = 'element' | 'region';
32
+ /** What this browser can capture. */
33
+ export interface DisplayCaptureSupport {
34
+ /** A screen, window or tab can be shared (`getDisplayMedia`). */
35
+ Display: boolean;
36
+ /** Element Capture (`RestrictionTarget`, Chromium 132+). */
37
+ ElementCapture: boolean;
38
+ /** Region Capture (`CropTarget`, Chromium 104+). */
39
+ RegionCapture: boolean;
40
+ }
41
+ export interface DisplayCaptureOptions {
42
+ /**
43
+ * The kind of surface the picker offers first. A hint: the user can still pick another kind, and only
44
+ * Chromium browsers read it. Ignored for a panel capture, which asks for this tab.
45
+ */
46
+ PreferredSurface?: DisplayCaptureSurface;
47
+ /**
48
+ * Share only this element of the page. Needs Element or Region Capture (see
49
+ * {@link GetDisplayCaptureSupport}); Element Capture is used where the browser has it. Element Capture emits
50
+ * frames only while the element is its own stacking context, so unless it already is one, the element's
51
+ * inline style gets `isolation: isolate` while it is shared and its own inline value back when the share
52
+ * ends. Meanwhile its descendants stack inside it: one with a high `z-index` no longer paints over content
53
+ * outside the panel.
54
+ */
55
+ Panel?: Element;
56
+ /**
57
+ * The panel's name, such as "Whiteboard", carried on the capture ({@link DisplayCapture.PanelLabel}) so the
58
+ * UI and the agent can name what is shared. Read only with {@link Panel}.
59
+ */
60
+ PanelLabel?: string;
61
+ /**
62
+ * Also capture the shared surface's audio, where the browser offers it (Chromium: tab or system audio).
63
+ * Defaults to `false`: the agent already hears the microphone.
64
+ */
65
+ IncludeAudio?: boolean;
66
+ }
67
+ /** A live share. */
68
+ export interface DisplayCapture {
69
+ readonly Stream: MediaStream;
70
+ /** The shared video track. */
71
+ readonly Track: MediaStreamTrack;
72
+ /** What is being shared now. It can change if the user switches surfaces mid-share. */
73
+ readonly Surface: CapturedDisplaySurface;
74
+ /** The browser's label for the shared surface, such as a window or tab title. */
75
+ readonly Label: string;
76
+ /** How the stream was narrowed, for a panel capture. */
77
+ readonly PanelMethod?: PanelCaptureMethod;
78
+ /** The shared panel's name, for a panel capture that was given one ({@link DisplayCaptureOptions.PanelLabel}). */
79
+ readonly PanelLabel?: string;
80
+ /**
81
+ * Calls `handler` once when the share ends: the user pressed the browser's "Stop sharing", the shared
82
+ * surface closed, or {@link DisplayCapture.Stop} was called. If the share has already ended, `handler` is
83
+ * called at once.
84
+ *
85
+ * @returns A function that removes the handler.
86
+ */
87
+ OnEnded(handler: () => void): () => void;
88
+ /** Stops sharing. Calling it again does nothing. */
89
+ Stop(): void;
90
+ }
91
+ /** Why a capture failed. */
92
+ export type DisplayCaptureFailure =
93
+ /** The browser cannot share a screen at all (mobile browsers, or no DOM). */
94
+ 'unsupported'
95
+ /** A panel was asked for, but the browser has neither Element nor Region Capture (Firefox, Safari). */
96
+ | 'panel-unsupported'
97
+ /** A panel was asked for, but the user shared a screen, a window or another tab. The capture was stopped. */
98
+ | 'panel-wrong-surface'
99
+ /** The operating system or the page's permissions policy blocked sharing. */
100
+ | 'denied'
101
+ /** Anything else; see the message. */
102
+ | 'error';
103
+ /** The outcome of {@link RequestDisplayCapture}. It always resolves; it never rejects. */
104
+ export type DisplayCaptureResult = {
105
+ Status: 'started';
106
+ Capture: DisplayCapture;
107
+ } | {
108
+ Status: 'cancelled';
109
+ } | {
110
+ Status: 'failed';
111
+ Reason: DisplayCaptureFailure;
112
+ Message: string;
113
+ };
114
+ /** What this browser can capture. */
115
+ export declare function GetDisplayCaptureSupport(): DisplayCaptureSupport;
116
+ /**
117
+ * Opens the browser's share picker and starts sharing what the user picks. Call it from a user gesture.
118
+ *
119
+ * @param options What to offer, whether to share only a panel, and whether to include audio.
120
+ * @returns `started` with the live capture, `cancelled` when the user closed the picker, or `failed` with a reason.
121
+ */
122
+ export declare function RequestDisplayCapture(options?: DisplayCaptureOptions): Promise<DisplayCaptureResult>;
123
+ /**
124
+ * The kind of surface a captured track shows, from the browser's `displaySurface` setting. It reads any display
125
+ * track, including one captured elsewhere, such as a LiveKit screen share.
126
+ */
127
+ export declare function CapturedSurfaceOf(track: MediaStreamTrack): CapturedDisplaySurface;
128
+ //# sourceMappingURL=displayCapture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"displayCapture.d.ts","sourceRoot":"","sources":["../../src/media/displayCapture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,uCAAuC;AACvC,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEhE,iFAAiF;AACjF,MAAM,MAAM,sBAAsB,GAAG,qBAAqB,GAAG,SAAS,CAAC;AAEvE,uDAAuD;AACvD,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEtD,qCAAqC;AACrC,MAAM,WAAW,qBAAqB;IAClC,iEAAiE;IACjE,OAAO,EAAE,OAAO,CAAC;IACjB,4DAA4D;IAC5D,cAAc,EAAE,OAAO,CAAC;IACxB,oDAAoD;IACpD,aAAa,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,qBAAqB;IAClC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,qBAAqB,CAAC;IACzC;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,oBAAoB;AACpB,MAAM,WAAW,cAAc;IAC3B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,8BAA8B;IAC9B,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IACjC,uFAAuF;IACvF,QAAQ,CAAC,OAAO,EAAE,sBAAsB,CAAC;IACzC,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,wDAAwD;IACxD,QAAQ,CAAC,WAAW,CAAC,EAAE,kBAAkB,CAAC;IAC1C,kHAAkH;IAClH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;;OAMG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IACzC,oDAAoD;IACpD,IAAI,IAAI,IAAI,CAAC;CAChB;AAED,4BAA4B;AAC5B,MAAM,MAAM,qBAAqB;AAC7B,6EAA6E;AAC3E,aAAa;AACf,uGAAuG;GACrG,mBAAmB;AACrB,6GAA6G;GAC3G,qBAAqB;AACvB,6EAA6E;GAC3E,QAAQ;AACV,sCAAsC;GACpC,OAAO,CAAC;AAEd,0FAA0F;AAC1F,MAAM,MAAM,oBAAoB,GAC1B;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,cAAc,CAAA;CAAE,GAC9C;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,GACvB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,qBAAqB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AA0C3E,qCAAqC;AACrC,wBAAgB,wBAAwB,IAAI,qBAAqB,CAOhE;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA6B9G;AAoHD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,sBAAsB,CAWjF"}
@@ -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`: prompts via `getUserMedia` (consent-gated via {@link RealtimeTrackDescriptor.RequiresConsent}).
6
- * - `CreateScreenCapture`: prompts via `getDisplayMedia` (consent-gated via {@link RealtimeTrackDescriptor.RequiresConsent}).
7
- * - `CreateStreamFrameCapture`: extracts periodic JPEG frames from an already-acquired `MediaStream`.
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
- * Cadence is throttled to at most 1 frame per second (1 fps ceiling per Live API capabilities guide).
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
- * Capture cadence in frames per second (fps).
37
- * Capped at 1 fps maximum (Gemini Live ceiling). Defaults to `Descriptor?.Rate ?? 1`.
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 CreateStreamFrameCapture}. */
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;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAElE;;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;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACpC,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,mBAAmB,GAC7B,aAAa,CAyEf;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACrC,OAAO,EAAE,mBAAmB,EAC5B,WAAW,CAAC,EAAE,qBAAqB,GACpC,OAAO,CAAC,aAAa,CAAC,CAqBxB;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACrC,OAAO,EAAE,mBAAmB,EAC5B,mBAAmB,CAAC,EAAE,yBAAyB,GAChD,OAAO,CAAC,aAAa,CAAC,CAqBxB;AAED,wDAAwD;AACxD,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
+ {"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`: prompts via `getUserMedia` (consent-gated via {@link RealtimeTrackDescriptor.RequiresConsent}).
6
- * - `CreateScreenCapture`: prompts via `getDisplayMedia` (consent-gated via {@link RealtimeTrackDescriptor.RequiresConsent}).
7
- * - `CreateStreamFrameCapture`: extracts periodic JPEG frames from an already-acquired `MediaStream`.
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
- * Cadence is throttled to at most 1 frame per second (1 fps ceiling per Live API capabilities guide).
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
- const rawRate = options.Rate ?? options.Descriptor?.Rate ?? 1;
22
- // Cadence ceiling: max 1 fps per Gemini Live API specs; minimum 0.1 fps
23
- const rate = Math.min(Math.max(rawRate, 0.1), 1);
24
- const intervalMs = Math.floor(1000 / rate);
25
- const mimeType = options.MimeType ?? 'image/jpeg';
26
- const quality = options.Quality ?? 0.8;
27
- let stopped = false;
28
- let timer = null;
29
- let videoEl = null;
30
- let canvasEl = null;
31
- if (typeof document !== 'undefined' && typeof document.createElement === 'function') {
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 }, frameRate: { max: 1 } },
72
+ video: constraints ?? { width: { ideal: 1280 }, height: { ideal: 720 } },
106
73
  });
107
- const capture = CreateStreamFrameCapture(stream, options);
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
- const stream = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions ?? { video: { frameRate: { max: 1 } } });
134
- const capture = CreateStreamFrameCapture(stream, options);
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 CreateStreamFrameCapture}. */
115
+ /** @deprecated Use {@link FrameSampler}. */
146
116
  export function createStreamFrameCapture(stream, options) {
147
117
  return CreateStreamFrameCapture(stream, options);
148
118
  }