Root cause was Brave-on-Android's Web Audio tampering breaking Gradio's
client-side recorder re-encode (confirmed: Chrome records fine, upload always
worked). No app/model change needed for that. Strip the ASR_DEBUG-gated logging
now that it's diagnosed.
Kept: format="wav" (m4a/mp3 uploads), editable=False (skip the fragile trim
re-encode), soundfile->librosa loader, silence guard, single-language decode,
fast scipy resample, peak-normalization.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ASR: disable post-record audio editor (editable=False) — the real mic fix
fcabla+1: Claude Opus 4.8 (1M context)
b752726
Upload was instant + correct, but recording showed a trim/edit UI that froze for
minutes then uploaded silence. That's Gradio's post-recording editor (editable
defaults to True): it decodes the recording to an editable buffer and re-encodes
it client-side, which hangs and yields silent audio on some browsers (e.g. Brave
/Android). The upload path has no editor, hence instant + correct.
editable=False makes a recording go straight to the server like an upload does.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Upload of a phone voice memo (m4a/aac) raised a libsndfile error: soundfile only
reads wav/flac/ogg. And mic recordings arrived as readable-but-silent wav.
- gr.Audio(format="wav"): gradio converts uploads AND recordings to wav via
ffmpeg server-side before handing us the path.
- transcribe(): if soundfile fails, fall back to librosa.load (ffmpeg backend),
which decodes m4a/mp3/opus/webm. So any input format works.
Confirms ASR on a real recording via the upload path and isolates the mic-record
silence (gradio's browser-side re-encode). [asr-debug] retained.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ASR: single-language decode + silence guard + fast resample
fcabla+1: Claude Opus 4.8 (1M context)
eacc13c
Real-mic logs showed the saved clip was pure silence (peak 0.0, all zeros), on
which the model emitted confident hallucinations ("...next slide..."), and the
librosa resample took ~13s. Fixes:
- Decode ONLY the UI-selected language; drop the en<->es fallback that turned an
empty English pass into a Spanish hallucination (the UI already has a selector).
- Silence guard: clips shorter than 0.5s or with peak < 1e-3 return "" with a
clear log instead of being transcribed into nonsense.
- Peak-normalize to ~0.9 to match the model's expected input level.
- Resample via scipy.signal.resample_poly (fast) with librosa/decimate fallbacks.
Does not by itself fix a mic that captures silence (upstream/browser); it makes
that case honest (empty, logged) rather than hallucinated. [asr-debug] retained.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ASR: fix live-mic garbage — load mic audio as float via filepath, not int16 numpy
fcabla+1: Claude Opus 4.8 (1M context)
2dd2a0e
Root cause (proven by [asr-debug] on a real mic call): gr.Audio(type="numpy")
delivered the recording as int16 already truncated to +/-1 (peak exactly 1,
rms 0.017 vs the demo's 0.117) — a float [-1,1] waveform cast to int16 without
scaling, so speech collapsed to near-silence before transcribe() saw it. The
>1.5 normalize check never fired (max==1.0), the resample (librosa) was fine but
operated on garbage, and the model returned ""/confident hallucination.
Fix: mic uses type="filepath"; transcribe() reads it with soundfile as float32
(always_2d) — the exact path the working 16k self-test uses. Legacy (sr, array)
tuples still accepted. Self-test now passes the filepath too, so it verifies the
new load path on deploy.
[asr-debug] gating retained (ASR_DEBUG=1) for this verification round.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ASR: add gated [asr-debug] instrumentation for the live mic path
fcabla+1: Claude Opus 4.8 (1M context)
54998fe
Self-test (16k mono demo) works but real browser-mic transcripts are confident
nonsense. The mic path uniquely exercises the 48k->16k resample and int16->float
normalize branches the 16k demo skips. Add ASR_DEBUG=1-gated logging of input
sr/dtype/shape/range, pre/post-resample length+rms, processor tensor shapes, and
raw decoded text per language, to capture exactly what reaches the model on a
real mic call. Behavior unchanged when ASR_DEBUG is unset. Temporary; removed
once the root cause is fixed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Root cause of the dead mic: the model is gated and the Space ran unauthenticated,
so from_pretrained 401'd at download and the model never loaded (preload swallowed
it; every mic call returned ""). Fixed by adding the HF_TOKEN Space secret.
Code hardening so it actually transcribes once the gate opens:
- _load() now moves the fp16 model to CUDA inside the @spaces.GPU call (mirrors
game/model.py); without it, fp16 generate on CPU raises and returns "".
- Use the native CohereAsrForConditionalGeneration class (transformers>=5.11)
instead of AutoModelForSpeechSeq2Seq, which is not guaranteed to map cohere_asr.
- Proper librosa resample to 16k (guarded fallback to the old decimation).
- spaces.GPU duration 20->30 for the cold 2B host->device transfer.
- Add librosa + soundfile deps.
- Env-gated _selftest() (ASR_SELFTEST=1) transcribes the model's demo clip so the
deploy logs prove Cohere works without a mic.
No Whisper anywhere; on any failure returns "" and logs the exact error.
…