{"record":{"id":"ee67a33f05d057c7","repo":"mudler/LocalAI","slug":"web-audio-api-not-available","errorCode":null,"errorMessage":"Web Audio API not available","messagePattern":"Web Audio API not available","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"core/http/react-ui/src/hooks/useAudioPeaks.js","lineNumber":40,"sourceCode":"  const [duration, setDuration] = useState(0)\n  const [error, setError] = useState(null)\n  const [loading, setLoading] = useState(false)\n\n  useEffect(() => {\n    setPeaks(null)\n    setDuration(0)\n    setError(null)\n    setLoading(false)\n    if (!src) return\n    let cancelled = false\n    setLoading(true)\n\n    async function decode() {\n      try {\n        const response = await fetch(src)\n        const buf = await response.arrayBuffer()\n        const ctx = getSharedAudioContext()\n        if (!ctx) throw new Error('Web Audio API not available')\n        const audioBuf = await ctx.decodeAudioData(buf.slice(0))\n        if (cancelled) return\n        const data = audioBuf.getChannelData(0)\n        const step = Math.max(1, Math.floor(data.length / buckets))\n        const result = new Float32Array(buckets)\n        for (let i = 0; i < buckets; i++) {\n          let peak = 0\n          const start = i * step\n          const end = Math.min(start + step, data.length)\n          for (let j = start; j < end; j++) {\n            const v = Math.abs(data[j])\n            if (v > peak) peak = v\n          }\n          result[i] = peak\n        }\n        setPeaks(result)\n        setDuration(audioBuf.duration)\n        setLoading(false)","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/mudler/LocalAI/blob/44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26/core/http/react-ui/src/hooks/useAudioPeaks.js#L22-L58","documentation":"This error is printed by the cgo bridge in LocalAI's whisper backend when whisper_vad_detect_speech() (whisper.cpp Silero VAD) returns false for the submitted PCM buffer. whisper.cpp returns false from this call when the audio cannot be processed for speech detection — most commonly because the buffer is shorter than the minimum the VAD model accepts, because the global vctx was never initialized (load_model_vad not called or previously failed), or because the compute pass itself errored. It is a C-level integer return code surfaced through cgo, not a Go error value.","triggerScenarios":"Calling vad() with pcmf32_len below the Silero VAD minimum window (whisper.cpp rejects audio shorter than the model's minimum sample count, on the order of a few hundred ms at 16 kHz); calling vad() before a successful load_model_vad(), leaving the static vctx null (whisper.cpp then fails immediately); passing audio resampled to a rate other than 16 kHz mono float32; a ggml backend compute failure (e.g. incompatible GPU backend, out-of-memory) during the VAD forward pass; loading a regular transcription GGUF instead of a Silero-VAD GGUF would fail earlier at whisper_vad_init_from_file_with_params, but a truncated/corrupt VAD model can still init and then fail here.","commonSituations":"Users enabling LocalAI's VAD-based audio chunking and feeding very short clips (e.g. streaming chunks of 100–300 ms); forgetting to configure the VAD model path so the transcriber model is loaded but vctx is null; audio arriving stereo or 8 kHz because the upstream resampling step was skipped; whisper.cpp version drift between the vendored ggml/whisper sources and the prebuilt gowhisper library; GPU/CUDA or Metal backend failures on constrained hardware.","solutions":["Check the audio length before calling vad(): whisper.cpp's Silero VAD requires a minimum buffer (>= 512 samples ≈ 32 ms per frame, and practically >= ~1 s for meaningful detection); buffer or concatenate short streaming chunks until you have at least ~0.5–1 s of 16 kHz mono PCM.","Verify that load_model_vad() was called and returned 0 before vad(); inspect stderr for 'error: Failed to init model as VAD' — if present, the model path points at a non-VAD GGUF and must point at a Silero VAD model (e.g. silence-pc or silero VAD gguf).","Confirm the PCM input is 16 kHz, mono, float32 normalized [-1,1]; re-run the pipeline with a known-good WAV file to isolate resampling bugs.","Check the [ERROR]-prefixed ggml log lines (installed via whisper_log_set in the same file) immediately above this message — they name the underlying compute failure (backend load failure, OOM, unsupported tensor op); rebuild/re-run with CPU-only backends if a GPU backend is implicated.","If whisper.cpp was recently updated, rebuild the gowhisper C++ shim against the matching headers so the whisper_vad_* ABI agrees with the vendored library."],"exampleFix":"// Go caller: buffer short chunks before calling VAD\n// before\nsegs, err := gw.VAD(chunk) // chunk may be 200 ms -> \"error: failed to detect speech\"\n\n// after\nconst minVADSamples = 16000 // 1 s @ 16 kHz\nbuf = append(buf, chunk...)\nif len(buf) < minVADSamples {\n    continue // keep accumulating audio\n}\nsegs, err := gw.VAD(buf)\nif err != nil {\n    log.Printf(\"vad failed (len=%d samples): %v\", len(buf), err)\n    return err\n}","handlingStrategy":"validation","validationCode":"// Run before calling vad(): minimum length, sample-rate, and init checks\nconst whisperSampleRate = 16000\nconst minVADSeconds = 1.0\n\nfunc canRunVAD(sampleCount int, vadModelLoaded bool) error {\n    if !vadModelLoaded { // load_model_vad() must have returned 0\n        return errors.New(\"VAD model not loaded\")\n    }\n    if sampleCount < int(minVADSeconds*whisperSampleRate) {\n        return fmt.Errorf(\"audio too short for VAD: %d samples (< %d)\",\n            sampleCount, int(minVADSeconds*whisperSampleRate))\n    }\n    return nil\n}","typeGuard":"// Go: shape check on the PCM slice handed to cgo\nfunc isVADReadyPCM(pcm []float32) bool {\n    return len(pcm) >= 16000 && // >= 1 s of 16 kHz mono\n        !hasNaN(pcm)\n}\n\nfunc hasNaN(pcm []float32) bool {\n    for _, s := range pcm {\n        if math.IsNaN(s) || math.Abs(s) > 1e3 { // not normalized float PCM\n            return true\n        }\n    }\n    return false\n}","tryCatchPattern":"// cgo has no exceptions: treat the integer return as the error\nrc := C.vad((*C.float)(&pcm[0]), C.size_t(len(pcm)), &out, &outLen)\nif rc == 1 {\n    // do NOT retry the same buffer; log length and model state, then\n    // drop or grow the buffer before the next attempt\n    log.Printf(\"vad failed: len=%d samples, vctxOK=%v\", len(pcm), vctxOK)\n}","preventionTips":["Buffer streaming audio to >= 1 s of 16 kHz mono float32 PCM before invoking VAD","Verify load_model_vad() returned 0 (a real Silero-VAD GGUF) before the first vad() call","Resample all input to 16 kHz mono and normalize to [-1,1] before the cgo boundary","Log the ggml [ERROR] lines (already routed to stderr by ggml_log_cb) alongside the failure for root-cause triage","Pin the whisper.cpp version and rebuild the gowhisper shim whenever the vendored dependency changes"],"tags":["whisper-cpp","vad","audio","cgo","localai","speech"],"backgroundTag":null,"analyzedSha":"44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26","analyzedAt":"2026-08-15T10:13:50.291Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}