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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) 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 +107 -0
  33. package/dist/drivers/geminiEnterpriseRealtimeClient.js.map +1 -0
  34. package/dist/drivers/geminiRealtimeClient.d.ts +314 -48
  35. package/dist/drivers/geminiRealtimeClient.d.ts.map +1 -1
  36. package/dist/drivers/geminiRealtimeClient.js +759 -176
  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/generic/baseRealtimeClient.d.ts +173 -29
  47. package/dist/generic/baseRealtimeClient.d.ts.map +1 -1
  48. package/dist/generic/baseRealtimeClient.js +233 -14
  49. package/dist/generic/baseRealtimeClient.js.map +1 -1
  50. package/dist/generic/openAIProtocolClient.d.ts +2 -0
  51. package/dist/generic/openAIProtocolClient.d.ts.map +1 -1
  52. package/dist/generic/openAIProtocolClient.js +14 -0
  53. package/dist/generic/openAIProtocolClient.js.map +1 -1
  54. package/dist/index.d.ts +2 -3
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +3 -3
  57. package/dist/index.js.map +1 -1
  58. package/dist/media/attachVideoSource.d.ts +23 -0
  59. package/dist/media/attachVideoSource.d.ts.map +1 -0
  60. package/dist/media/attachVideoSource.js +49 -0
  61. package/dist/media/attachVideoSource.js.map +1 -0
  62. package/dist/media/channelVideoSource.d.ts +110 -14
  63. package/dist/media/channelVideoSource.d.ts.map +1 -1
  64. package/dist/media/channelVideoSource.js +183 -18
  65. package/dist/media/channelVideoSource.js.map +1 -1
  66. package/dist/media/decoders/frameScheduler.d.ts +119 -0
  67. package/dist/media/decoders/frameScheduler.d.ts.map +1 -0
  68. package/dist/media/decoders/frameScheduler.js +238 -0
  69. package/dist/media/decoders/frameScheduler.js.map +1 -0
  70. package/dist/media/decoders/imageFrameDecoder.d.ts +58 -0
  71. package/dist/media/decoders/imageFrameDecoder.d.ts.map +1 -0
  72. package/dist/media/decoders/imageFrameDecoder.js +110 -0
  73. package/dist/media/decoders/imageFrameDecoder.js.map +1 -0
  74. package/dist/media/decoders/mseFmp4Decoder.d.ts +130 -0
  75. package/dist/media/decoders/mseFmp4Decoder.d.ts.map +1 -0
  76. package/dist/media/decoders/mseFmp4Decoder.js +402 -0
  77. package/dist/media/decoders/mseFmp4Decoder.js.map +1 -0
  78. package/dist/media/decoders/streamCanvas.d.ts +46 -0
  79. package/dist/media/decoders/streamCanvas.d.ts.map +1 -0
  80. package/dist/media/decoders/streamCanvas.js +163 -0
  81. package/dist/media/decoders/streamCanvas.js.map +1 -0
  82. package/dist/media/decoders/videoMimeTypes.d.ts +29 -0
  83. package/dist/media/decoders/videoMimeTypes.d.ts.map +1 -0
  84. package/dist/media/decoders/videoMimeTypes.js +50 -0
  85. package/dist/media/decoders/videoMimeTypes.js.map +1 -0
  86. package/dist/media/decoders/webCodecsChunkDecoder.d.ts +99 -0
  87. package/dist/media/decoders/webCodecsChunkDecoder.d.ts.map +1 -0
  88. package/dist/media/decoders/webCodecsChunkDecoder.js +265 -0
  89. package/dist/media/decoders/webCodecsChunkDecoder.js.map +1 -0
  90. package/dist/media/displayCapture.d.ts +128 -0
  91. package/dist/media/displayCapture.d.ts.map +1 -0
  92. package/dist/media/displayCapture.js +245 -0
  93. package/dist/media/displayCapture.js.map +1 -0
  94. package/dist/media/frameCapture.d.ts +25 -8
  95. package/dist/media/frameCapture.d.ts.map +1 -1
  96. package/dist/media/frameCapture.js +42 -72
  97. package/dist/media/frameCapture.js.map +1 -1
  98. package/dist/media/frameSampler.d.ts +94 -0
  99. package/dist/media/frameSampler.d.ts.map +1 -0
  100. package/dist/media/frameSampler.js +134 -0
  101. package/dist/media/frameSampler.js.map +1 -0
  102. package/dist/media/index.d.ts +32 -0
  103. package/dist/media/index.d.ts.map +1 -0
  104. package/dist/media/index.js +32 -0
  105. package/dist/media/index.js.map +1 -0
  106. package/dist/media/localMediaController.d.ts +116 -0
  107. package/dist/media/localMediaController.d.ts.map +1 -0
  108. package/dist/media/localMediaController.js +281 -0
  109. package/dist/media/localMediaController.js.map +1 -0
  110. package/dist/media/mediaLayout.d.ts +93 -0
  111. package/dist/media/mediaLayout.d.ts.map +1 -0
  112. package/dist/media/mediaLayout.js +187 -0
  113. package/dist/media/mediaLayout.js.map +1 -0
  114. package/dist/media/mediaPreview.d.ts +94 -0
  115. package/dist/media/mediaPreview.d.ts.map +1 -0
  116. package/dist/media/mediaPreview.js +154 -0
  117. package/dist/media/mediaPreview.js.map +1 -0
  118. package/dist/media/mediaStage.d.ts +99 -0
  119. package/dist/media/mediaStage.d.ts.map +1 -0
  120. package/dist/media/mediaStage.js +171 -0
  121. package/dist/media/mediaStage.js.map +1 -0
  122. package/dist/media/model.d.ts +154 -0
  123. package/dist/media/model.d.ts.map +1 -0
  124. package/dist/media/model.js +9 -0
  125. package/dist/media/model.js.map +1 -0
  126. package/dist/media/playbackClock.d.ts +20 -0
  127. package/dist/media/playbackClock.d.ts.map +1 -0
  128. package/dist/media/playbackClock.js +13 -0
  129. package/dist/media/playbackClock.js.map +1 -0
  130. package/dist/media/videoFrameDecoder.d.ts +86 -0
  131. package/dist/media/videoFrameDecoder.d.ts.map +1 -0
  132. package/dist/media/videoFrameDecoder.js +2 -0
  133. package/dist/media/videoFrameDecoder.js.map +1 -0
  134. package/dist/media/videoFrameDecoderRegistry.d.ts +40 -0
  135. package/dist/media/videoFrameDecoderRegistry.d.ts.map +1 -0
  136. package/dist/media/videoFrameDecoderRegistry.js +69 -0
  137. package/dist/media/videoFrameDecoderRegistry.js.map +1 -0
  138. package/dist/media/videoPacing.d.ts +32 -0
  139. package/dist/media/videoPacing.d.ts.map +1 -0
  140. package/dist/media/videoPacing.js +37 -0
  141. package/dist/media/videoPacing.js.map +1 -0
  142. package/dist/media/videoPlayout.d.ts +168 -0
  143. package/dist/media/videoPlayout.d.ts.map +1 -0
  144. package/dist/media/videoPlayout.js +217 -0
  145. package/dist/media/videoPlayout.js.map +1 -0
  146. package/dist/media/videoSourceArbiter.d.ts +250 -0
  147. package/dist/media/videoSourceArbiter.d.ts.map +1 -0
  148. package/dist/media/videoSourceArbiter.js +423 -0
  149. package/dist/media/videoSourceArbiter.js.map +1 -0
  150. package/dist/testing/conformanceAssertions.d.ts +25 -0
  151. package/dist/testing/conformanceAssertions.d.ts.map +1 -0
  152. package/dist/testing/conformanceAssertions.js +64 -0
  153. package/dist/testing/conformanceAssertions.js.map +1 -0
  154. package/dist/testing/conformanceFixtures.d.ts +76 -0
  155. package/dist/testing/conformanceFixtures.d.ts.map +1 -0
  156. package/dist/testing/conformanceFixtures.js +169 -0
  157. package/dist/testing/conformanceFixtures.js.map +1 -0
  158. package/dist/testing/conformanceGates.d.ts +32 -0
  159. package/dist/testing/conformanceGates.d.ts.map +1 -0
  160. package/dist/testing/conformanceGates.js +35 -0
  161. package/dist/testing/conformanceGates.js.map +1 -0
  162. package/dist/testing/conformanceMicrophone.d.ts +10 -0
  163. package/dist/testing/conformanceMicrophone.d.ts.map +1 -0
  164. package/dist/testing/conformanceMicrophone.js +71 -0
  165. package/dist/testing/conformanceMicrophone.js.map +1 -0
  166. package/dist/testing/conformanceTimeline.d.ts +128 -0
  167. package/dist/testing/conformanceTimeline.d.ts.map +1 -0
  168. package/dist/testing/conformanceTimeline.js +32 -0
  169. package/dist/testing/conformanceTimeline.js.map +1 -0
  170. package/dist/testing/conformanceVideoStream.d.ts +29 -0
  171. package/dist/testing/conformanceVideoStream.d.ts.map +1 -0
  172. package/dist/testing/conformanceVideoStream.js +39 -0
  173. package/dist/testing/conformanceVideoStream.js.map +1 -0
  174. package/dist/testing/index.d.ts +29 -0
  175. package/dist/testing/index.d.ts.map +1 -0
  176. package/dist/testing/index.js +28 -0
  177. package/dist/testing/index.js.map +1 -0
  178. package/dist/testing/realtimeVideoConformance.d.ts +23 -0
  179. package/dist/testing/realtimeVideoConformance.d.ts.map +1 -0
  180. package/dist/testing/realtimeVideoConformance.js +139 -0
  181. package/dist/testing/realtimeVideoConformance.js.map +1 -0
  182. package/dist/testing/realtimeVideoConformanceChecks.d.ts +4 -0
  183. package/dist/testing/realtimeVideoConformanceChecks.d.ts.map +1 -0
  184. package/dist/testing/realtimeVideoConformanceChecks.js +164 -0
  185. package/dist/testing/realtimeVideoConformanceChecks.js.map +1 -0
  186. package/dist/testing/realtimeVideoConformanceFrameChecks.d.ts +4 -0
  187. package/dist/testing/realtimeVideoConformanceFrameChecks.d.ts.map +1 -0
  188. package/dist/testing/realtimeVideoConformanceFrameChecks.js +63 -0
  189. package/dist/testing/realtimeVideoConformanceFrameChecks.js.map +1 -0
  190. package/dist/testing/realtimeVideoConformanceSession.d.ts +108 -0
  191. package/dist/testing/realtimeVideoConformanceSession.d.ts.map +1 -0
  192. package/dist/testing/realtimeVideoConformanceSession.js +270 -0
  193. package/dist/testing/realtimeVideoConformanceSession.js.map +1 -0
  194. package/dist/testing/realtimeVideoConformanceTurnChecks.d.ts +4 -0
  195. package/dist/testing/realtimeVideoConformanceTurnChecks.d.ts.map +1 -0
  196. package/dist/testing/realtimeVideoConformanceTurnChecks.js +248 -0
  197. package/dist/testing/realtimeVideoConformanceTurnChecks.js.map +1 -0
  198. package/dist/testing/realtimeVideoConformanceTypes.d.ts +155 -0
  199. package/dist/testing/realtimeVideoConformanceTypes.d.ts.map +1 -0
  200. package/dist/testing/realtimeVideoConformanceTypes.js +2 -0
  201. package/dist/testing/realtimeVideoConformanceTypes.js.map +1 -0
  202. package/dist/testing/recordingPlayout.d.ts +84 -0
  203. package/dist/testing/recordingPlayout.d.ts.map +1 -0
  204. package/dist/testing/recordingPlayout.js +120 -0
  205. package/dist/testing/recordingPlayout.js.map +1 -0
  206. package/package.json +29 -4
