Skip to main content

Module audio_dsp

Module audio_dsp 

Source
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)

  1. decode_to_pcm — turn the vendor-issued WAV/MP3/OGG bytes into a normalised mono f32 PCM at a known sample rate.
  2. spectral_subtraction_denoise — estimate the noise floor from the silent head of the file, subtract from every frame.
  3. bandpass_filter — keep 80–3500 Hz; drop sub-bass rumble + above-speech ringing.
  4. [time_stretch_to_natural_rate] — phase-vocoder time-stretch so the dominant pitch sits at typical-human speech cadence.
  5. 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 PcmAudio at TARGET_SAMPLE_RATE.
encode_wav_pcm16
Re-encode a PcmAudio back to a 16-bit-LE WAV byte stream. The STT solver pipes the bytes returned by preprocess_for_stt to 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_ms of 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.