# Voice health and audio problems - `core/voice.py::_voice_health(p, analyze=False)` returns the metadata checks (`ok`, `warnings`, `duration`, `word_count`, `words_per_sec`, `loudness`) plus `problems`. - `core/audio.py::audio_problems` decodes with pydub in 50 ms chunks (first 120 s only) and returns `[{kind: silence|clipping|level_jump, start_s, end_s, detail}]`. Thresholds are `PROBLEM_*` constants. No new dependencies. - Cost model: decoding is the expensive part, so the voice list never analyses (`analyze=False` returns `meta["audio_problems"]`, empty if absent). Fresh analysis runs for `GET /api/voices/{id}/health` and the routing test, cached in-process by (path, mtime). Imports store the result in meta in `routes/sources.py::_prepare_imported_voice`; failures there never block the import. - UI: `fmtAudioProblems` (static/js/utils.js) renders text for the routing result and the Try-out voice panel (`#preview-match-problems`, `role=status`). - Limits: heuristics (RMS/peak per chunk); legacy voices show problems only after the health endpoint is called.