TL;DR>
我在同一台 M2 MacBook(8GB)上把 whisper.cpp 和 WhisperX 都裝過、都跑過,結論是這兩個不在同一層,沒有「該選哪個」這種問題。
whisper.cpp 贏在形態:clone、cmake兩行、下載一個.bin,我從頭到尾沒踩到坑。WhisperX 贏在設計:它把「時間戳」從生成模型的順手猜測,改成一道有解的對齊問題。
我的順序是先裝 whisper.cpp;只有當你真的需要字級時間戳或語者分離時,才值得再扛 WhisperX 那套依賴。
📌 目錄
兩個工具各自在解什麼問題
whisper.cpp 是 Georgi Gerganov 的 ggml 系列專案之一,把 OpenAI 的 Whisper 模型用純 C/C++ 重寫一次,MIT 授權。它要解的問題是「讓 Whisper 在一般人的機器上跑起來」:不用 Python、不用 PyTorch,build 完就是一支執行檔加一個模型檔。
WhisperX 是 Max Bain 的研究專案,BSD-2-Clause,論文發表在 INTERSPEECH 2023。它要解的是另一個問題:Whisper 給你的時間戳不夠準也不夠細,只有句子級,而且會漂。WhisperX 在轉錄前後各接一段處理——前面用 VAD 切掉靜音,後面用 wav2vec2 音素模型做強制對齊,把時間戳磨到每一個字。轉錄本身它不自己做,是呼叫 faster-whisper。
看清楚這句話會省下很多糾結:WhisperX 的核心價值不是轉錄,是轉錄之後那一步。 它跟 whisper.cpp 不是同一個位置上的兩個選項。
我這兩個工具各自寫過一篇實測:whisper.cpp 本機語音轉文字 和 WhisperX 字級時間戳與語者分離。這篇是把兩次實測擺在一起,回答「所以我該裝哪個」。
我只用兩個維度比
我沒有用功能對照表來做這個決定。因為 whisper.cpp 在功能表上缺的那些欄位,多數是它刻意不做的——把「缺勾」當成「比較差」,會誤讀它的設計取向。
我實際做決定時只看兩件事:
這兩個維度是正交的。一個工具可以在形態上極簡而在設計上保守,反之亦然。這兩個工具剛好各佔一邊,所以它們的比較才有意義。
維度一:形態成本,以及我踩到的三個坑
whisper.cpp 的安裝在我這台是這樣:
git clone https://github.com/ggml-org/whisper.cpp.git
cd whisper.cpp
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j --config Release
bash ./models/download-ggml-model.sh large-v3-turbo
沒有第六步。macOS 上不用額外裝任何東西,Metal 支援預設開啟。跑完之後你手上有一支執行檔 build/bin/whisper-cli 和一個 .bin 模型檔,把這兩個東西複製到另一台 Mac 一樣能跑。
我從 clone 到轉出第一段中文,一個坑都沒踩到。
WhisperX 這邊,我裝在一個獨立的 venv 裡(whisperx 3.8.6、torch 2.8.0、faster_whisper 1.2.1),過程踩到三個東西:
| 遇到的狀況 | 影響 | 解法 |
|---|---|---|
torchcodec 載不起來,噴 libavutil.59.dylib 找不到 | 沒有影響,轉錄照跑照出 | 想清掉就 brew install ffmpeg |
NLTK 的 punkt_tab 沒附,對齊那步需要 | 真的擋住:跑完五分鐘輸出目錄是空的 | python -c "import nltk; nltk.download('punkt_tab')" |
在 /tmp 底下執行被擋,Blocked import of regex from current working directory | 直接跑不起來 | 換到自己家目錄跑,或加 PYTHONSAFEPATH=1 |
ls 輸出目錄才發現是空的。
這就是形態成本的差距。whisper.cpp 的失敗模式很少,因為它的依賴幾乎只有一個 C++ 編譯器;WhisperX 站在 PyTorch、faster-whisper、pyannote、NLTK 這一整疊之上,每一層都有自己的裝法和自己的坑。三個坑各自都有解,也都不難解,但你得先知道要去解。
這一項 whisper.cpp 大勝,而且不是小勝。 如果我要教別人裝一套本機語音轉文字,我只會教 whisper.cpp——不是因為它比較好,是因為對方照著做幾乎不會失敗。
維度二:時間戳是怎麼來的
翻過來看設計,WhisperX 有一件事做得很漂亮。
Whisper 的時間戳是它在生成逐字稿的同時「順便」預測出來的。這是一個生成任務:模型一邊猜下一個 token,一邊猜這個 token 大概在第幾秒。既然是猜,就會漂,而且沒有明確的訊號告訴你哪裡漂了。
WhisperX 換了一個問法。它先把逐字稿拿到手,然後另外載入一個 wav2vec2 音素辨識模型,做強制對齊:在「文字內容已經確定」的前提下,問題變成「把這串已知的字,排進時間軸上最合理的位置」。這已經不是生成問題,是一個有標準解法的動態規劃問題。
差別在於,這個問法會順便產出一個副產品:對齊的信心分數。這是我實測 JSON 裡的一段:
{"word": "我", "start": 0.993, "end": 1.193, "score": 0.984}
{"word": "是", "start": 1.193, "end": 1.393, "score": 0.903}
{"word": "陳", "start": 1.393, "end": 1.534, "score": 0.969}
{"word": "彥", "start": 1.534, "end": 1.594, "score": 0.668}
「彥」那個字 score 是 0.668,鄰居都是 0.9 以上。而那個位置剛好就是轉錄把我名字聽成同音字的地方——對齊不上,分數就掉下來了。
我沒有教它去偵測轉錄錯誤,這是「換一種問法」自然掉出來的東西。你可以直接拿 score 當篩選條件,把低分的位置抽出來人工複查。做語料清理、做字幕校對,這一欄很值錢。
whisper.cpp 在這個維度上是保守的:它就是把 Whisper 原本的行為忠實地跑出來,包含 Whisper 原本的時間戳品質。它沒有想解這個問題。
速度數字與它的可比性
先講一件必須誠實說的事:這兩組數字不能直接對比。 我兩篇實測用的不是同一段音檔(whisper.cpp 那次是用 macOS 的 say 合成的 17.6 秒旁白,WhisperX 那次是我自己錄的 17.66 秒語音),模型也不同,一個走 Metal 一個純 CPU。
所以下面這張表只能當「各自的量級」看,不是賽跑成績:
| 工具與設定 | 音檔 | 耗時 | 相對即時 |
|---|---|---|---|
| whisper.cpp base(多語,BLAS) | 17.6 秒中文 | 2.54 秒 | 約 6.9 倍 |
| whisper.cpp large-v3-turbo(Metal) | 17.6 秒中文 | 11.94 秒 | 約 1.5 倍 |
| WhisperX base + 對齊(純 CPU) | 17.66 秒中文 | 35.11 秒 | 約 2.0 倍(比音檔慢) |
WhisperX base + --no_align(純 CPU) | 17.66 秒中文 | 25.71 秒 | 約 1.5 倍(比音檔慢) |
從這張表能安全推出來的結論只有兩個:
- 兩者在這台 8GB 的 M2 上都是可用的量級,一小時的錄音都在幾十分鐘內能處理完。
- WhisperX 的對齊那一步在我這台大約多花 9 秒(35.11 減 25.71),這是換到 86 個字全部帶時間戳的價格。
選擇順序
我的建議不是二選一,是先後:
先裝 whisper.cpp。 理由是它的成本近乎為零,而且對大多數需求它就是答案。把會議錄音轉成文字、把 podcast 轉逐字稿、把訪談整理成筆記——這些只要句子級時間戳,甚至只要純文字。whisper.cpp 用 large-v3-turbo 在我這台中文全對,還快過即時。
確定需要下面這些,才裝 WhisperX:
- 要做字級字幕(卡拉 OK 式逐字上色、短影音逐字跳動字幕)
- 要語者分離,需要知道每句話是誰講的
- 要做語料品質篩選,想用
score自動標出可疑位置 - 要在逐字稿上做精確剪輯,需要知道某個詞的秒數
反過來說,如果你確實需要字級時間戳,那三個安裝坑就完全值得——因為沒有第二個工具會用同樣乾淨的方式給你 score 這一欄。
順帶一提,我兩個都留在機器上,沒有卸載任何一個。它們吃的空間不衝突,用途也不重疊。
什麼情況我不會用這兩個
誠實講邊界:
- 要即時串流轉錄(一邊講一邊出字)。這兩個都是為離線批次設計的。whisper.cpp 有 stream 範例,但那是滑動視窗的近似做法,不是真正的串流架構。
- 音檔量大到需要 GPU 農場。WhisperX 的 README 寫的「70x realtime with large-v2」是 CUDA 環境的數字,跟 Mac 沒有關係;真要大量處理,該考慮的是租 GPU 而不是在筆電上排隊。
- 需要商用等級的中文標點與段落切分。兩者輸出的中文標點都偏機械,WhisperX 的中文對齊還是字元級不是詞級,正式字幕仍然要自己拿
words陣列重新分組。 - 語者分離要開箱即用。WhisperX 的 diarization 預設模型是 HuggingFace 上的 gated model,要先去接受條款、掛個人 access token。這一段我自己沒有實測過(我的測試音檔只有我一個人講話),上面的描述是我讀
whisperx/diarize.py和 README 得到的,不是我跑出來的結果。
FAQ
whisper.cpp 跟 WhisperX 該選哪一個?
多數情況先選 whisper.cpp,因為安裝成本近乎為零而且對一般轉錄需求足夠。只有當你需要字級時間戳、語者分離或對齊信心分數時,才需要再裝 WhisperX。這兩個不是互斥選項,可以同時裝。
WhisperX 為什麼比 whisper.cpp 慢?
因為它做的事情比較多。WhisperX 除了轉錄,還跑了 VAD 前處理和 wav2vec2 強制對齊。我實測對齊那一步在 M2 純 CPU 上大約多花 9 秒(17.66 秒的音檔)。另外我的 WhisperX 測試是純 CPU,whisper.cpp 大模型走的是 Metal GPU,這兩組數字用的不是同一段音檔也不是同一個後端,不能直接對比。
字級時間戳一定要用 WhisperX 嗎?
whisper.cpp 有 -ml 之類的參數可以控制輸出粒度,但那是把句子切短,時間戳的來源仍然是 Whisper 自己預測的。WhisperX 的字級時間戳是另外用 wav2vec2 音素模型對齊算出來的,而且附帶信心分數,來源和品質是兩回事。
兩個都裝會不會衝突?
不會。whisper.cpp 是一支獨立執行檔加模型檔,WhisperX 是 Python 套件,我把它裝在獨立的 venv 裡。兩者各自的模型權重也是分開下載、分開快取的。
8GB 記憶體的 Mac 跑得動嗎?
我這台就是 8GB 的 M2。whisper.cpp 載入 1.5GB 的 large-v3-turbo 全程沒有 swap 壓力,運算緩衝區加起來不到 200MB。WhisperX 用 base 模型加 int8 量化也跑得動,但它同時要載轉錄模型和對齊模型,記憶體壓力比 whisper.cpp 明顯大。
小結
whisper.cpp 和 WhisperX 放在一起比,會發現它們在不同的維度上各自做到很好:一個把安裝成本壓到幾乎不存在,一個把時間戳從猜測改成可解的對齊問題。這兩件事沒有互相取代的關係。
我在同一台 M2 MacBook 上實測的結果是:whisper.cpp 從 clone 到轉出中文零個坑,large-v3-turbo 中文全對且快過即時;WhisperX 踩了三個安裝坑,但 86 個字全部拿到 start、end 和 score,而且低分的位置準確指向轉錯的那個字。
所以順序是先 whisper.cpp,需要字級時間戳再加 WhisperX。兩個都留著不衝突。
延伸資源
- whisper.cpp GitHub — MIT 授權,ggml-org 維護
- WhisperX GitHub — BSD-2-Clause,Max Bain
- WhisperX 論文(arXiv 2303.00747) — INTERSPEECH 2023
- 我的 whisper.cpp 實測:whisper.cpp 本機語音轉文字:M2 MacBook 實測
- 我的 WhisperX 實測:WhisperX 字級時間戳與語者分離