Zackriya-Solutions/meetily · error

Whisper transcription failed on segment {}: {}

Error message

Whisper transcription failed on segment {}: {}

What it means

`WhisperEngine::transcribe_audio_with_confidence(samples, language)` returned Err for segment i; the whisper-rs error is chained after the colon. As with the parakeet branch, `?` aborts the whole import on one failing segment. Distinct from the model-load error in get_or_init_whisper: the model is already loaded here — this is an inference-time failure.

Source

Thrown at frontend/src-tauri/src/audio/import.rs:594

                segment.samples.len()
            );
            continue;
        }

        // Transcribe
        let (text, conf) = if use_parakeet {
            let engine = parakeet_engine.as_ref().unwrap();
            let text = engine
                .transcribe_audio(segment.samples.clone())
                .await
                .map_err(|e| anyhow!("Parakeet transcription failed on segment {}: {}", i, e))?;
            (text, 0.9f32)
        } else {
            let engine = whisper_engine.as_ref().unwrap();
            let (text, conf, _) = engine
                .transcribe_audio_with_confidence(segment.samples.clone(), language.clone())
                .await
                .map_err(|e| anyhow!("Whisper transcription failed on segment {}: {}", i, e))?;
            (text, conf)
        };

        let trimmed = text.trim();
        if !trimmed.is_empty() {
            debug!(
                "Segment {}/{}: {:.1}s, conf={:.2}, text='{}'",
                i + 1, processable_count, segment_duration_sec, conf,
                if trimmed.len() > 80 { let mut end = 80; while !trimmed.is_char_boundary(end) { end -= 1; } &trimmed[..end] } else { trimmed }
            );
            all_transcripts.push((text, segment.start_timestamp_ms, segment.end_timestamp_ms));
            total_confidence += conf;
        } else {
            debug!("Segment {}/{}: {:.1}s — empty transcription", i + 1, processable_count, segment_duration_sec);
        }
    }

    let transcribed_count = all_transcripts.len();

View on GitHub (pinned to 0281737d87)

Solutions

  1. Normalize the language argument to an ISO-639-1 code (map 'english' to 'en') or pass None before invoking the import command
  2. Inspect the inner whisper-rs error text after the colon — it distinguishes invalid-parameter errors from GPU/backend errors
  3. Retry the failed segment once (transient Metal/CUDA faults often pass) before aborting the import
  4. If GPU errors repeat, test with a CPU-feature build to confirm, then fix the GPU runtime

Example fix

// before — any segment failure aborts the import
let (text, conf, _) = engine
    .transcribe_audio_with_confidence(segment.samples.clone(), language.clone())
    .await
    .map_err(|e| anyhow!("Whisper transcription failed on segment {}: {}", i, e))?;

// after — validate language once, then tolerate per-segment failure
let lang = language.as_deref().map(normalize_lang_code); // 'english' -> 'en'
let (text, conf, _) = match engine
    .transcribe_audio_with_confidence(segment.samples.clone(), lang)
    .await
{
    Ok(r) => r,
    Err(e) => {
        warn!("Whisper failed on segment {}, skipping: {}", i, e);
        continue;
    }
};
Defensive patterns

Strategy: retry

Validate before calling

// validate the language argument before invoking import
const WHISPER_LANGS = new Set(['en', 'es', 'fr', 'de', /* ... */]);
const lang = language && WHISPER_LANGS.has(language.toLowerCase()) ? language : null;
await invoke('start_import', { sourcePath, title, language: lang });

Try / catch

Retry once with the same segment (transient GPU faults pass), then skip the segment and continue the loop; abort the import only when consecutive segments fail — surfacing the inner whisper-rs error text is what makes the retry decision possible.

Prevention

When it happens

Trigger: Default whisper path with >0 segments: an invalid `language` string (whisper-rs expects ISO codes like 'en', not 'english'), the model being unloaded/invalidated concurrently while the loop runs, a GPU (Metal/CUDA/Vulkan) context lost after sleep/wake, or corrupt/empty sample slices after VAD splitting.

Common situations: A language selector sending full language names; user changes or unloads the whisper model in settings during a long import; laptop sleep/resume mid-import; edge-case segments near the 1600-sample skip threshold.

Related errors


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