CastPolish v1.4 — Quality Presets, Vocabulary Hints, and the Bug That Hid Inside a Fix

CastPolish v1.4 — Quality Presets, Vocabulary Hints, and the Bug That Hid Inside a Fix

CastPolish v1.4 is the biggest update since launch. It adds one-click quality presets, a vocabulary hints field that dramatically improves how Whisper handles names and domain terms, and the new large-v3-turbo model — plus a long list of fixes from a full security and correctness review. And it comes with a debugging story I think is worth telling honestly: a bug that hid inside a fix for five days, and what it took to find it.

Quality Presets: pick by stakes, not by settings

The Process screen now has three preset buttons. Instead of asking you to know which Whisper model to pick, they ask the only question that matters: how much does the wording matter?

  • ⚡ Quick draft — a fast general take. Good for reviewing content and finding quotes. Not recommended for publication or when exact wording matters.
  • 🎙️ Production — publication quality for podcasts and general content.
  • 🎯 High accuracy — for material where wording matters: legal, theological, medical, official statements. Slowest, most accurate. It selects the new large-v3-turbo model and the best installed noise reduction automatically.
CastPolish Process Audio screen with the High accuracy preset selected
The 🎯 High accuracy preset: large-v3-turbo, AI noise reduction, and the vocabulary hints field — with an honest disclaimer that automated transcription still needs review when the stakes are high.

One thing I insisted on: the high-accuracy tier says plainly that automated transcription can still make errors. If you're transcribing something legal or medical, review the transcript. A tool should tell you its limits.

Vocabulary Hints: teach Whisper your proper nouns

Whisper is remarkable, but it has never heard of your church body, your guests' names, or your field's jargon. In a recent sermon transcript, the smaller Whisper model rendered "Lutheran Church—Missouri Synod" as "Lutheran Church, Missouri, send it to Lutherans" — and turned every "snooze button" into a "news button."

The new Vocabulary hints field fixes most of this with one line. List the names and terms your speaker uses — Lutheran Church—Missouri Synod, LCMS, catechism, sanctification — and Whisper is strongly biased toward transcribing them correctly. It costs nothing and works with every model size. If you transcribe the same speaker every week, this field plus the High accuracy preset is the single biggest accuracy upgrade available.

The Bug That Hid Inside a Fix

Now the story. Five days ago, CastPolish's "Dynamic" noise reduction mode (the noisereduce library) started hanging on longer files. The diagnosis at the time seemed reasonable: too many FFT samples. The fix: downsample the audio to 22 kHz mono before denoising. The hang went away, and the commit message confidently said the change "preserves full voice quality."

It did not. The published audio — the actual MP3 you'd upload to your podcast host — was being encoded from that downsampled intermediate. Every stereo episode processed with Dynamic noise reduction went out as 22 kHz mono: half the bandwidth, no stereo image, silently.

This week, a code review flagged the quality loss, and I "fixed" it by restoring the original sample rate — at which point a reasonable question got raised: wasn't that downsample deliberate? Didn't it prevent a hang?

It was, and it did. So which is it — quality or hangs? The only way to know was to measure. The benchmark results made no sense at first:

InputTime to denoise
2 min — 22 kHz mono (the "safe" path)1.3 s
2 min — 44.1 kHz stereo (the "hanging" path)1.4 s
15 min — 44.1 kHz stereo3.2 s
10 seconds — 44.1 kHz stereo, original code>60 s, killed

Fifteen minutes of full-quality stereo: 3.2 seconds. Ten seconds of the same audio through the original code: over a minute before I killed it. Sample count was never the problem.

The real bug was one transposed array. The audio library returns sound as (samples, channels) — millions of rows, two columns. The noise reduction library expects (channels, samples) — two rows, millions of columns. Nobody converted between them. So for stereo audio, noisereduce believed it had been handed 441,000 separate audio channels, each two samples long, and dutifully began processing every one of them. That's not slow — that's a different, enormous job. It only ever looked length-related.

And the original fix? Forcing mono produces a one-dimensional array, which has no rows or columns to confuse. The downsample to 22 kHz — the part that cost everyone audio quality — contributed nothing. The fix worked by accident, and the misdiagnosis hid in a commit message that said quality was preserved.

v1.4 transposes the array correctly. You get full-rate, full-stereo Dynamic noise reduction, and the hang is gone for the right reason instead of the wrong one. The transpose now carries a comment in the source code loud enough that nobody will ever "simplify" it away.

If you used Dynamic noise reduction before v1.4

Any episode you processed with the Dynamic (noisereduce) mode before this release went out at 22 kHz mono. If any of those were stereo recordings that matter to you, reprocess them on v1.4 to restore full fidelity. Episodes processed with Standard or AI Enhanced (DeepFilterNet) modes were never affected.

Everything else in v1.4

  • Security hardening — transcript HTML now escapes filenames and data (a crafted filename could previously inject scripts), and the config API rejects cross-origin requests that could have redirected your transcripts to an attacker's server
  • Disk leak fixed — every job used to leave its intermediate audio (up to several GB) in temp storage forever; everything is cleaned up now, success or failure
  • In-app installs work immediately — packages installed from the Dependencies panel no longer require a server restart (and no longer risk silently passing audio through unprocessed)
  • Job queue — uploads now process one at a time instead of all at once, so batch-submitting a season of episodes won't exhaust your RAM
  • Whisper stays loaded — the model is cached between jobs instead of reloading gigabytes from disk every run
  • Plus: timeouts on all audio processing (a corrupt file can no longer hang a job forever), atomic settings saves, correct timestamps in hour-plus caption files, smarter update checks, and an Ollama circuit breaker so a stalled local LLM can't add hours to a job

CastPolish is free and open-source

MIT license  ·  macOS full support  ·  Linux & Windows supported

★  View on GitHub ⬇  Download install.command

macOS: double-click install.command in Finder  ·  Linux/Windows: python3 castpolish.py serve  ·  Updating: just re-run the installer or git pull

Albert Collver

Albert Collver

Albert Collver, Ph.D. — Lutheran theologian, podcaster, and lifelong coder since the '90s shareware era. I build free, open-source tools like CastPolish, liturgical software, and family-history projects. All local, no cloud.
Missouri