screenpipe/screenpipe · error

set sample rate

Error message

set sample rate

What it means

create_mp3_data configures an mp3lame-encoder Builder before building it; set_sample_rate returns Err when the rate is outside LAME's supported range (MP3 supports 8/11.025/12/16/22.05/24/32/44.1/48 kHz) or the builder is otherwise in an invalid state. The code unwraps it with .expect("set sample rate"), so any failure panics the calling thread.

Source

Thrown at crates/screenpipe-audio/src/transcription/openai_compatible/batch.rs:245

    // Downsample if needed
    let samples: Vec<f32> = if target_sample_rate < sample_rate && sample_rate > 0 {
        let ratio = sample_rate / target_sample_rate;
        audio_data
            .iter()
            .enumerate()
            .filter(|(i, _)| i % ratio as usize == 0)
            .map(|(_, &s)| s)
            .collect()
    } else {
        audio_data.to_vec()
    };

    let mut encoder = Builder::new().expect("failed to create mp3lame encoder");
    encoder.set_num_channels(1).expect("set channels");
    encoder
        .set_sample_rate(target_sample_rate)
        .expect("set sample rate");
    encoder
        .set_brate(mp3lame_encoder::Bitrate::Kbps64)
        .expect("set bitrate");
    encoder
        .set_quality(mp3lame_encoder::Quality::Good)
        .expect("set quality");
    let mut encoder = encoder.build().expect("build encoder");

    // Convert f32 samples to i16 for mp3lame
    let pcm_i16: Vec<i16> = samples
        .iter()
        .map(|&s| {
            let clamped = s.clamp(-1.0, 1.0);
            (clamped * i16::MAX as f32) as i16
        })
        .collect();

    let input = MonoPcm(&pcm_i16);

View on GitHub (pinned to 4ebf712990)

Solutions

  1. map the incoming rate to the nearest LAME-supported value instead of only handling >=44100 (e.g. round 22050->24000 or use a whitelist)
  2. validate sample_rate > 0 and within LAME's supported set before constructing the Builder
  3. replace .expect with graceful error propagation (Result) so transcription degrades instead of panicking

Example fix

// before
let target_sample_rate = if sample_rate >= 44100 { 16000 } else { sample_rate };
// after
const LAME_RATES: [u32; 9] = [8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000];
let target_sample_rate = if sample_rate >= 44100 { 16000 } else {
    *LAME_RATES.iter().min_by_key(|&&r| r.abs_diff(sample_rate)).unwrap_or(&16000)
};
Defensive patterns

Strategy: validation

Validate before calling

const LAME_RATES: [u32; 9] = [8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000];
fn is_lame_supported(rate: u32) -> bool { rate > 0 && LAME_RATES.contains(&rate) }
if !is_lame_supported(sample_rate) { /* resample to nearest supported rate before calling */ }

Type guard

fn lame_supported(rate: u32) -> Option<u32> {
    const LAME_RATES: [u32; 9] = [8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000];
    LAME_RATES.iter().copied().min_by_key(|&r| r.abs_diff(rate))
}

Try / catch

match encoder.set_sample_rate(target) {
    Ok(b) => b,
    Err(e) => { error!("sample rate {} rejected by LAME: {:?}", target, e); return Err(anyhow!("unsupported sample rate")); }
}

Prevention

When it happens

Trigger: audio input at a sample rate that is not an MPEG-1/2-supported frequency reaches create_mp3_data — e.g. a device producing 44101 Hz, or a corrupted rate of 0 — because the code only downsamples to 16 kHz when rate >= 44100 and passes anything else through verbatim.

Common situations: unusual audio hardware or virtual audio devices reporting non-standard rates; tests generating synthetic PCM at arbitrary rates; changes to the downsampling branch that let odd rates through.

Related errors


AI-assisted analysis of screenpipe/screenpipe@4ebf712990 (2026-09-01). Data as JSON: /api/errors/17df6bcb3be48316. Report an issue: GitHub.