@@ -0,0 +1,281 @@
1
+ /**
2
+ * @fileoverview LOCAL MEDIA CONTROLLER: the user's camera and microphone. It lists devices, starts and stops
3
+ * each kind, moves a live kind to another device, follows device changes, and reports all of it through
4
+ * {@link LocalMediaController.State$}.
5
+ *
6
+ * - **It never starts on its own.** Every capture begins with an explicit {@link LocalMediaController.Start}.
7
+ * Whether frames or audio reach the model is decided where they are sent (the runtime, after the camera
8
+ * check), not here.
9
+ * - **A device switch keeps the stream.** The new track replaces the old one inside the `MediaStream` that
10
+ * {@link LocalMediaController.GetStream} handed out, so a `<video>` self-view or a `FrameSampler` keeps
11
+ * working. Consumers bound to a track rather than a stream (a Web Audio source node, a WebRTC sender) must
12
+ * rebind when `State$` reports the new device; a realtime client does it in `ReplaceMicrophone`. The new
13
+ * track keeps the old one's `enabled` flag, so a muted microphone stays muted. The current device is
14
+ * released before the new one opens, because mobile browsers open one camera at a time; if the new one
15
+ * fails, the previous one is reopened.
16
+ * - **A lost device falls back to the default.** When the device in use goes away (unplugged, Bluetooth
17
+ * dropped), the kind restarts on the system default device. Only when none is left does it report `failed`.
18
+ * - **Capture runs at the device's native frame rate**; pace what the model receives with a `FrameSampler`.
19
+ *
20
+ * Screen sharing is `RequestDisplayCapture`'s job, not this controller's.
21
+ *
22
+ * @module @memberjunction/ai-realtime-client/media
23
+ */
24
+ import { BehaviorSubject } from 'rxjs';
25
+ const DEFAULT_CAMERA_CONSTRAINTS = { width: { ideal: 1280 }, height: { ideal: 720 } };
26
+ const DEFAULT_MICROPHONE_CONSTRAINTS = { echoCancellation: true, noiseSuppression: true, autoGainControl: true };
27
+ const OFF = { Status: 'off' };
28
+ /** The camera and microphone of one browser session. */
29
+ export class LocalMediaController {
30
+ constructor(options = {}) {
31
+ this.options = options;
32
+ this.state = new BehaviorSubject({ Camera: OFF, Microphone: OFF, Devices: [] });
33
+ this.live = { camera: null, microphone: null };
34
+ this.pending = { camera: null, microphone: null };
35
+ /** Bumped by every Stop, so a start that resolves after it knows it was cancelled. */
36
+ this.generation = { camera: 0, microphone: 0 };
37
+ this.onDeviceChange = () => void this.RefreshDevices();
38
+ this.disposed = false;
39
+ mediaDevices()?.addEventListener('devicechange', this.onDeviceChange);
40
+ }
41
+ /** The current state. */
42
+ get State() {
43
+ return this.state.value;
44
+ }
45
+ /** The state, now and on every change. Completes on {@link Dispose}. */
46
+ get State$() {
47
+ return this.state.asObservable();
48
+ }
49
+ /** The live stream of a kind, or `null` while it is off. The same object across device switches. */
50
+ GetStream(kind) {
51
+ return this.live[kind]?.Stream ?? null;
52
+ }
53
+ /**
54
+ * Lists the input devices. Labels stay empty until the user has allowed this site that kind of device. If
55
+ * the browser cannot list them, the last list is kept.
56
+ */
57
+ async RefreshDevices() {
58
+ const devices = mediaDevices();
59
+ if (!devices?.enumerateDevices) {
60
+ return this.State.Devices;
61
+ }
62
+ try {
63
+ const listed = await devices.enumerateDevices();
64
+ const inputs = listed.flatMap((info) => {
65
+ const kind = localKindOf(info.kind);
66
+ return kind ? [{ DeviceID: info.deviceId, Kind: kind, Label: info.label, GroupID: info.groupId }] : [];
67
+ });
68
+ this.publish({ Devices: inputs });
69
+ return inputs;
70
+ }
71
+ catch (err) {
72
+ console.warn('[LocalMediaController] Could not list devices:', err);
73
+ return this.State.Devices;
74
+ }
75
+ }
76
+ /**
77
+ * Starts capturing a kind: on `deviceId` when it is available, otherwise on the system default. If the
78
+ * kind is already on, returns its stream.
79
+ */
80
+ Start(kind, deviceId) {
81
+ const current = this.live[kind];
82
+ if (current) {
83
+ return Promise.resolve({ Status: 'started', Stream: current.Stream });
84
+ }
85
+ let pending = this.pending[kind];
86
+ if (!pending) {
87
+ pending = this.startCapture(kind, deviceId).finally(() => {
88
+ this.pending[kind] = null;
89
+ });
90
+ this.pending[kind] = pending;
91
+ }
92
+ return pending;
93
+ }
94
+ /**
95
+ * Moves a live kind to another device, keeping the same stream. The current device is released first; if
96
+ * the new device fails, the previous one is reopened. A kind that is off is started on that device instead.
97
+ */
98
+ async SwitchDevice(kind, deviceId) {
99
+ const current = this.live[kind];
100
+ if (!current) {
101
+ return this.Start(kind, deviceId);
102
+ }
103
+ const previous = current.Track.getSettings().deviceId;
104
+ const generation = this.beginChange(kind, current);
105
+ const switched = await this.acquire(kind, { exact: deviceId });
106
+ if (!this.isLatest(kind, generation, switched)) {
107
+ return { Status: 'failed', Reason: 'error', Message: 'Stopped or changed again before the switch finished.' };
108
+ }
109
+ if (switched.Status === 'started') {
110
+ this.insertTrack(kind, current, switched.Track);
111
+ return { Status: 'started', Stream: current.Stream };
112
+ }
113
+ await this.reopenOrFail(kind, current, previous ? { exact: previous } : undefined, generation);
114
+ return switched;
115
+ }
116
+ /** Stops a kind and releases its device. */
117
+ Stop(kind) {
118
+ this.generation[kind]++;
119
+ const current = this.live[kind];
120
+ this.live[kind] = null;
121
+ if (current) {
122
+ current.Unwatch();
123
+ current.Stream.getTracks().forEach((track) => track.stop());
124
+ }
125
+ this.publishTrack(kind, OFF);
126
+ }
127
+ /** Stops both kinds, stops following device changes, and completes {@link State$}. */
128
+ Dispose() {
129
+ if (this.disposed) {
130
+ return;
131
+ }
132
+ this.Stop('camera');
133
+ this.Stop('microphone');
134
+ mediaDevices()?.removeEventListener('devicechange', this.onDeviceChange);
135
+ this.disposed = true;
136
+ this.state.complete();
137
+ }
138
+ async startCapture(kind, deviceId) {
139
+ const generation = this.generation[kind];
140
+ this.publishTrack(kind, { Status: 'starting' });
141
+ const acquired = await this.acquire(kind, deviceId ? { ideal: deviceId } : undefined);
142
+ if (!this.isLatest(kind, generation, acquired)) {
143
+ return { Status: 'failed', Reason: 'error', Message: 'Stopped before the device started.' };
144
+ }
145
+ if (acquired.Status === 'failed') {
146
+ this.publishTrack(kind, { Status: 'failed', Failure: acquired.Reason, Message: acquired.Message });
147
+ return acquired;
148
+ }
149
+ const stream = acquired.Stream;
150
+ this.live[kind] = { Stream: stream, Track: acquired.Track, Unwatch: this.watch(kind, acquired.Track) };
151
+ this.publishTrack(kind, onState(acquired.Track));
152
+ // Labels appear once the user has allowed the device.
153
+ void this.RefreshDevices();
154
+ return { Status: 'started', Stream: stream };
155
+ }
156
+ /** Asks the browser for one track of a kind. */
157
+ async acquire(kind, deviceId) {
158
+ const devices = mediaDevices();
159
+ if (!devices?.getUserMedia) {
160
+ return { Status: 'failed', Reason: 'unsupported', Message: 'This browser cannot capture a camera or microphone.' };
161
+ }
162
+ const constraints = { ...this.constraintsFor(kind), ...(deviceId ? { deviceId } : {}) };
163
+ try {
164
+ const stream = await devices.getUserMedia(kind === 'camera' ? { video: constraints } : { audio: constraints });
165
+ const track = (kind === 'camera' ? stream.getVideoTracks() : stream.getAudioTracks())[0];
166
+ if (!track) {
167
+ stream.getTracks().forEach((t) => t.stop());
168
+ return { Status: 'failed', Reason: 'error', Message: `The browser returned no ${kind} track.` };
169
+ }
170
+ return { Status: 'started', Stream: stream, Track: track };
171
+ }
172
+ catch (err) {
173
+ return { Status: 'failed', Reason: failureOf(err), Message: err instanceof Error ? err.message : String(err) };
174
+ }
175
+ }
176
+ constraintsFor(kind) {
177
+ return kind === 'camera'
178
+ ? (this.options.CameraConstraints ?? DEFAULT_CAMERA_CONSTRAINTS)
179
+ : (this.options.MicrophoneConstraints ?? DEFAULT_MICROPHONE_CONSTRAINTS);
180
+ }
181
+ /**
182
+ * Releases a live capture's device ahead of opening another one, and reports the kind as starting.
183
+ *
184
+ * @returns The change's generation: a later change, or a Stop, makes it stale.
185
+ */
186
+ beginChange(kind, current) {
187
+ current.Unwatch();
188
+ current.Stream.removeTrack(current.Track);
189
+ current.Track.stop();
190
+ this.publishTrack(kind, { Status: 'starting' });
191
+ return ++this.generation[kind];
192
+ }
193
+ /** Whether a change is still the latest for its kind. If not, the device it opened is released. */
194
+ isLatest(kind, generation, acquired) {
195
+ if (generation === this.generation[kind]) {
196
+ return true;
197
+ }
198
+ if (acquired.Status === 'started') {
199
+ acquired.Track.stop();
200
+ }
201
+ return false;
202
+ }
203
+ /**
204
+ * Puts a track in the stream of the capture it replaces and reports its device. The track takes over the
205
+ * old one's `enabled` flag, so a muted microphone stays muted on the new device.
206
+ */
207
+ insertTrack(kind, replacing, track) {
208
+ track.enabled = replacing.Track.enabled;
209
+ replacing.Stream.addTrack(track);
210
+ this.live[kind] = { Stream: replacing.Stream, Track: track, Unwatch: this.watch(kind, track) };
211
+ this.publishTrack(kind, onState(track));
212
+ }
213
+ /** Opens a device in place of a released capture; if that fails, stops the kind and reports why. */
214
+ async reopenOrFail(kind, replacing, deviceId, generation) {
215
+ const reopened = await this.acquire(kind, deviceId);
216
+ if (!this.isLatest(kind, generation, reopened)) {
217
+ return;
218
+ }
219
+ if (reopened.Status === 'started') {
220
+ this.insertTrack(kind, replacing, reopened.Track);
221
+ return;
222
+ }
223
+ this.Stop(kind);
224
+ this.publishTrack(kind, { Status: 'failed', Failure: reopened.Reason, Message: reopened.Message });
225
+ }
226
+ /** Follows a live track: when it ends without being stopped here, its device went away. */
227
+ watch(kind, track) {
228
+ const onEnded = () => void this.recoverFromLostDevice(kind, track);
229
+ track.addEventListener('ended', onEnded);
230
+ return () => track.removeEventListener('ended', onEnded);
231
+ }
232
+ /** Restarts a kind whose device went away on the system default, or reports that none is left. */
233
+ async recoverFromLostDevice(kind, lost) {
234
+ const current = this.live[kind];
235
+ if (!current || current.Track !== lost) {
236
+ return;
237
+ }
238
+ const generation = this.beginChange(kind, current);
239
+ await this.reopenOrFail(kind, current, undefined, generation);
240
+ }
241
+ publishTrack(kind, track) {
242
+ this.publish(kind === 'camera' ? { Camera: track } : { Microphone: track });
243
+ }
244
+ publish(change) {
245
+ if (!this.disposed) {
246
+ this.state.next({ ...this.state.value, ...change });
247
+ }
248
+ }
249
+ }
250
+ /** The browser's media devices, or `undefined` where there are none (Node, some embedded views). */
251
+ function mediaDevices() {
252
+ return typeof navigator === 'undefined' ? undefined : navigator.mediaDevices;
253
+ }
254
+ /** The local kind of a browser device kind; `null` for outputs. */
255
+ function localKindOf(kind) {
256
+ if (kind === 'videoinput') {
257
+ return 'camera';
258
+ }
259
+ return kind === 'audioinput' ? 'microphone' : null;
260
+ }
261
+ /** The `on` state for a live track: its device and name. */
262
+ function onState(track) {
263
+ return { Status: 'on', DeviceID: track.getSettings().deviceId, Label: track.label };
264
+ }
265
+ /** Maps a `getUserMedia` rejection to a failure reason. */
266
+ function failureOf(err) {
267
+ switch (err instanceof Error ? err.name : '') {
268
+ case 'NotAllowedError':
269
+ case 'SecurityError':
270
+ return 'denied';
271
+ case 'NotFoundError':
272
+ case 'OverconstrainedError':
273
+ return 'not-found';
274
+ case 'NotReadableError':
275
+ case 'AbortError':
276
+ return 'in-use';
277
+ default:
278
+ return 'error';
279
+ }
280
+ }
281
+ //# sourceMappingURL=localMediaController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localMediaController.js","sourceRoot":"","sources":["../../src/media/localMediaController.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * @fileoverview MEDIA LAYOUT: the user's layout of a media stage as a host keeps and saves it.
3
+ * - **Moves.** One move per surface, oldest first: the list `LayoutMediaStage` and `ResolveSurfacePlacements` read.
4
+ * {@link RecordPlacementMove} keeps it that way, and {@link WithoutStageMoves} hands the stage back to its default.
5
+ * - **Boxes.** Where the user put each picture-in-picture box, by surface key, as fractions of the stage.
6
+ * - **Self-view.** Whether the user hid their own tile, for a host that lets them (the meeting room).
7
+ *
8
+ * The realtime call keeps its channels' layout this way and the meeting room its participants' tiles, so both save the
9
+ * same form ({@link SerializePlacementMoves}, {@link SerializePipRects}, {@link SerializeSelfViewHidden}) and read it
10
+ * back tolerantly, through {@link MediaLayoutPrefs} under each host's own keys.
11
+ *
12
+ * @module @memberjunction/ai-realtime-client/media
13
+ */
14
+ import { type MediaPipRect, type MediaPlacementMove } from './model.js';
15
+ /** Adds a move at the end, dropping the surface's earlier move, so the list keeps one move per surface in order. */
16
+ export declare function RecordPlacementMove(moves: readonly MediaPlacementMove[], move: MediaPlacementMove): MediaPlacementMove[];
17
+ /**
18
+ * The moves without any move to the stage: whatever the user put there goes back to its default. The stage goes to the
19
+ * newest move there, so a host whose "unpin" should hand the stage back to its default, not to an earlier move, drops
20
+ * the stage moves before recording the next one.
21
+ */
22
+ export declare function WithoutStageMoves(moves: readonly MediaPlacementMove[]): MediaPlacementMove[];
23
+ /** Reads saved moves. Tolerant: a value that is not a list reads as no moves, and a malformed entry is skipped. */
24
+ export declare function ParsePlacementMoves(raw: string | null | undefined): MediaPlacementMove[];
25
+ /** The saved form of a list of moves. */
26
+ export declare function SerializePlacementMoves(moves: readonly MediaPlacementMove[]): string;
27
+ /** Adds a box at the end, dropping the surface's earlier box, so the boxes the user moved most recently come last. */
28
+ export declare function RecordPipRect(rects: ReadonlyMap<string, MediaPipRect>, key: string, rect: MediaPipRect): Map<string, MediaPipRect>;
29
+ /**
30
+ * Reads saved picture-in-picture boxes, by surface key. Tolerant: a value that is not an object reads as none, and a box
31
+ * that is not four fractions with a size is skipped.
32
+ */
33
+ export declare function ParsePipRects(raw: string | null | undefined): Map<string, MediaPipRect>;
34
+ /** The saved form of picture-in-picture boxes, by surface key. */
35
+ export declare function SerializePipRects(rects: ReadonlyMap<string, MediaPipRect>): string;
36
+ /**
37
+ * Reads whether the user hid their self-view. Tolerant: only a saved `true` hides it; nothing saved, `false` or anything
38
+ * else shows it.
39
+ */
40
+ export declare function ParseSelfViewHidden(raw: string | null | undefined): boolean;
41
+ /** The saved form of whether the user hid their self-view: JSON `true` or `false`. */
42
+ export declare function SerializeSelfViewHidden(hidden: boolean): string;
43
+ /** A per-user settings store: MJ's `UserInfoEngine` is one, or anything with the same two methods. */
44
+ export interface MediaLayoutSettings {
45
+ /** The text saved under a key, or `undefined` when there is none. */
46
+ GetSetting(key: string): string | undefined;
47
+ /** Saves text under a key; the store may wait for a burst of changes to end. */
48
+ SetSettingDebounced(key: string, value: string): void;
49
+ }
50
+ /** The keys a host saves its layout under, so two hosts never overwrite each other's. */
51
+ export interface MediaLayoutKeys {
52
+ /** Where the moves go. */
53
+ Moves: string;
54
+ /** Where the picture-in-picture boxes go. */
55
+ PipRects: string;
56
+ /** Where whether the user hid their self-view goes. A host with no Hide on the user's own tile leaves it out. */
57
+ SelfViewHidden?: string;
58
+ }
59
+ /** How many moves, and how many boxes, a saved layout keeps: the newest. The oldest go first. */
60
+ export declare const MEDIA_LAYOUT_SAVED_LIMIT = 50;
61
+ /**
62
+ * A host's saved layout: its moves, its picture-in-picture boxes and whether the user hid their self-view, in a per-user
63
+ * settings store under the host's own keys. Reading treats a store that is not ready (it throws) as nothing saved;
64
+ * writing skips one, or one that fails to save, so the layout then lasts for this session only. Writing keeps the newest
65
+ * {@link MEDIA_LAYOUT_SAVED_LIMIT} moves and boxes.
66
+ */
67
+ export declare class MediaLayoutPrefs {
68
+ private readonly store;
69
+ private readonly keys;
70
+ /**
71
+ * @param store The settings store, looked up each time it is used, since a host's store may be ready only later.
72
+ * @param keys Where this host's layout goes.
73
+ */
74
+ constructor(store: () => MediaLayoutSettings, keys: MediaLayoutKeys);
75
+ /** The saved moves, oldest first; none when nothing is saved or the store is not ready. */
76
+ LoadMoves(): MediaPlacementMove[];
77
+ /** The saved boxes, by surface key; none when nothing is saved or the store is not ready. */
78
+ LoadPipRects(): Map<string, MediaPipRect>;
79
+ /** Saves the moves, the newest {@link MEDIA_LAYOUT_SAVED_LIMIT} of them. */
80
+ SaveMoves(moves: readonly MediaPlacementMove[]): void;
81
+ /** Saves the boxes, the newest {@link MEDIA_LAYOUT_SAVED_LIMIT} of them (the last in the map's order). */
82
+ SavePipRects(rects: ReadonlyMap<string, MediaPipRect>): void;
83
+ /**
84
+ * Whether the user hid their self-view: shown when nothing usable is saved, the store is not ready, or the host keeps
85
+ * no self-view setting (it named no key for it).
86
+ */
87
+ LoadSelfViewHidden(): boolean;
88
+ /** Saves whether the user hid their self-view; nothing, for a host that keeps no self-view setting. */
89
+ SaveSelfViewHidden(hidden: boolean): void;
90
+ private read;
91
+ private write;
92
+ }
93
+ //# sourceMappingURL=mediaLayout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mediaLayout.d.ts","sourceRoot":"","sources":["../../src/media/mediaLayout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAoB,KAAK,YAAY,EAAuB,KAAK,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE5G,oHAAoH;AACpH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,kBAAkB,EAAE,EAAE,IAAI,EAAE,kBAAkB,GAAG,kBAAkB,EAAE,CAExH;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,kBAAkB,EAAE,GAAG,kBAAkB,EAAE,CAE5F;AAED,mHAAmH;AACnH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,kBAAkB,EAAE,CAaxF;AAED,yCAAyC;AACzC,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,SAAS,kBAAkB,EAAE,GAAG,MAAM,CAEpF;AAED,sHAAsH;AACtH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAKlI;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAmBvF;AAED,kEAAkE;AAClE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,MAAM,CAElF;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAE3E;AAED,sFAAsF;AACtF,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAE/D;AAED,sGAAsG;AACtG,MAAM,WAAW,mBAAmB;IAChC,qEAAqE;IACrE,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAC5C,gFAAgF;IAChF,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACzD;AAED,yFAAyF;AACzF,MAAM,WAAW,eAAe;IAC5B,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,iHAAiH;IACjH,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,iGAAiG;AACjG,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAE3C;;;;;GAKG;AACH,qBAAa,gBAAgB;IAMrB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI;IANzB;;;OAGG;gBAEkB,KAAK,EAAE,MAAM,mBAAmB,EAChC,IAAI,EAAE,eAAe;IAG1C,2FAA2F;IACpF,SAAS,IAAI,kBAAkB,EAAE;IAIxC,6FAA6F;IACtF,YAAY,IAAI,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC;IAIhD,4EAA4E;IACrE,SAAS,CAAC,KAAK,EAAE,SAAS,kBAAkB,EAAE,GAAG,IAAI;IAI5D,0GAA0G;IACnG,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,IAAI;IAInE;;;OAGG;IACI,kBAAkB,IAAI,OAAO;IAKpC,uGAAuG;IAChG,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAOhD,OAAO,CAAC,IAAI;IAQZ,OAAO,CAAC,KAAK;CAOhB"}
@@ -0,0 +1,187 @@
1
+ /**
2
+ * @fileoverview MEDIA LAYOUT: the user's layout of a media stage as a host keeps and saves it.
3
+ * - **Moves.** One move per surface, oldest first: the list `LayoutMediaStage` and `ResolveSurfacePlacements` read.
4
+ * {@link RecordPlacementMove} keeps it that way, and {@link WithoutStageMoves} hands the stage back to its default.
5
+ * - **Boxes.** Where the user put each picture-in-picture box, by surface key, as fractions of the stage.
6
+ * - **Self-view.** Whether the user hid their own tile, for a host that lets them (the meeting room).
7
+ *
8
+ * The realtime call keeps its channels' layout this way and the meeting room its participants' tiles, so both save the
9
+ * same form ({@link SerializePlacementMoves}, {@link SerializePipRects}, {@link SerializeSelfViewHidden}) and read it
10
+ * back tolerantly, through {@link MediaLayoutPrefs} under each host's own keys.
11
+ *
12
+ * @module @memberjunction/ai-realtime-client/media
13
+ */
14
+ import { MEDIA_PLACEMENTS } from './model.js';
15
+ /** Adds a move at the end, dropping the surface's earlier move, so the list keeps one move per surface in order. */
16
+ export function RecordPlacementMove(moves, move) {
17
+ return [...moves.filter((existing) => existing.SurfaceKey !== move.SurfaceKey), move];
18
+ }
19
+ /**
20
+ * The moves without any move to the stage: whatever the user put there goes back to its default. The stage goes to the
21
+ * newest move there, so a host whose "unpin" should hand the stage back to its default, not to an earlier move, drops
22
+ * the stage moves before recording the next one.
23
+ */
24
+ export function WithoutStageMoves(moves) {
25
+ return moves.filter((move) => move.Placement !== 'stage');
26
+ }
27
+ /** Reads saved moves. Tolerant: a value that is not a list reads as no moves, and a malformed entry is skipped. */
28
+ export function ParsePlacementMoves(raw) {
29
+ if (!raw) {
30
+ return [];
31
+ }
32
+ try {
33
+ const parsed = JSON.parse(raw);
34
+ if (!Array.isArray(parsed)) {
35
+ return [];
36
+ }
37
+ return parsed.filter(isMove).map((move) => ({ SurfaceKey: move.SurfaceKey, Placement: move.Placement }));
38
+ }
39
+ catch {
40
+ return [];
41
+ }
42
+ }
43
+ /** The saved form of a list of moves. */
44
+ export function SerializePlacementMoves(moves) {
45
+ return JSON.stringify(moves.map((move) => ({ SurfaceKey: move.SurfaceKey, Placement: move.Placement })));
46
+ }
47
+ /** Adds a box at the end, dropping the surface's earlier box, so the boxes the user moved most recently come last. */
48
+ export function RecordPipRect(rects, key, rect) {
49
+ const next = new Map(rects);
50
+ next.delete(key);
51
+ next.set(key, rect);
52
+ return next;
53
+ }
54
+ /**
55
+ * Reads saved picture-in-picture boxes, by surface key. Tolerant: a value that is not an object reads as none, and a box
56
+ * that is not four fractions with a size is skipped.
57
+ */
58
+ export function ParsePipRects(raw) {
59
+ const rects = new Map();
60
+ if (!raw) {
61
+ return rects;
62
+ }
63
+ try {
64
+ const parsed = JSON.parse(raw);
65
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
66
+ return rects;
67
+ }
68
+ for (const [key, value] of Object.entries(parsed)) {
69
+ if (isPipRect(value)) {
70
+ rects.set(key, { X: value.X, Y: value.Y, W: value.W, H: value.H });
71
+ }
72
+ }
73
+ return rects;
74
+ }
75
+ catch {
76
+ return rects;
77
+ }
78
+ }
79
+ /** The saved form of picture-in-picture boxes, by surface key. */
80
+ export function SerializePipRects(rects) {
81
+ return JSON.stringify(Object.fromEntries([...rects].map(([key, rect]) => [key, { X: rect.X, Y: rect.Y, W: rect.W, H: rect.H }])));
82
+ }
83
+ /**
84
+ * Reads whether the user hid their self-view. Tolerant: only a saved `true` hides it; nothing saved, `false` or anything
85
+ * else shows it.
86
+ */
87
+ export function ParseSelfViewHidden(raw) {
88
+ return raw === SerializeSelfViewHidden(true);
89
+ }
90
+ /** The saved form of whether the user hid their self-view: JSON `true` or `false`. */
91
+ export function SerializeSelfViewHidden(hidden) {
92
+ return JSON.stringify(hidden);
93
+ }
94
+ /** How many moves, and how many boxes, a saved layout keeps: the newest. The oldest go first. */
95
+ export const MEDIA_LAYOUT_SAVED_LIMIT = 50;
96
+ /**
97
+ * A host's saved layout: its moves, its picture-in-picture boxes and whether the user hid their self-view, in a per-user
98
+ * settings store under the host's own keys. Reading treats a store that is not ready (it throws) as nothing saved;
99
+ * writing skips one, or one that fails to save, so the layout then lasts for this session only. Writing keeps the newest
100
+ * {@link MEDIA_LAYOUT_SAVED_LIMIT} moves and boxes.
101
+ */
102
+ export class MediaLayoutPrefs {
103
+ /**
104
+ * @param store The settings store, looked up each time it is used, since a host's store may be ready only later.
105
+ * @param keys Where this host's layout goes.
106
+ */
107
+ constructor(store, keys) {
108
+ this.store = store;
109
+ this.keys = keys;
110
+ }
111
+ /** The saved moves, oldest first; none when nothing is saved or the store is not ready. */
112
+ LoadMoves() {
113
+ return ParsePlacementMoves(this.read(this.keys.Moves));
114
+ }
115
+ /** The saved boxes, by surface key; none when nothing is saved or the store is not ready. */
116
+ LoadPipRects() {
117
+ return ParsePipRects(this.read(this.keys.PipRects));
118
+ }
119
+ /** Saves the moves, the newest {@link MEDIA_LAYOUT_SAVED_LIMIT} of them. */
120
+ SaveMoves(moves) {
121
+ this.write(this.keys.Moves, SerializePlacementMoves(moves.slice(-MEDIA_LAYOUT_SAVED_LIMIT)));
122
+ }
123
+ /** Saves the boxes, the newest {@link MEDIA_LAYOUT_SAVED_LIMIT} of them (the last in the map's order). */
124
+ SavePipRects(rects) {
125
+ this.write(this.keys.PipRects, SerializePipRects(new Map([...rects].slice(-MEDIA_LAYOUT_SAVED_LIMIT))));
126
+ }
127
+ /**
128
+ * Whether the user hid their self-view: shown when nothing usable is saved, the store is not ready, or the host keeps
129
+ * no self-view setting (it named no key for it).
130
+ */
131
+ LoadSelfViewHidden() {
132
+ const key = this.keys.SelfViewHidden;
133
+ return key !== undefined && ParseSelfViewHidden(this.read(key));
134
+ }
135
+ /** Saves whether the user hid their self-view; nothing, for a host that keeps no self-view setting. */
136
+ SaveSelfViewHidden(hidden) {
137
+ const key = this.keys.SelfViewHidden;
138
+ if (key !== undefined) {
139
+ this.write(key, SerializeSelfViewHidden(hidden));
140
+ }
141
+ }
142
+ read(key) {
143
+ try {
144
+ return this.store().GetSetting(key);
145
+ }
146
+ catch {
147
+ return undefined;
148
+ }
149
+ }
150
+ write(key, value) {
151
+ try {
152
+ this.store().SetSettingDebounced(key, value);
153
+ }
154
+ catch {
155
+ // The store is not ready, or failed to save: the layout lasts for this session only.
156
+ }
157
+ }
158
+ }
159
+ function isMove(value) {
160
+ return (typeof value === 'object' &&
161
+ value !== null &&
162
+ 'SurfaceKey' in value &&
163
+ typeof value.SurfaceKey === 'string' &&
164
+ 'Placement' in value &&
165
+ isPlacement(value.Placement));
166
+ }
167
+ function isPlacement(value) {
168
+ return typeof value === 'string' && MEDIA_PLACEMENTS.includes(value);
169
+ }
170
+ function isPipRect(value) {
171
+ return (typeof value === 'object' &&
172
+ value !== null &&
173
+ 'X' in value &&
174
+ 'Y' in value &&
175
+ 'W' in value &&
176
+ 'H' in value &&
177
+ isFraction(value.X) &&
178
+ isFraction(value.Y) &&
179
+ isFraction(value.W) &&
180
+ isFraction(value.H) &&
181
+ value.W > 0 &&
182
+ value.H > 0);
183
+ }
184
+ function isFraction(value) {
185
+ return typeof value === 'number' && Number.isFinite(value) && value >= 0 && value <= 1;
186
+ }
187
+ //# sourceMappingURL=mediaLayout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mediaLayout.js","sourceRoot":"","sources":["../../src/media/mediaLayout.ts"],"names":[],"mappings":"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"}