Stable beats fast: the Apple-GPU crash that taught CastPolish to use the CPU
I hit "go" on a two-and-a-half-hour transcription, walked away, and came back to find the entire app gone. Not an error message. Not a failed job sitting in the queue. Gone — the server process had vanished, and the browser tab was frozen on a status bar that hadn't moved in nearly an hour.
Here's what happened, why it happened, and the small fix that turned a crash into a clean run — with a chart of exactly where the time went.
The job
CastPolish is my free, local alternative to Auphonic — it normalizes loudness, transcribes with Whisper, labels speakers, and writes shownotes and documents, all on your own Mac with no cloud. The file was a 2 hour 28 minute interview, "The Future of the Lutheran Church." I asked for the works: Whisper large-v3-turbo transcription, speaker diarization, and enhanced PDF/Word documents.
About 34 minutes in, during the speaker-diarization step, it died.
The crash
The log told the story, if you know how to read Apple's GPU stack:
Unable to reach MTLCompilerService ... error 32 - Broken pipe
MPSKernelDAG.mm:1290: failed assertion `Error getting visible function...'Speaker diarization (via pyannote.audio) was running on Apple's GPU through Metal Performance Shaders (MPS). MTLCompilerService is the macOS daemon that compiles GPU shaders on demand — and over a long run, with sustained memory pressure and a constant stream of kernel compilations, the connection to that daemon dropped. "Broken pipe."
The cruel part is the second line. When the connection died, Metal hit a hard C++ assertion — and a failed assertion calls abort(), which terminates the whole process with SIGABRT. There is no Python exception to catch. No amount of try/except around the diarization call could have saved it. The process was simply executed at the operating-system level, mid-thought.
That's why the UI froze instead of showing an error: the backend it was polling had ceased to exist.
The fix
The honest fix wasn't to make MPS more resilient — you can't, when the failure is an uncatchable abort from inside Apple's framework. The fix was to keep diarization off the GPU entirely.
CastPolish v1.7.1 adds a diarize_device setting (cpu / mps / cuda / auto) that defaults to CPU. The CPU path never touches Metal, never asks MTLCompilerService for anything, and so it cannot hit this class of crash. If you do opt into the GPU and it throws a catchable error, it now retries on CPU automatically.
Transcription still runs on MPS, where it's fast and stable. Only diarization — the step that was actually crashing — moved to the CPU.
The re-run, and where the time went
The second attempt ran start to finish: 2,147 transcript segments, 24 chapters, and the PDF and Word documents I'd been missing. Total processing time was 2 hours 20 minutes. Here's the breakdown by operation:

Three things jump out:
- Speaker diarization on CPU took 71% of the entire run — about 99 minutes. That single step is the whole price of stability. On the GPU it would have been far faster… when it didn't crash.
- Transcription was cheap by comparison — 34 minutes for a 2.5-hour file, because it still runs on the GPU.
- The "enhanced documents" grammar polish was only ~6 minutes — it runs one local-LLM pass per paragraph (466 of them), so it feels heavy, but on a long file it's a rounding error next to diarization. Still, it's a checkbox you can turn off for a faster run.
The lesson
We reach for the GPU by reflex — it's supposed to be the fast path. But "fast when it works" loses to "slow but always finishes," especially for an unattended batch job you've walked away from. A 20-minute speedup isn't worth a crash that costs you two hours and produces nothing.
I also kept a small retest harness in the repo: a standalone script that runs diarization on MPS against a long file. When a future macOS or PyTorch update fixes the underlying instability, I can run it, confirm MPS finishes cleanly, and flip the faster path back on — without guessing.
CastPolish v1.7.1 is on GitHub, free and open source. If you're running long files through it on Apple Silicon, you already have the stable default.
Comments ()