Expand description
Audio captcha pre-processing pipeline.
Audio captchas (reCAPTCHA accessibility audio, hCaptcha audio challenge, Friendly Captcha audio fallback) are deliberately distorted to defeat naive transcription:
- Noise floor injection — pink/brown noise at -20 to -30 dB to confuse VAD-driven STT models.
- Time-stretch — 0.8× to 1.3× playback speed at random.
- Pitch shift — semitone-level pitch perturbation.
- Bandlimit — high-pass at 80 Hz, low-pass at 4 kHz so commercial 16 kHz STT models lose harmonics.
- Echo — 50-150 ms tap with 30-50% feedback.
Sending the raw distorted audio to whisper-cli typically scores
50-65% word accuracy. With pre-processing the same audio rises
to 85-95% on the bench audio fixtures. This module ships the
pre-processing pipeline; the crate::solver::AudioCaptchaSolver
pipes raw audio through it before the STT call.
§Pipeline stages (in order)
decode_to_pcm— turn the vendor-issued WAV/MP3/OGG bytes into a normalised monof32PCM at a known sample rate.spectral_subtraction_denoise— estimate the noise floor from the silent head of the file, subtract from every frame.bandpass_filter— keep 80–3500 Hz; drop sub-bass rumble + above-speech ringing.- [
time_stretch_to_natural_rate] — phase-vocoder time-stretch so the dominant pitch sits at typical-human speech cadence. peak_normalise— gain-stage to -1 dBFS so the STT model sees consistent amplitude across challenges.
§Pure-Rust by design
No FFmpeg, no SoX, no native dependencies. The whole pipeline is
deliberately small + dependency-free so it ships in a container
without apt install. Tradeoff: we don’t get SoX’s polyphase
resampler quality. Acceptable because STT models are robust to
mild aliasing.
Structs§
- PcmAudio
- One PCM buffer at the pipeline’s working sample rate. f32 mono.
Constants§
- TARGET_
SAMPLE_ RATE - Sample rate the pipeline normalises to. 16 kHz matches whisper / most commercial STT — going higher wastes bytes; going lower drops the upper formants STT relies on for vowel discrimination.
Functions§
- bandpass_
filter - 2nd-order Butterworth bandpass filter, applied as cascaded
1st-order high-pass + low-pass biquads. Keeps
low_hz..high_hz, drops everything outside. - decode_
to_ pcm - Decode raw bytes (WAV / MP3 / OGG / FLAC — whatever the vendor
hands us) into
PcmAudioatTARGET_SAMPLE_RATE. - encode_
wav_ pcm16 - Re-encode a
PcmAudioback to a 16-bit-LE WAV byte stream. The STT solver pipes the bytes returned bypreprocess_for_sttto whisper-cli / OpenAI Whisper API / Deepgram via this encoder. - peak_
normalise - Peak-normalise to a target dBFS. -1 dBFS keeps headroom while maximising signal that the STT model sees.
- preprocess_
for_ stt - Run the full pipeline on raw vendor audio bytes. Returns the pre-processed PCM ready to feed to STT.
- resample_
linear - Linear-interpolation resampler. Cheap; good enough for STT preprocessing (the model is robust to mild aliasing).
- spectral_
subtraction_ denoise - Estimate the noise floor from the first
head_msof the audio (assumes the vendor’s challenge starts with brief silence — a safe assumption across reCAPTCHA / hCaptcha / Friendly Captcha). Subtract that floor from every sample. Catches background-noise distortion vendors apply to defeat naive STT. - time_
stretch - Time-stretch by
factor(1.0 = no change, <1 speeds up, >1 slows down). Used to normalise vendor-injected playback-rate distortion before STT.