{"record":{"id":"17df6bcb3be48316","repo":"screenpipe/screenpipe","slug":"set-sample-rate-17df6b","errorCode":null,"errorMessage":"set sample rate","messagePattern":"set sample rate","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/screenpipe-audio/src/transcription/openai_compatible/batch.rs","lineNumber":245,"sourceCode":"\n    // Downsample if needed\n    let samples: Vec<f32> = if target_sample_rate < sample_rate && sample_rate > 0 {\n        let ratio = sample_rate / target_sample_rate;\n        audio_data\n            .iter()\n            .enumerate()\n            .filter(|(i, _)| i % ratio as usize == 0)\n            .map(|(_, &s)| s)\n            .collect()\n    } else {\n        audio_data.to_vec()\n    };\n\n    let mut encoder = Builder::new().expect(\"failed to create mp3lame encoder\");\n    encoder.set_num_channels(1).expect(\"set channels\");\n    encoder\n        .set_sample_rate(target_sample_rate)\n        .expect(\"set sample rate\");\n    encoder\n        .set_brate(mp3lame_encoder::Bitrate::Kbps64)\n        .expect(\"set bitrate\");\n    encoder\n        .set_quality(mp3lame_encoder::Quality::Good)\n        .expect(\"set quality\");\n    let mut encoder = encoder.build().expect(\"build encoder\");\n\n    // Convert f32 samples to i16 for mp3lame\n    let pcm_i16: Vec<i16> = samples\n        .iter()\n        .map(|&s| {\n            let clamped = s.clamp(-1.0, 1.0);\n            (clamped * i16::MAX as f32) as i16\n        })\n        .collect();\n\n    let input = MonoPcm(&pcm_i16);","sourceCodeStart":227,"sourceCodeEnd":263,"githubUrl":"https://github.com/screenpipe/screenpipe/blob/4ebf712990fee17eeaf904dacf749b6e96ac9bf3/crates/screenpipe-audio/src/transcription/openai_compatible/batch.rs#L227-L263","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["map the incoming rate to the nearest LAME-supported value instead of only handling >=44100 (e.g. round 22050->24000 or use a whitelist)","validate sample_rate > 0 and within LAME's supported set before constructing the Builder","replace .expect with graceful error propagation (Result) so transcription degrades instead of panicking"],"exampleFix":"// before\nlet target_sample_rate = if sample_rate >= 44100 { 16000 } else { sample_rate };\n// after\nconst LAME_RATES: [u32; 9] = [8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000];\nlet target_sample_rate = if sample_rate >= 44100 { 16000 } else {\n    *LAME_RATES.iter().min_by_key(|&&r| r.abs_diff(sample_rate)).unwrap_or(&16000)\n};","handlingStrategy":"validation","validationCode":"const LAME_RATES: [u32; 9] = [8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000];\nfn is_lame_supported(rate: u32) -> bool { rate > 0 && LAME_RATES.contains(&rate) }\nif !is_lame_supported(sample_rate) { /* resample to nearest supported rate before calling */ }","typeGuard":"fn lame_supported(rate: u32) -> Option<u32> {\n    const LAME_RATES: [u32; 9] = [8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000];\n    LAME_RATES.iter().copied().min_by_key(|&r| r.abs_diff(rate))\n}","tryCatchPattern":"match encoder.set_sample_rate(target) {\n    Ok(b) => b,\n    Err(e) => { error!(\"sample rate {} rejected by LAME: {:?}\", target, e); return Err(anyhow!(\"unsupported sample rate\")); }\n}","preventionTips":["only feed LAME sample rates from its supported list; resample anything else first","treat all mp3lame Builder setters as fallible — never .expect them in production paths","add a unit test that rounds sample rates from real devices through create_mp3_data"],"tags":["audio","mp3","panic","sample-rate"],"backgroundTag":"mp3-encoder-invalid-configuration","analyzedSha":"4ebf712990fee17eeaf904dacf749b6e96ac9bf3","analyzedAt":"2026-09-01T23:33:43.065Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}