Repository navigation
feat: run pyannote's speaker-embedding network on the Intel GPU (#135) - #138
Open
raphaelm22 wants to merge 7 commits into
Open
raphaelm22 wants to merge 7 commits into
raphaelm22 wants to merge 7 commits into
Conversation
…cure#131) faster-whisper (CTranslate2) only runs on the CPU or NVIDIA GPUs. A new "Intel GPU (OpenVINO)" compute device runs Whisper through OpenVINO GenAI's WhisperPipeline on Intel's int8 model builds. On a Core Ultra 7 265U, large-v3-turbo transcribed a 7.4 min meeting in ~45 s instead of 7.7 min on the CPU. - openvino_whisper.py (no Qt): model repos, pipeline cache with a compiled-model cache, faster-whisper's Silero VAD (WhisperPipeline has none and hallucinates over silence), 60 s speech batches as the only progress/cancel points, language detected once then pinned. - TranscriptionWorker._run_openvino: any OpenVINO failure, at load or mid-run, falls back to the CPU; unreadable audio still errors. - Settings: new device entry with inline status; openvino-genai is installed on demand, asked before any config write since Config.set() saves immediately. - System Status: Intel GPU row when selected, and the Whisper model check looks for the OpenVINO build. - openvino extra in pyproject (uv.lock: only the four new packages), commented line in requirements.txt, module in the CI import smoke.
…intSecure#133) pyannote's get_embeddings runs the WeSpeaker ResNet once per (chunk, local speaker): three passes over the same 10 s of audio, though only the statistics pooling depends on the speaker. The model already pools (batch, speakers, frames) weights in one pass, so run it once per chunk. Embeddings were 96% of diarization time. On a 5-minute excerpt (Core Ultra 7 265U, CPU): 267 s -> 63-100 s, DER 0.0 against the original in the same process, identical speaker centroids.
…ureAintSecure#135) With the Intel GPU device selected, the WeSpeaker ResNet34 trunk is converted to OpenVINO from the loaded torch model (once, cached by a hash of the weights) and runs on the iGPU. fbank and the per-speaker pooling stay in torch on the CPU. Any failure, at build time or mid-run, finishes on the CPU. 31-minute meeting on a Core Ultra 7 265U: diarization 34 min (CPU, as shipped) -> 2.2 min (4.0 min on first use, including conversion), with every transcript segment given the same speaker as the CPU run.
Author
|
Ready for review (stacked on #132 and #136). Used daily since 15/10 on a Core Ultra 7 265U (Intel GPU selected, live transcription on): 7 real Teams meetings, 11 to 115 min, pt-BR, 4 to 6 speakers. No fallbacks or errors in the log. Speaker names after Stop: 11 min meeting 57 s, 40 min 2.1 min, 50 min 2.5 min, 108 min 7.4 min. Before #136/#138 a 31 min meeting took 39 min. |
raphaelm22
marked this pull request as ready for review
October 22, 2026 13:28
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #135.
Summary
With the Intel GPU device selected, transcription runs on the GPU (#132) but pyannote still ran entirely on the CPU, and was nearly all of the wait after Stop. This moves the expensive part of diarization, the WeSpeaker ResNet34 trunk, to the GPU through OpenVINO.
app/transcription/openvino_embeddings.py(new):get_trunkconverts the trunk from the loaded torch model once. pyannote's weights are gated, so no prebuilt model can ship.~/.talktrack/openvino_cache/wespeaker-trunk-<weights hash>.xml, so a pyannote model update converts again rather than reusing a stale file.GpuTrunk.embedkeeps fbank and the per-speaker statistics pooling in torch on the CPU and runs only the trunk on the GPU.chunk_embeddings.set_accelerator. The per-chunk pass from perf: one speaker-embedding pass per chunk, not per speaker (#133) #136 can hand its network call to an accelerator. If that raises mid-run, the error is kept onaccelerator.errorand the remaining batches run on the CPU model.DiarizationWorkersets the accelerator on every run: the trunk forintel_gpu,Nonefor everything else. Thecpuandintel_gpusettings share the cached(token, "cpu")pipeline, so a stale accelerator would otherwise keep using the GPU after switching back.Measurements (Core Ultra 7 265U)
Full 31-minute meeting through
DiarizationWorker:All 709 transcript segments got the same speaker label as the original CPU run, under the same 8 labels.
5-minute excerpt: 267 s (pyannote as is) → 18.5 s, DER 0.0002 against the original, speaker centroids at cosine ≥ 0.99999. Saved voice profiles (#128) stay comparable.
Trunk alone per batch of 32 chunks:
The NPU is not offered. It was no faster end to end, compiles in 30 s instead of 5, and is the device where large-v3-turbo hung in #132.
Tests
tests/test_openvino_embeddings.py, 17 new tests, with torch and OpenVINO stubbed. They cover:embedequal to the CPU model;GPUwithCACHE_DIR;release_trunks;_intel_gpu_trunkbuilding the trunk, explaining an unavailable GPU, and skipping unsupported models;run()attaching, clearing and evicting the trunk.Without the integration code, 9 fail. Full suite on this branch: 487 passed.
🤖 Generated with Claude Code