Files
FabledScribe/frontend/src/composables/useOnnxPreloader.ts
T
bvandeusen 72018aa389 feat(voice): add ONNX WASM idle preloader for Silero VAD
Configures vite-plugin-static-copy to serve @ricky0123/vad-web's ONNX model,
audio worklet, and onnxruntime-web WASM files from the site root.
useOnnxPreloader warms the model cache during page idle so the first mic
click is instant.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 17:41:17 -04:00

44 lines
1.4 KiB
TypeScript

import { ref, readonly } from 'vue'
/**
* Idle-preload the Silero VAD ONNX model and its companion assets.
*
* `@ricky0123/vad-web` pulls ~2MB of ONNX model + ~5MB of onnxruntime-web
* WASM the first time `MicVAD.new()` runs. Calling `defaultModelFetcher`
* during page idle warms the browser cache so the first mic click feels
* instant. If the preload fails, VAD simply loads lazily on first click.
*/
const ready = ref(false)
let loading = false
export function useOnnxPreloader() {
async function preload() {
if (ready.value || loading) return
loading = true
try {
const { defaultModelFetcher } = await import('@ricky0123/vad-web')
// Asset lives at site root because vite-plugin-static-copy drops it
// there. Match whatever path MicVAD will use at call time (see useVad).
await defaultModelFetcher('/silero_vad_v5.onnx')
ready.value = true
} catch {
// Non-fatal — MicVAD will load the model itself on first use.
} finally {
loading = false
}
}
function schedulePreload() {
if (ready.value) return
if (typeof window === 'undefined') return
if ('requestIdleCallback' in window) {
(window as Window & { requestIdleCallback: (cb: () => void, opts: { timeout: number }) => void })
.requestIdleCallback(() => void preload(), { timeout: 5000 })
} else {
setTimeout(() => void preload(), 5000)
}
}
return { ready: readonly(ready), schedulePreload }
}