@unctad-ai/voice-agent-core 0.1.1

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 (57) hide show
  1. package/dist/config/defaults.d.ts +128 -0
  2. package/dist/config/defaults.d.ts.map +1 -0
  3. package/dist/config/defaults.js +169 -0
  4. package/dist/config/defaults.js.map +1 -0
  5. package/dist/contexts/SiteConfigContext.d.ts +7 -0
  6. package/dist/contexts/SiteConfigContext.d.ts.map +1 -0
  7. package/dist/contexts/SiteConfigContext.js +14 -0
  8. package/dist/contexts/SiteConfigContext.js.map +1 -0
  9. package/dist/hooks/useAudioPlayback.d.ts +18 -0
  10. package/dist/hooks/useAudioPlayback.d.ts.map +1 -0
  11. package/dist/hooks/useAudioPlayback.js +482 -0
  12. package/dist/hooks/useAudioPlayback.js.map +1 -0
  13. package/dist/hooks/useTenVAD.d.ts +42 -0
  14. package/dist/hooks/useTenVAD.d.ts.map +1 -0
  15. package/dist/hooks/useTenVAD.js +318 -0
  16. package/dist/hooks/useTenVAD.js.map +1 -0
  17. package/dist/hooks/useVoiceAgent.d.ts +50 -0
  18. package/dist/hooks/useVoiceAgent.d.ts.map +1 -0
  19. package/dist/hooks/useVoiceAgent.js +1005 -0
  20. package/dist/hooks/useVoiceAgent.js.map +1 -0
  21. package/dist/index.d.ts +14 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +10 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/services/voiceApi.d.ts +22 -0
  26. package/dist/services/voiceApi.d.ts.map +1 -0
  27. package/dist/services/voiceApi.js +93 -0
  28. package/dist/services/voiceApi.js.map +1 -0
  29. package/dist/types/config.d.ts +53 -0
  30. package/dist/types/config.d.ts.map +1 -0
  31. package/dist/types/config.js +2 -0
  32. package/dist/types/config.js.map +1 -0
  33. package/dist/types/errors.d.ts +2 -0
  34. package/dist/types/errors.d.ts.map +1 -0
  35. package/dist/types/errors.js +2 -0
  36. package/dist/types/errors.js.map +1 -0
  37. package/dist/types/index.d.ts +5 -0
  38. package/dist/types/index.d.ts.map +1 -0
  39. package/dist/types/index.js +5 -0
  40. package/dist/types/index.js.map +1 -0
  41. package/dist/types/settings.d.ts +26 -0
  42. package/dist/types/settings.d.ts.map +1 -0
  43. package/dist/types/settings.js +2 -0
  44. package/dist/types/settings.js.map +1 -0
  45. package/dist/types/voice.d.ts +20 -0
  46. package/dist/types/voice.d.ts.map +1 -0
  47. package/dist/types/voice.js +11 -0
  48. package/dist/types/voice.js.map +1 -0
  49. package/dist/utils/audioUtils.d.ts +2 -0
  50. package/dist/utils/audioUtils.d.ts.map +1 -0
  51. package/dist/utils/audioUtils.js +30 -0
  52. package/dist/utils/audioUtils.js.map +1 -0
  53. package/dist/utils/wavParser.d.ts +27 -0
  54. package/dist/utils/wavParser.d.ts.map +1 -0
  55. package/dist/utils/wavParser.js +75 -0
  56. package/dist/utils/wavParser.js.map +1 -0
  57. package/package.json +47 -0
