Zackriya-Solutions/meetily · warning · anyhow::Error

No speech detected in audio file

Error message

No speech detected in audio file

What it means

VAD scanned the entire decoded file and returned zero speech segments, so retranscription stops before loading any engine. This is a content condition, not a crash: nothing in the audio crossed the VAD speech-probability and energy thresholds (vad.rs rejects audio with RMS < 0.2 or peak < 0.20 as silence).

Source

Thrown at frontend/src-tauri/src/audio/retranscription.rs:296

            "VAD segment stats: avg={:.0}ms, min={:.0}ms, max={:.0}ms, total_speech={:.1}s/{:.1}s ({:.0}%)",
            avg_duration, min_duration, max_duration,
            total_speech_ms / 1000.0, duration_seconds,
            (total_speech_ms / 1000.0 / duration_seconds) * 100.0
        );
        // Log first 10 segments for detailed inspection
        for (i, seg) in speech_segments.iter().take(10).enumerate() {
            let dur = seg.end_timestamp_ms - seg.start_timestamp_ms;
            debug!("  Segment {}: {:.0}ms-{:.0}ms ({:.0}ms, {} samples)",
                i, seg.start_timestamp_ms, seg.end_timestamp_ms, dur, seg.samples.len());
        }
        if total_segments > 10 {
            debug!("  ... and {} more segments", total_segments - 10);
        }
    }

    if total_segments == 0 {
        warn!("No speech detected in audio");
        return Err(anyhow!("No speech detected in audio file"));
    }

    emit_progress(&app, &meeting_id, "transcribing", 25, "Loading transcription engine...");

    // Initialize the appropriate engine once (not per-segment)
    let whisper_engine = if !use_parakeet {
        Some(get_or_init_whisper(&app, model.as_deref()).await?)
    } else {
        None
    };
    let parakeet_engine = if use_parakeet {
        Some(get_or_init_parakeet(&app, model.as_deref()).await?)
    } else {
        None
    };

    // Split very long segments at silence boundaries for better transcription quality.
    // Hard cuts at arbitrary sample positions lose words at boundaries. Instead, scan

View on GitHub (pinned to 0281737d87)

Solutions

  1. Open the source audio file in a player and confirm it actually contains audible speech.
  2. Check the preceding logs: 'Decoded audio: Xs' proves decode worked, and 'VAD detected 0 speech segments' proves the samples were too quiet - so the file, not the code, is the problem.
  3. If speech is present but very quiet, re-export or amplify the audio, then retranscribe again.
  4. Verify the correct microphone/system devices were selected for the original recording and re-record.
Defensive patterns

Strategy: validation

Validate before calling

// Cheap pre-check before starting retranscription: measure input energy
fn audio_has_energy(samples: &[f32]) -> bool {
    if samples.is_empty() { return false; }
    let rms = (samples.iter().map(|x| x * x).sum::<f32>() / samples.len() as f32).sqrt();
    let peak = samples.iter().fold(0.0f32, |a, x| a.max(x.abs()));
    rms >= 0.2 && peak >= 0.20 // mirror vad.rs silence thresholds
}
// if !audio_has_energy(&samples) { return early with a friendly message }

Try / catch

// Frontend: treat this as a content condition, not a crash
try { await invoke('start_retranscription', {...}); }
catch (e) {
  if (String(e).includes('No speech detected')) showInfo('Recording contains no detectable speech');
  else showError(e);
}

Prevention

When it happens

Trigger: Re-transcribing a recording that is silent, music-only, or extremely quiet; audio decoded with near-zero gain or a wrong sample rate so samples never reach speech energy; every candidate segment shorter than the 100ms / 1600-sample minimum.

Common situations: The original meeting captured the wrong input device and recorded silence; system-audio-only capture with no voices; an imported file that is background music; microphone gain set too low.

Related errors


AI-assisted analysis of Zackriya-Solutions/meetily@0281737d87 (2026-08-16). Data as JSON: /api/errors/f9d500bd98c5cfe9. Report an issue: GitHub.