@ohm_studio/sdk 0.2.0 → 0.5.0

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/dist/recorder.js CHANGED
@@ -1,22 +1,109 @@
1
- /**
2
- * Browser MediaRecorder wrapper. Hides the boilerplate of permissions,
3
- * stream tracks, chunk collection, and cleanup so customers can ship a
4
- * working recorder UI in three lines:
5
- *
6
- * const rec = new Recorder();
7
- * await rec.start();
8
- * const blob = await rec.stop(); // → ready to pass to ohm.audio.extract
9
- *
10
- * Designed for Vite / Next.js / CRA / any modern browser. SSR-safe — the
11
- * `MediaRecorder` API is only touched inside method bodies, so importing
12
- * this module doesn't break server bundles.
13
- */
14
- /** Returns true if the runtime supports recording (browser with MediaRecorder). */
1
+ // Lazy-loaded — only used when the produced Blob is WebM, so non-WebM
2
+ // browsers don't pay the parse cost.
3
+ let fixWebmDurationModule;
4
+ async function patchWebmDuration(blob, durationMs) {
5
+ if (!blob.type.includes("webm"))
6
+ return blob;
7
+ if (durationMs <= 0)
8
+ return blob;
9
+ try {
10
+ if (!fixWebmDurationModule) {
11
+ const mod = await import("fix-webm-duration");
12
+ // The package's main export is the function itself, but some
13
+ // bundlers wrap it as { default: fn }. Handle both shapes.
14
+ fixWebmDurationModule =
15
+ typeof mod === "function"
16
+ ? mod
17
+ : typeof mod.default === "function"
18
+ ? mod.default
19
+ : mod.fixWebmDuration;
20
+ }
21
+ if (!fixWebmDurationModule)
22
+ return blob;
23
+ return await fixWebmDurationModule(blob, durationMs);
24
+ }
25
+ catch {
26
+ // If patching fails for any reason (lib missing, parse error,
27
+ // unexpected format), return the original blob — the audio is fine,
28
+ // only the duration metadata is off.
29
+ return blob;
30
+ }
31
+ }
32
+ export class RecorderError extends Error {
33
+ code;
34
+ cause;
35
+ constructor(code, message, cause) {
36
+ super(message);
37
+ this.name = "RecorderError";
38
+ this.code = code;
39
+ this.cause = cause;
40
+ }
41
+ }
42
+ const MIME_CASCADE = [
43
+ "audio/webm;codecs=opus",
44
+ "audio/mp4;codecs=mp4a.40.2",
45
+ "audio/ogg;codecs=opus",
46
+ "audio/mp4",
47
+ "audio/webm",
48
+ ];
49
+ function clinicalConstraints(deviceId) {
50
+ const base = {
51
+ echoCancellation: true,
52
+ noiseSuppression: true,
53
+ autoGainControl: true,
54
+ channelCount: { ideal: 1 },
55
+ sampleRate: { ideal: 16_000 },
56
+ sampleSize: { ideal: 16 },
57
+ };
58
+ if (deviceId)
59
+ base.deviceId = { exact: deviceId };
60
+ return base;
61
+ }
62
+ function pickMimeType(requested) {
63
+ if (typeof MediaRecorder === "undefined")
64
+ return undefined;
65
+ const probe = (m) => {
66
+ try {
67
+ return MediaRecorder.isTypeSupported(m);
68
+ }
69
+ catch {
70
+ return false;
71
+ }
72
+ };
73
+ if (requested && probe(requested))
74
+ return requested;
75
+ for (const m of MIME_CASCADE)
76
+ if (probe(m))
77
+ return m;
78
+ return undefined; // browser will pick its own fallback
79
+ }
80
+ function mapDomError(err) {
81
+ const name = (err && err.name) || "";
82
+ switch (name) {
83
+ case "NotAllowedError":
84
+ case "SecurityError":
85
+ return new RecorderError("PermissionDenied", "Microphone access was denied. Ask the user to allow it in browser settings.", err);
86
+ case "NotFoundError":
87
+ case "DevicesNotFoundError":
88
+ return new RecorderError("NoMicrophone", "No microphone was found.", err);
89
+ case "NotReadableError":
90
+ case "TrackStartError":
91
+ return new RecorderError("MicrophoneBusy", "The microphone is in use by another app.", err);
92
+ case "OverconstrainedError":
93
+ case "ConstraintNotSatisfiedError":
94
+ return new RecorderError("OverConstrained", "The requested audio constraints can't be satisfied by this device.", err);
95
+ default:
96
+ return new RecorderError("Unknown", (err && err.message) || "Recorder error", err);
97
+ }
98
+ }
99
+ /** True if the runtime supports recording (browser with MediaRecorder + getUserMedia). */
15
100
  export function isRecordingSupported() {
16
101
  if (typeof window === "undefined")
17
102
  return false;
18
103
  if (typeof navigator === "undefined" || !navigator.mediaDevices)
19
104
  return false;
105
+ if (typeof navigator.mediaDevices.getUserMedia !== "function")
106
+ return false;
20
107
  if (typeof globalThis.MediaRecorder === "undefined")
21
108
  return false;
22
109
  return true;
@@ -27,74 +114,260 @@ export class Recorder {
27
114
  stream = null;
28
115
  state = "idle";
29
116
  opts;
117
+ mime;
118
+ startedAt = 0;
119
+ pausedAccumMs = 0;
120
+ pauseStartedAt = 0;
121
+ maxStopTimer = null;
122
+ // Level metering
123
+ audioCtx = null;
124
+ analyser = null;
125
+ levelSource = null;
126
+ levelRafId = null;
127
+ levelBuffer = null;
128
+ // Silence
129
+ silenceSinceMs = 0;
130
+ // Wake lock
131
+ wakeLockSentinel = null;
132
+ // Visibility
133
+ visibilityHandler = null;
30
134
  constructor(opts = {}) {
31
135
  this.opts = opts;
32
136
  }
33
- /** Current recorder state. */
137
+ /** Static support check. */
138
+ static isSupported() {
139
+ return isRecordingSupported();
140
+ }
141
+ /** Pick the best supported MIME type for this browser. */
142
+ static getSupportedMimeType(prefer) {
143
+ return pickMimeType(prefer);
144
+ }
145
+ /**
146
+ * Probe microphone permission *without* requesting it. Returns:
147
+ * "granted" — already allowed
148
+ * "denied" — user has blocked access; calling start() will reject
149
+ * "prompt" — browser will show the dialog on next start()
150
+ * "unknown" — browser doesn't support the Permissions API
151
+ */
152
+ static async probePermission() {
153
+ if (typeof navigator === "undefined" ||
154
+ !navigator.permissions ||
155
+ typeof navigator.permissions.query !== "function") {
156
+ return "unknown";
157
+ }
158
+ try {
159
+ const status = await navigator.permissions.query({
160
+ name: "microphone",
161
+ });
162
+ return status.state;
163
+ }
164
+ catch {
165
+ return "unknown";
166
+ }
167
+ }
168
+ /** Enumerate microphones. Empty `label` until permission is granted at least once. */
169
+ static async listMicrophones() {
170
+ if (typeof navigator === "undefined" ||
171
+ !navigator.mediaDevices ||
172
+ typeof navigator.mediaDevices.enumerateDevices !== "function") {
173
+ return [];
174
+ }
175
+ const devices = await navigator.mediaDevices.enumerateDevices();
176
+ return devices
177
+ .filter((d) => d.kind === "audioinput")
178
+ .map((d) => ({ deviceId: d.deviceId, label: d.label, groupId: d.groupId }));
179
+ }
180
+ /** Current state. */
34
181
  get currentState() {
35
182
  return this.state;
36
183
  }
184
+ /** Final MIME type the browser is producing (set after `start`). */
185
+ get mimeType() {
186
+ return this.rec?.mimeType || this.mime;
187
+ }
188
+ /** Recorded duration in ms (excluding paused time). 0 when idle. */
189
+ getDuration() {
190
+ if (this.state === "idle")
191
+ return 0;
192
+ const now = Date.now();
193
+ if (this.state === "paused") {
194
+ return this.pauseStartedAt - this.startedAt - this.pausedAccumMs;
195
+ }
196
+ return now - this.startedAt - this.pausedAccumMs;
197
+ }
37
198
  /**
38
199
  * Request microphone access and begin recording. Resolves once the
39
- * underlying MediaRecorder fires its `start` event. Throws on permission
40
- * denial or unsupported runtime.
200
+ * underlying MediaRecorder has fired `start`.
41
201
  */
42
202
  async start() {
43
203
  if (!isRecordingSupported()) {
44
- throw new Error("Recording not supported — MediaRecorder is unavailable in this runtime");
204
+ throw new RecorderError("NotSupported", "Recording isn't supported in this runtime — MediaRecorder or getUserMedia is missing.");
45
205
  }
46
206
  if (this.state !== "idle") {
47
- throw new Error(`Cannot start recorder while ${this.state}`);
207
+ throw new RecorderError("InvalidState", `Cannot start while recorder is "${this.state}".`);
208
+ }
209
+ this.setState("starting");
210
+ const constraints = this.opts.audioConstraints ??
211
+ (this.opts.clinicalDefaults === false
212
+ ? true
213
+ : clinicalConstraints(this.opts.deviceId));
214
+ try {
215
+ this.stream = await navigator.mediaDevices.getUserMedia({
216
+ audio: constraints,
217
+ });
218
+ }
219
+ catch (e) {
220
+ this.setState("idle");
221
+ const err = mapDomError(e);
222
+ this.opts.onError?.(err);
223
+ throw err;
224
+ }
225
+ // Detect mic disconnect / OS-level revoke.
226
+ for (const track of this.stream.getAudioTracks()) {
227
+ track.addEventListener("ended", () => {
228
+ if (this.state === "recording" || this.state === "paused") {
229
+ this.opts.onDeviceLost?.();
230
+ this.opts.onError?.(new RecorderError("DeviceLost", "Microphone was disconnected."));
231
+ this.cancel();
232
+ }
233
+ });
234
+ }
235
+ this.mime = pickMimeType(this.opts.mimeType);
236
+ let rec;
237
+ try {
238
+ rec = new MediaRecorder(this.stream, {
239
+ mimeType: this.mime,
240
+ audioBitsPerSecond: this.opts.audioBitsPerSecond ?? 32_000,
241
+ });
242
+ }
243
+ catch (e) {
244
+ this.cleanupStream();
245
+ this.setState("idle");
246
+ const err = mapDomError(e);
247
+ this.opts.onError?.(err);
248
+ throw err;
48
249
  }
49
- const mimeType = this.opts.mimeType ?? "audio/webm;codecs=opus";
50
- this.stream = await navigator.mediaDevices.getUserMedia({
51
- audio: this.opts.audioConstraints ?? true,
52
- });
53
- const rec = new MediaRecorder(this.stream, { mimeType });
54
250
  this.chunks = [];
55
251
  rec.ondataavailable = (e) => {
56
- if (e.data && e.data.size > 0)
252
+ if (e.data && e.data.size > 0) {
57
253
  this.chunks.push(e.data);
254
+ this.opts.onChunk?.(e.data);
255
+ }
256
+ };
257
+ rec.onerror = (e) => {
258
+ const err = mapDomError(e?.error || e);
259
+ this.opts.onError?.(err);
58
260
  };
59
261
  this.rec = rec;
262
+ this.startLevelMeter();
263
+ if (this.opts.wakeLock)
264
+ await this.acquireWakeLock();
265
+ if (this.opts.pauseOnHidden)
266
+ this.attachVisibility();
60
267
  return new Promise((resolve, reject) => {
61
268
  rec.onstart = () => {
269
+ this.startedAt = Date.now();
270
+ this.pausedAccumMs = 0;
271
+ this.silenceSinceMs = 0;
62
272
  this.setState("recording");
273
+ if (this.opts.maxDurationMs && this.opts.maxDurationMs > 0) {
274
+ this.maxStopTimer = setTimeout(() => {
275
+ this.stop().catch(() => {
276
+ /* swallow — handled via onError */
277
+ });
278
+ }, this.opts.maxDurationMs);
279
+ }
63
280
  resolve();
64
281
  };
65
- rec.onerror = (e) => reject(e?.error || new Error("recorder error"));
66
- rec.start();
282
+ const onceErr = (e) => {
283
+ const err = mapDomError(e?.error || e);
284
+ this.opts.onError?.(err);
285
+ reject(err);
286
+ };
287
+ rec.addEventListener("error", onceErr, { once: true });
288
+ try {
289
+ if (this.opts.timesliceMs && this.opts.timesliceMs > 0) {
290
+ rec.start(this.opts.timesliceMs);
291
+ }
292
+ else {
293
+ rec.start();
294
+ }
295
+ }
296
+ catch (e) {
297
+ const err = mapDomError(e);
298
+ this.opts.onError?.(err);
299
+ reject(err);
300
+ }
67
301
  });
68
302
  }
303
+ /** Pause recording. Resumable via `resume()`. */
304
+ pause() {
305
+ if (this.state !== "recording" || !this.rec) {
306
+ throw new RecorderError("InvalidState", `Cannot pause while "${this.state}".`);
307
+ }
308
+ this.rec.pause();
309
+ this.pauseStartedAt = Date.now();
310
+ this.setState("paused");
311
+ }
312
+ /** Resume after `pause()`. */
313
+ resume() {
314
+ if (this.state !== "paused" || !this.rec) {
315
+ throw new RecorderError("InvalidState", `Cannot resume while "${this.state}".`);
316
+ }
317
+ this.pausedAccumMs += Date.now() - this.pauseStartedAt;
318
+ this.rec.resume();
319
+ this.setState("recording");
320
+ }
69
321
  /**
70
- * Stop recording and resolve with the assembled Blob. The caller can
71
- * pass this Blob directly to `ohm.audio.extract({ file: blob, ... })`.
72
- * Stops all media tracks so the browser's mic indicator clears.
322
+ * Stop recording and return the assembled Blob, ready to pass to
323
+ * `ohm.audio.extract({ file: blob, })`. Releases mic, wake lock, AudioContext.
73
324
  */
74
325
  async stop() {
75
- if (!this.rec || this.state !== "recording") {
76
- throw new Error("Recorder is not recording");
326
+ if (!this.rec || (this.state !== "recording" && this.state !== "paused")) {
327
+ throw new RecorderError("InvalidState", `Cannot stop while "${this.state}".`);
77
328
  }
78
329
  this.setState("stopping");
79
330
  return new Promise((resolve, reject) => {
80
331
  const rec = this.rec;
81
- rec.onstop = () => {
82
- const blob = new Blob(this.chunks, {
83
- type: rec.mimeType || "audio/webm",
84
- });
332
+ const durationMs = this.getDuration();
333
+ rec.onstop = async () => {
334
+ const type = rec.mimeType || this.mime || "audio/webm";
335
+ const raw = new Blob(this.chunks, { type });
85
336
  this.cleanup();
337
+ // Patch malformed EBML duration so <audio> seeking works and
338
+ // pipelines that read the header don't reject the file. No-op
339
+ // for non-WebM blobs and for failures.
340
+ const blob = await patchWebmDuration(raw, durationMs);
86
341
  resolve(blob);
87
342
  };
88
- rec.onerror = (e) => {
343
+ rec.addEventListener("error", (e) => {
89
344
  this.cleanup();
90
- reject(e?.error || new Error("recorder error"));
91
- };
92
- rec.stop();
345
+ const err = mapDomError(e?.error || e);
346
+ this.opts.onError?.(err);
347
+ reject(err);
348
+ }, { once: true });
349
+ try {
350
+ rec.stop();
351
+ }
352
+ catch (e) {
353
+ this.cleanup();
354
+ const err = mapDomError(e);
355
+ this.opts.onError?.(err);
356
+ reject(err);
357
+ }
93
358
  });
94
359
  }
95
- /** Abort the recording without surfacing the captured audio. */
360
+ /** Stop after `ms` from now. Returns the same promise as `stop()`. */
361
+ stopAfter(ms) {
362
+ return new Promise((resolve, reject) => {
363
+ setTimeout(() => {
364
+ this.stop().then(resolve, reject);
365
+ }, ms);
366
+ });
367
+ }
368
+ /** Abort — releases everything, no Blob. */
96
369
  cancel() {
97
- if (this.rec && this.state === "recording") {
370
+ if (this.rec && (this.state === "recording" || this.state === "paused")) {
98
371
  try {
99
372
  this.rec.stop();
100
373
  }
@@ -104,11 +377,140 @@ export class Recorder {
104
377
  }
105
378
  this.cleanup();
106
379
  }
107
- cleanup() {
108
- this.stream?.getTracks().forEach((t) => t.stop());
380
+ // ─── internals ──────────────────────────────────────────────────────
381
+ startLevelMeter() {
382
+ if (!this.stream || !this.opts.onLevel)
383
+ return;
384
+ if (typeof AudioContext === "undefined")
385
+ return;
386
+ try {
387
+ const Ctx = globalThis.AudioContext ||
388
+ globalThis.webkitAudioContext;
389
+ this.audioCtx = new Ctx();
390
+ this.levelSource = this.audioCtx.createMediaStreamSource(this.stream);
391
+ this.analyser = this.audioCtx.createAnalyser();
392
+ this.analyser.fftSize = 1024;
393
+ this.analyser.smoothingTimeConstant = 0.6;
394
+ this.levelSource.connect(this.analyser);
395
+ this.levelBuffer = new Uint8Array(new ArrayBuffer(this.analyser.fftSize));
396
+ const silenceMs = this.opts.silenceAutoStop?.ms ?? 6000;
397
+ const silenceThr = this.opts.silenceAutoStop?.threshold ?? 0.012;
398
+ const tick = () => {
399
+ if (!this.analyser || !this.levelBuffer)
400
+ return;
401
+ this.analyser.getByteTimeDomainData(this.levelBuffer);
402
+ // RMS in 0..1
403
+ let sum = 0;
404
+ for (let i = 0; i < this.levelBuffer.length; i++) {
405
+ const v = (this.levelBuffer[i] - 128) / 128;
406
+ sum += v * v;
407
+ }
408
+ const rms = Math.sqrt(sum / this.levelBuffer.length);
409
+ this.opts.onLevel?.(rms);
410
+ if (this.opts.silenceAutoStop && this.state === "recording") {
411
+ if (rms < silenceThr) {
412
+ if (this.silenceSinceMs === 0)
413
+ this.silenceSinceMs = Date.now();
414
+ else if (Date.now() - this.silenceSinceMs >= silenceMs) {
415
+ this.silenceSinceMs = 0;
416
+ this.stop().catch(() => { });
417
+ return;
418
+ }
419
+ }
420
+ else {
421
+ this.silenceSinceMs = 0;
422
+ }
423
+ }
424
+ this.levelRafId = requestAnimationFrame(tick);
425
+ };
426
+ this.levelRafId = requestAnimationFrame(tick);
427
+ }
428
+ catch {
429
+ /* metering is best-effort; never block recording */
430
+ }
431
+ }
432
+ async acquireWakeLock() {
433
+ try {
434
+ const wl = navigator.wakeLock;
435
+ if (wl && typeof wl.request === "function") {
436
+ this.wakeLockSentinel = await wl.request("screen");
437
+ }
438
+ }
439
+ catch {
440
+ /* best-effort */
441
+ }
442
+ }
443
+ releaseWakeLock() {
444
+ try {
445
+ this.wakeLockSentinel?.release?.();
446
+ }
447
+ catch {
448
+ /* ignore */
449
+ }
450
+ this.wakeLockSentinel = null;
451
+ }
452
+ attachVisibility() {
453
+ if (typeof document === "undefined")
454
+ return;
455
+ this.visibilityHandler = () => {
456
+ if (document.visibilityState === "hidden" && this.state === "recording") {
457
+ try {
458
+ this.pause();
459
+ }
460
+ catch {
461
+ /* ignore */
462
+ }
463
+ }
464
+ };
465
+ document.addEventListener("visibilitychange", this.visibilityHandler);
466
+ }
467
+ detachVisibility() {
468
+ if (this.visibilityHandler && typeof document !== "undefined") {
469
+ document.removeEventListener("visibilitychange", this.visibilityHandler);
470
+ }
471
+ this.visibilityHandler = null;
472
+ }
473
+ cleanupStream() {
474
+ this.stream?.getTracks().forEach((t) => {
475
+ try {
476
+ t.stop();
477
+ }
478
+ catch {
479
+ /* ignore */
480
+ }
481
+ });
109
482
  this.stream = null;
483
+ }
484
+ cleanup() {
485
+ if (this.maxStopTimer) {
486
+ clearTimeout(this.maxStopTimer);
487
+ this.maxStopTimer = null;
488
+ }
489
+ if (this.levelRafId !== null) {
490
+ cancelAnimationFrame(this.levelRafId);
491
+ this.levelRafId = null;
492
+ }
493
+ try {
494
+ this.levelSource?.disconnect();
495
+ this.analyser?.disconnect();
496
+ this.audioCtx?.close().catch(() => { });
497
+ }
498
+ catch {
499
+ /* ignore */
500
+ }
501
+ this.levelSource = null;
502
+ this.analyser = null;
503
+ this.audioCtx = null;
504
+ this.levelBuffer = null;
505
+ this.releaseWakeLock();
506
+ this.detachVisibility();
507
+ this.cleanupStream();
110
508
  this.rec = null;
111
509
  this.chunks = [];
510
+ this.startedAt = 0;
511
+ this.pausedAccumMs = 0;
512
+ this.pauseStartedAt = 0;
513
+ this.silenceSinceMs = 0;
112
514
  this.setState("idle");
113
515
  }
114
516
  setState(next) {
@@ -1 +1 @@
1
- {"version":3,"file":"recorder.js","sourceRoot":"","sources":["../src/recorder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"recorder.js","sourceRoot":"","sources":["../src/recorder.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ohm_studio/sdk",
3
- "version": "0.2.0",
3
+ "version": "0.5.0",
4
4
  "description": "OHM Studio SDK for JavaScript / TypeScript / React. Voice-to-structured-JSON clinical extraction APIs.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -39,11 +39,16 @@
39
39
  "access": "public"
40
40
  },
41
41
  "scripts": {
42
- "build": "tsc -p tsconfig.json",
43
- "typecheck": "tsc -p tsconfig.json --noEmit"
42
+ "clean": "rm -rf dist",
43
+ "build": "rm -rf dist && tsc -p tsconfig.json",
44
+ "typecheck": "tsc -p tsconfig.json --noEmit",
45
+ "test": "vitest run",
46
+ "test:watch": "vitest"
44
47
  },
45
48
  "dependencies": {
46
- "@ohm_studio/sdk-core": "workspace:*"
49
+ "@ohm_studio/sdk-core": "workspace:*",
50
+ "fix-webm-duration": "^1.0.6",
51
+ "idb-keyval": "^6.2.2"
47
52
  },
48
53
  "peerDependencies": {
49
54
  "react": ">=17"
@@ -52,8 +57,13 @@
52
57
  "react": { "optional": true }
53
58
  },
54
59
  "devDependencies": {
60
+ "@testing-library/react": "^16.3.2",
55
61
  "@types/react": "^18.3.23",
62
+ "fake-indexeddb": "^6.2.5",
63
+ "happy-dom": "^20.9.0",
56
64
  "react": "^18.3.1",
57
- "typescript": "^5.8.3"
65
+ "react-dom": "^18.3.1",
66
+ "typescript": "^5.8.3",
67
+ "vitest": "^4.1.5"
58
68
  }
59
69
  }