@@ -0,0 +1,482 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react';
2
+ import { parseWavHeader, pcmToFloat32 } from '../utils/wavParser';
3
+ import { WAV_HEADER_SIZE, TTS_STREAM_CHUNK_MS } from '../config/defaults';
4
+ export function useAudioPlayback({ onPlaybackEnd, volumeRef, speedRef, } = {}) {
5
+ const audioCtxRef = useRef(null);
6
+ const sourceRef = useRef(null);
7
+ const streamingSourcesRef = useRef([]);
8
+ const analyserRef = useRef(null);
9
+ const gainRef = useRef(null);
10
+ const [analyserNode, setAnalyserNode] = useState(null);
11
+ const onPlaybackEndRef = useRef(onPlaybackEnd);
12
+ useEffect(() => {
13
+ onPlaybackEndRef.current = onPlaybackEnd;
14
+ }, [onPlaybackEnd]);
15
+ const playPromiseResolveRef = useRef(null);
16
+ /** When true, suppress onPlaybackEnd in onended — explicit stop, not natural end */
17
+ const stoppingRef = useRef(false);
18
+ /** Next scheduled time for streaming chunk scheduling */
19
+ const streamNextTimeRef = useRef(0);
20
+ const getContext = useCallback(() => {
21
+ if (!audioCtxRef.current) {
22
+ try {
23
+ audioCtxRef.current = new AudioContext();
24
+ gainRef.current = audioCtxRef.current.createGain();
25
+ gainRef.current.gain.value = volumeRef?.current ?? 1;
26
+ analyserRef.current = audioCtxRef.current.createAnalyser();
27
+ analyserRef.current.fftSize = 256;
28
+ // Chain: source → gain → analyser → destination
29
+ gainRef.current.connect(analyserRef.current);
30
+ analyserRef.current.connect(audioCtxRef.current.destination);
31
+ setAnalyserNode(analyserRef.current);
32
+ }
33
+ catch (err) {
34
+ console.error('[useAudioPlayback] Failed to create AudioContext:', err);
35
+ return null;
36
+ }
37
+ }
38
+ return audioCtxRef.current;
39
+ }, []);
40
+ /** Call on first user gesture (e.g. FAB click) to eagerly create AudioContext.
41
+ * Mobile Safari requires AudioContext creation inside a user-triggered event. */
42
+ const initContext = useCallback(() => {
43
+ const ctx = getContext();
44
+ if (!ctx)
45
+ console.warn('[useAudioPlayback] initContext: AudioContext unavailable');
46
+ }, [getContext]);
47
+ /** Smoothly ramp gain to new volume (15ms ramp, no clicks) */
48
+ const applyVolume = useCallback((v) => {
49
+ const ctx = audioCtxRef.current;
50
+ const gain = gainRef.current;
51
+ if (ctx && gain) {
52
+ gain.gain.setTargetAtTime(v, ctx.currentTime, 0.015);
53
+ }
54
+ }, []);
55
+ const playAudio = useCallback(async (audioBuffer) => {
56
+ const ctx = getContext();
57
+ if (!ctx)
58
+ throw new Error('AudioContext unavailable — cannot play audio');
59
+ if (ctx.state === 'suspended')
60
+ await ctx.resume();
61
+ // Stop any current playback and resolve pending promise
62
+ try {
63
+ sourceRef.current?.stop();
64
+ }
65
+ catch {
66
+ // ignore
67
+ }
68
+ playPromiseResolveRef.current?.();
69
+ playPromiseResolveRef.current = null;
70
+ const buffer = await ctx.decodeAudioData(audioBuffer.slice(0));
71
+ const source = ctx.createBufferSource();
72
+ source.buffer = buffer;
73
+ if (speedRef)
74
+ source.playbackRate.value = speedRef.current;
75
+ source.connect(gainRef.current);
76
+ sourceRef.current = source;
77
+ return new Promise((resolve) => {
78
+ playPromiseResolveRef.current = resolve;
79
+ source.onended = () => {
80
+ sourceRef.current = null;
81
+ playPromiseResolveRef.current = null;
82
+ if (!stoppingRef.current) {
83
+ onPlaybackEndRef.current?.();
84
+ }
85
+ resolve();
86
+ };
87
+ source.start();
88
+ });
89
+ }, [getContext, speedRef]);
90
+ const stopAudio = useCallback(() => {
91
+ // Suppress onPlaybackEnd during explicit stop — the caller manages state.
92
+ stoppingRef.current = true;
93
+ // Resume context if suspended — prevents stuck state after barge-in.
94
+ // source.stop() works on a suspended context (it marks the source for
95
+ // stopping; the audio thread processes it when resumed), but resuming
96
+ // ensures onended fires promptly for cleanup.
97
+ const ctx = audioCtxRef.current;
98
+ if (ctx?.state === 'suspended') {
99
+ ctx.resume(); // fire-and-forget
100
+ }
101
+ // Stop buffered playback source
102
+ try {
103
+ sourceRef.current?.stop();
104
+ }
105
+ catch {
106
+ // If stop() throws, onended won't fire — resolve the hanging promise
107
+ }
108
+ sourceRef.current = null;
109
+ // Stop all streaming playback sources
110
+ for (const src of streamingSourcesRef.current) {
111
+ try {
112
+ src.stop();
113
+ }
114
+ catch {
115
+ // ignore — may already have ended
116
+ }
117
+ }
118
+ streamingSourcesRef.current = [];
119
+ playPromiseResolveRef.current?.();
120
+ playPromiseResolveRef.current = null;
121
+ stoppingRef.current = false;
122
+ }, []);
123
+ /**
124
+ * Suspend audio playback for two-phase barge-in.
125
+ * Uses AudioContext.suspend() to freeze the entire audio graph in place —
126
+ * all scheduled sources pause mid-playback. Works identically for streaming
127
+ * (CosyVoice, Chatterbox, Resemble) and buffered (Pocket TTS) providers.
128
+ * New chunks from the TTS stream continue to be scheduled on the frozen
129
+ * context and will play seamlessly when resumePlayback() unfreezes it.
130
+ */
131
+ const suspendPlayback = useCallback(() => {
132
+ const ctx = audioCtxRef.current;
133
+ if (ctx && ctx.state === 'running') {
134
+ ctx.suspend(); // fire-and-forget — resolves in ~microseconds on audio thread
135
+ }
136
+ }, []);
137
+ /**
138
+ * Resume audio playback after a false barge-in.
139
+ * Unfreezes the AudioContext — all paused and newly scheduled sources
140
+ * continue playing from exactly where they stopped. Zero content loss.
141
+ */
142
+ const resumePlayback = useCallback(() => {
143
+ const ctx = audioCtxRef.current;
144
+ if (ctx && ctx.state === 'suspended') {
145
+ ctx.resume(); // fire-and-forget
146
+ }
147
+ }, []);
148
+ /**
149
+ * Stream audio chunks for gapless playback as they arrive.
150
+ * Parses the WAV header from the first bytes, then converts PCM chunks
151
+ * into AudioBuffers scheduled for back-to-back playback.
152
+ *
153
+ * During AudioContext.suspend() (barge-in), chunks continue to be parsed
154
+ * and scheduled normally — they simply won't produce audio until the
155
+ * context is resumed. This eliminates all buffering complexity.
156
+ */
157
+ const playStreamingAudio = useCallback(async (chunks, signal) => {
158
+ const ctx = getContext();
159
+ if (!ctx)
160
+ throw new Error('AudioContext unavailable — cannot play streaming audio');
161
+ if (ctx.state === 'suspended')
162
+ await ctx.resume();
163
+ // Stop any current playback
164
+ try {
165
+ sourceRef.current?.stop();
166
+ }
167
+ catch {
168
+ // ignore
169
+ }
170
+ for (const src of streamingSourcesRef.current) {
171
+ try {
172
+ src.stop();
173
+ }
174
+ catch {
175
+ /* ignore */
176
+ }
177
+ }
178
+ streamingSourcesRef.current = [];
179
+ playPromiseResolveRef.current?.();
180
+ playPromiseResolveRef.current = null;
181
+ if (signal?.aborted) {
182
+ throw signal.reason ?? new DOMException('Aborted', 'AbortError');
183
+ }
184
+ // Deferred resolve/reject — the promise settles when the last AudioBufferSourceNode ends
185
+ let resolvePlayback;
186
+ let rejectPlayback;
187
+ const playbackPromise = new Promise((resolve, reject) => {
188
+ resolvePlayback = resolve;
189
+ rejectPlayback = reject;
190
+ });
191
+ playPromiseResolveRef.current = resolvePlayback;
192
+ const onAbort = () => {
193
+ for (const src of streamingSourcesRef.current) {
194
+ try {
195
+ src.stop();
196
+ }
197
+ catch {
198
+ /* ignore */
199
+ }
200
+ }
201
+ streamingSourcesRef.current = [];
202
+ playPromiseResolveRef.current = null;
203
+ rejectPlayback(signal.reason ?? new DOMException('Aborted', 'AbortError'));
204
+ };
205
+ signal?.addEventListener('abort', onAbort, { once: true });
206
+ try {
207
+ let headerBuf = new Uint8Array(0);
208
+ let header = null;
209
+ let pcmCarry = new Uint8Array(0); // leftover PCM bytes between chunks
210
+ let firstChunk = true;
211
+ let bytesPerChunk = 0; // set after header is parsed
212
+ // Sample-exact scheduling: track total samples as integer to avoid
213
+ // floating-point drift from repeated audioBuffer.duration additions.
214
+ // 0.15s (150ms at 24kHz = 3600 samples) is NOT exactly representable
215
+ // in float64; adding it ~47 times for a 7s clip accumulates error
216
+ // that creates micro-gaps/overlaps → audible clicks.
217
+ let scheduleStartTime = 0;
218
+ let totalSamplesScheduled = 0;
219
+ let sampleRate = 0;
220
+ streamNextTimeRef.current = 0;
221
+ for await (const chunk of chunks) {
222
+ if (signal?.aborted)
223
+ break;
224
+ if (!header) {
225
+ // Accumulate bytes until we have the full WAV header
226
+ const merged = new Uint8Array(headerBuf.length + chunk.length);
227
+ merged.set(headerBuf);
228
+ merged.set(chunk, headerBuf.length);
229
+ headerBuf = merged;
230
+ if (headerBuf.length < WAV_HEADER_SIZE)
231
+ continue;
232
+ header = parseWavHeader(headerBuf.slice(0, WAV_HEADER_SIZE));
233
+ sampleRate = header.sampleRate;
234
+ // Compute chunk size from target duration — adapts to any sample rate
235
+ const samplesPerChunk = Math.floor((sampleRate * TTS_STREAM_CHUNK_MS) / 1000);
236
+ bytesPerChunk = samplesPerChunk * header.bytesPerSample;
237
+ // Remaining bytes after header are PCM data
238
+ const remaining = headerBuf.slice(WAV_HEADER_SIZE);
239
+ if (remaining.length > 0) {
240
+ pcmCarry = remaining;
241
+ }
242
+ headerBuf = new Uint8Array(0); // free
243
+ }
244
+ else {
245
+ // Append chunk to PCM carry buffer
246
+ const merged = new Uint8Array(pcmCarry.length + chunk.length);
247
+ merged.set(pcmCarry);
248
+ merged.set(chunk, pcmCarry.length);
249
+ pcmCarry = merged;
250
+ }
251
+ // Schedule AudioBuffers from accumulated PCM.
252
+ // During AudioContext.suspend(), these sources are created and
253
+ // scheduled normally — they just won't produce audio until resumed.
254
+ while (pcmCarry.length >= bytesPerChunk) {
255
+ const pcmSlice = pcmCarry.slice(0, bytesPerChunk);
256
+ pcmCarry = pcmCarry.slice(bytesPerChunk);
257
+ const float32 = pcmToFloat32(pcmSlice, header);
258
+ const audioBuffer = ctx.createBuffer(1, float32.length, sampleRate);
259
+ audioBuffer.copyToChannel(float32, 0);
260
+ const source = ctx.createBufferSource();
261
+ source.buffer = audioBuffer;
262
+ if (speedRef)
263
+ source.playbackRate.value = speedRef.current;
264
+ source.connect(gainRef.current);
265
+ streamingSourcesRef.current.push(source);
266
+ // Clean up each source when it finishes — keeps the array bounded
267
+ // to only currently-playing/scheduled sources during suspension.
268
+ source.onended = () => {
269
+ const idx = streamingSourcesRef.current.indexOf(source);
270
+ if (idx !== -1)
271
+ streamingSourcesRef.current.splice(idx, 1);
272
+ };
273
+ if (firstChunk) {
274
+ // 25ms lookahead: by the time source.start() runs, ctx.currentTime
275
+ // has advanced past the read value. Starting in the past causes the
276
+ // buffer to play immediately, overlapping the next scheduled buffer → click.
277
+ scheduleStartTime = ctx.currentTime + 0.025;
278
+ streamNextTimeRef.current = scheduleStartTime;
279
+ firstChunk = false;
280
+ }
281
+ source.start(streamNextTimeRef.current);
282
+ totalSamplesScheduled += float32.length;
283
+ const effectiveSpeed = speedRef?.current ?? 1;
284
+ streamNextTimeRef.current =
285
+ scheduleStartTime + totalSamplesScheduled / (sampleRate * effectiveSpeed);
286
+ }
287
+ }
288
+ // --- Generator exhausted ---
289
+ // Flush remaining PCM (last partial chunk)
290
+ if (header && pcmCarry.length >= header.bytesPerSample) {
291
+ const alignedLen = Math.floor(pcmCarry.length / header.bytesPerSample) * header.bytesPerSample;
292
+ const pcmSlice = pcmCarry.slice(0, alignedLen);
293
+ const float32 = pcmToFloat32(pcmSlice, header);
294
+ const audioBuffer = ctx.createBuffer(1, float32.length, sampleRate);
295
+ audioBuffer.copyToChannel(float32, 0);
296
+ const source = ctx.createBufferSource();
297
+ source.buffer = audioBuffer;
298
+ if (speedRef)
299
+ source.playbackRate.value = speedRef.current;
300
+ source.connect(gainRef.current);
301
+ streamingSourcesRef.current.push(source);
302
+ source.onended = () => {
303
+ const idx = streamingSourcesRef.current.indexOf(source);
304
+ if (idx !== -1)
305
+ streamingSourcesRef.current.splice(idx, 1);
306
+ };
307
+ if (firstChunk) {
308
+ scheduleStartTime = ctx.currentTime + 0.025;
309
+ streamNextTimeRef.current = scheduleStartTime;
310
+ }
311
+ source.start(streamNextTimeRef.current);
312
+ totalSamplesScheduled += float32.length;
313
+ const effectiveSpeed = speedRef?.current ?? 1;
314
+ streamNextTimeRef.current =
315
+ scheduleStartTime + totalSamplesScheduled / (sampleRate * effectiveSpeed);
316
+ }
317
+ // Wire playback-end detection on the last scheduled source.
318
+ // Each source's onended already handles cleanup (splice from array).
319
+ // The last source additionally fires onPlaybackEndRef and resolves.
320
+ const sources = streamingSourcesRef.current;
321
+ const lastSource = sources.length > 0 ? sources[sources.length - 1] : null;
322
+ if (lastSource) {
323
+ const existingOnEnded = lastSource.onended;
324
+ lastSource.onended = (ev) => {
325
+ // Run the cleanup handler first (splice from array)
326
+ existingOnEnded?.call(lastSource, ev);
327
+ playPromiseResolveRef.current = null;
328
+ signal?.removeEventListener('abort', onAbort);
329
+ if (!stoppingRef.current) {
330
+ onPlaybackEndRef.current?.();
331
+ }
332
+ resolvePlayback();
333
+ };
334
+ }
335
+ else {
336
+ // No audio was produced
337
+ playPromiseResolveRef.current = null;
338
+ signal?.removeEventListener('abort', onAbort);
339
+ if (!stoppingRef.current) {
340
+ onPlaybackEndRef.current?.();
341
+ }
342
+ resolvePlayback();
343
+ }
344
+ }
345
+ catch (err) {
346
+ signal?.removeEventListener('abort', onAbort);
347
+ for (const src of streamingSourcesRef.current) {
348
+ try {
349
+ src.stop();
350
+ }
351
+ catch {
352
+ /* ignore */
353
+ }
354
+ }
355
+ streamingSourcesRef.current = [];
356
+ playPromiseResolveRef.current = null;
357
+ rejectPlayback(err);
358
+ }
359
+ return playbackPromise;
360
+ }, [getContext]);
361
+ /**
362
+ * Play a sequence of audio buffers back-to-back (sentence-level pipelined TTS).
363
+ * All promises are started in parallel but played in order.
364
+ * Only fires onPlaybackEnd after the last buffer finishes.
365
+ */
366
+ const playAudioSequence = useCallback(async (audioPromises, signal) => {
367
+ if (audioPromises.length === 0)
368
+ return;
369
+ const ctx = getContext();
370
+ if (!ctx)
371
+ throw new Error('AudioContext unavailable — cannot play audio sequence');
372
+ if (ctx.state === 'suspended')
373
+ await ctx.resume();
374
+ // Stop any current playback
375
+ try {
376
+ sourceRef.current?.stop();
377
+ }
378
+ catch {
379
+ // ignore
380
+ }
381
+ for (const src of streamingSourcesRef.current) {
382
+ try {
383
+ src.stop();
384
+ }
385
+ catch {
386
+ /* ignore */
387
+ }
388
+ }
389
+ streamingSourcesRef.current = [];
390
+ playPromiseResolveRef.current?.();
391
+ playPromiseResolveRef.current = null;
392
+ for (let i = 0; i < audioPromises.length; i++) {
393
+ if (signal?.aborted)
394
+ throw new DOMException('Aborted', 'AbortError');
395
+ const arrayBuf = await audioPromises[i];
396
+ if (signal?.aborted)
397
+ throw new DOMException('Aborted', 'AbortError');
398
+ const buffer = await ctx.decodeAudioData(arrayBuf.slice(0));
399
+ if (signal?.aborted)
400
+ throw new DOMException('Aborted', 'AbortError');
401
+ const source = ctx.createBufferSource();
402
+ source.buffer = buffer;
403
+ if (speedRef)
404
+ source.playbackRate.value = speedRef.current;
405
+ source.connect(gainRef.current);
406
+ sourceRef.current = source;
407
+ const isLast = i === audioPromises.length - 1;
408
+ await new Promise((resolve, reject) => {
409
+ playPromiseResolveRef.current = resolve;
410
+ const onAbort = () => {
411
+ try {
412
+ source.stop();
413
+ }
414
+ catch {
415
+ /* ignore */
416
+ }
417
+ sourceRef.current = null;
418
+ playPromiseResolveRef.current = null;
419
+ reject(signal.reason ?? new DOMException('Aborted', 'AbortError'));
420
+ };
421
+ signal?.addEventListener('abort', onAbort, { once: true });
422
+ source.onended = () => {
423
+ signal?.removeEventListener('abort', onAbort);
424
+ sourceRef.current = null;
425
+ playPromiseResolveRef.current = null;
426
+ if (isLast && !stoppingRef.current) {
427
+ onPlaybackEndRef.current?.();
428
+ }
429
+ resolve();
430
+ };
431
+ source.start();
432
+ });
433
+ }
434
+ }, [getContext]);
435
+ const getAmplitude = useCallback(() => {
436
+ const analyser = analyserRef.current;
437
+ if (!analyser)
438
+ return 0;
439
+ const data = new Uint8Array(analyser.frequencyBinCount);
440
+ analyser.getByteFrequencyData(data);
441
+ let sum = 0;
442
+ for (let i = 0; i < data.length; i++) {
443
+ sum += data[i];
444
+ }
445
+ return sum / (data.length * 255);
446
+ }, []);
447
+ useEffect(() => {
448
+ return () => {
449
+ try {
450
+ sourceRef.current?.stop();
451
+ }
452
+ catch {
453
+ // ignore
454
+ }
455
+ for (const src of streamingSourcesRef.current) {
456
+ try {
457
+ src.stop();
458
+ }
459
+ catch {
460
+ /* ignore */
461
+ }
462
+ }
463
+ streamingSourcesRef.current = [];
464
+ playPromiseResolveRef.current?.();
465
+ playPromiseResolveRef.current = null;
466
+ audioCtxRef.current?.close();
467
+ };
468
+ }, []);
469
+ return {
470
+ playAudio,
471
+ playAudioSequence,
472
+ playStreamingAudio,
473
+ stopAudio,
474
+ suspendPlayback,
475
+ resumePlayback,
476
+ getAmplitude,
477
+ initContext,
478
+ applyVolume,
479
+ analyser: analyserNode,
480
+ };
481
+ }
482
+ //# sourceMappingURL=useAudioPlayback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAudioPlayback.js","sourceRoot":"","sources":["../../src/hooks/useAudioPlayback.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * useTenVAD — React hook wrapping TEN VAD (WebAssembly) for browser voice
3
+ * activity detection. Drop-in replacement for `useMicVAD` from
4
+ * `@ricky0123/vad-react` with the same callback/state contract.
5
+ *
6
+ * Architecture:
7
+ * AudioContext (16 kHz) → AudioWorkletNode (ten-vad-processor.js)
8
+ * → postMessage Float32 chunks → main-thread WASM inference
9
+ * → speech segmentation state machine → callbacks
10
+ */
11
+ export interface UseTenVADOptions {
12
+ /** Start capturing immediately on mount (default false) */
13
+ startOnLoad?: boolean;
14
+ /** Hop size in samples for each VAD frame at 16 kHz (default 256 = 16 ms) */
15
+ hopSize?: number;
16
+ /** VAD probability threshold [0-1] (default 0.5) */
17
+ threshold?: number;
18
+ /** Probability above which speech is considered to have started */
19
+ positiveSpeechThreshold?: number;
20
+ /** Probability below which speech is considered to have ended */
21
+ negativeSpeechThreshold?: number;
22
+ /** How long (ms) speech must stay below negative threshold before segment ends */
23
+ redemptionMs?: number;
24
+ /** Minimum speech duration (ms) to fire onSpeechEnd; shorter = onVADMisfire */
25
+ minSpeechMs?: number;
26
+ /** Audio to keep before speech onset (ms) */
27
+ preSpeechPadMs?: number;
28
+ onSpeechStart?: () => void;
29
+ onSpeechEnd?: (audio: Float32Array) => void;
30
+ onVADMisfire?: () => void;
31
+ onFrameProcessed?: (probabilities: {
32
+ isSpeech: number;
33
+ rms: number;
34
+ }) => void;
35
+ }
36
+ export declare function useTenVAD(options?: UseTenVADOptions): {
37
+ loading: boolean;
38
+ errored: false | object;
39
+ start: () => Promise<void>;
40
+ pause: () => void;
41
+ };
42
+ //# sourceMappingURL=useTenVAD.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTenVAD.d.ts","sourceRoot":"","sources":["../../src/hooks/useTenVAD.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA2BH,MAAM,WAAW,gBAAgB;IAC/B,2DAA2D;IAC3D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,iEAAiE;IACjE,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,kFAAkF;IAClF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,MAAM,CAAC;IAGxB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAC5C,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,gBAAgB,CAAC,EAAE,CAAC,aAAa,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAC/E;AAsBD,wBAAgB,SAAS,CAAC,OAAO,GAAE,gBAAqB;;;;;EAyWvD"}