{"record":{"id":"1c26f8c751e0843a","repo":"Mintplex-Labs/anything-llm","slug":"audio-file-sample-rate-is-too-low-for-accurate-tra","errorCode":null,"errorMessage":"Audio file sample rate is too low for accurate transcription. Minimum required is 4kHz.","messagePattern":"Audio file sample rate is too low for accurate transcription\\. Minimum required is 4kHz\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"collector/utils/WhisperProviders/localWhisper.js","lineNumber":40,"sourceCode":"    if (!fs.existsSync(this.cacheDir))\n      fs.mkdirSync(this.cacheDir, { recursive: true });\n\n    this.#log(\"Initialized.\");\n  }\n\n  #log(text, ...args) {\n    console.log(`\\x1b[32m[LocalWhisper]\\x1b[0m ${text}`, ...args);\n  }\n\n  #validateAudioFile(wavFile) {\n    const sampleRate = wavFile.fmt.sampleRate;\n    const duration = wavFile.data.samples / sampleRate;\n\n    // Most speech recognition systems expect minimum 8kHz\n    // But we'll set it lower to be safe\n    if (sampleRate < 4000) {\n      // 4kHz minimum\n      throw new Error(\n        \"Audio file sample rate is too low for accurate transcription. Minimum required is 4kHz.\"\n      );\n    }\n\n    // Typical audio file duration limits\n    const MAX_DURATION_SECONDS = 4 * 60 * 60; // 4 hours\n    if (duration > MAX_DURATION_SECONDS) {\n      throw new Error(\"Audio file duration exceeds maximum limit of 4 hours.\");\n    }\n\n    // Check final sample count after upsampling to prevent memory issues\n    const targetSampleRate = 16000;\n    const upsampledSamples = duration * targetSampleRate;\n    const MAX_SAMPLES = 230_400_000; // ~4 hours at 16kHz\n\n    if (upsampledSamples > MAX_SAMPLES) {\n      throw new Error(\"Audio file exceeds maximum allowed length.\");\n    }","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/526360e320da9d1b36074be5ed64fe76e5bbfbbd/collector/utils/WhisperProviders/localWhisper.js#L22-L58","documentation":"LocalWhisper.#validateAudioFile rejects WAVs whose fmt.sampleRate is below 4000 Hz. Whisper typically needs >=8 kHz; 4 kHz is a conservative floor. Since ffmpeg converts to 16 kHz beforehand, hitting this means conversion produced unexpected output or a pre-existing WAV bypassed conversion.","triggerScenarios":"A WAV reaching #validateAudioFile with fmt.sampleRate < 4000 — a hand-crafted file, a conversion that mis-parsed the header, or wavFile.fmt mis-read.","commonSituations":"Feeding a low-rate WAV directly; ffmpeg produced a malformed header; telephony audio downsampled below 4 kHz.","solutions":["Ensure all audio flows through convertAudioToWav (which forces 16 kHz) before validation.","Re-encode the source to at least 16 kHz before passing to LocalWhisper.","Inspect wavFile.fmt.sampleRate to confirm the header parsed correctly."],"exampleFix":"// before\nif (sampleRate < 4000) throw new Error(\"Audio file sample rate is too low...\");\n\n// after — include the actual rate for debugging\nif (sampleRate < 4000)\n  throw new Error(`Sample rate ${sampleRate} Hz is below the 4 kHz minimum.`);","handlingStrategy":"validation","validationCode":"function sampleRateOk(wavFile) {\n  return (wavFile?.fmt?.sampleRate ?? 0) >= 4000;\n}","typeGuard":"function isValidWav(wav) {\n  return !!wav && typeof wav === \"object\"\n    && wav.fmt && typeof wav.fmt.sampleRate === \"number\"\n    && wav.data && typeof wav.data.samples === \"number\";\n}","tryCatchPattern":"try { this.#validateAudioFile(wavFile); }\ncatch (e) {\n  if (e.message.includes(\"sample rate is too low\")) { /* re-encode source to 16 kHz */ }\n  throw e;\n}","preventionTips":["Always pre-convert audio to 16 kHz with ffmpeg.","Reject obvious non-audio inputs upstream.","Log wavFile.fmt before validation during development."],"tags":["audio","whisper","validation","sample-rate"],"backgroundTag":null,"analyzedSha":"526360e320da9d1b36074be5ed64fe76e5bbfbbd","analyzedAt":"2026-08-13T01:45:47.170Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}