sherpa-onnx 對上 Whisper:離線語音辨識怎麼選?台灣華語實測與 STT 技術盤點

語音訊號分流到本機筆電與遠端運算的示意圖

48 秒的台灣華語音檔,sherpa-onnx 跑完只花 0.76 秒。同一段音檔、同一台 MacBook,只用 CPU 的 faster-whisper 跑 medium 模型要 31 秒,差了 40 倍。

差這麼多,第一個反應通常是「那準確度一定爛掉吧」。結果清楚語音的字錯誤率兩邊都在 2% 到 4% 之間,差距比我想像的小很多。反倒是 Whisper 在快語速時開始「腦補」,這個比速度更值得注意。這篇把我實測 sherpa-onnx(跑 SenseVoice 模型)和 Whisper 的過程整理出來(素材是 TTS 合成語音,限制後面會講清楚),順便盤點 2026 年還有哪些語音轉文字(STT)技術值得看,最後依使用場景給選擇建議。

測試環境

  • 硬體:Apple Silicon MacBook(arm64),只用 CPU、4 執行緒
  • sherpa-onnx 2.0.1(Python wheel),模型 SenseVoice int8(zh/en/ja/ko/yue,2024-07-17 版)
  • faster-whisper 1.2.1,模型 Whisper medium 與 large-v3-turbo,int8 量化、beam size 5、開啟內建 VAD
  • Python 3.12,另用 OpenCC 做簡轉繁
  • 前置知識:會用 pip、知道什麼是取樣率就夠了

先搞清楚:sherpa-onnx 不是模型,是推論框架

很多人把 sherpa-onnx 跟 Whisper 放在同一個層級比較,這其實有點錯位。

sherpa-onnx 是 k2-fsa 團隊(新一代 Kaldi)做的語音推論框架,底層是 onnxruntime。它本身不訓練模型,而是把各家模型轉成 ONNX 之後統一跑起來:SenseVoice、Whisper、Paraformer、Zipformer、Moonshine、NVIDIA Parakeet 都能載入。除了語音辨識,它還包了 TTS、VAD、說話人分離、關鍵字偵測,支援 C++、Python、Swift、Kotlin、Go、Rust 等 12 種程式語言,Linux、macOS、Windows、Android、iOS、樹莓派、WebAssembly 都能跑,授權是 Apache-2.0。

所以這篇真正在比的是兩件事:

  • 模型:SenseVoice (阿里巴巴通義實驗室 FunAudioLLM)對上 Whisper (OpenAI)
  • 推論方式:sherpa-onnx + onnxruntime 對上 faster-whisper + CTranslate2

把這兩層拆開來看,後面的結果才好解釋。

自回歸逐字輸出與非自回歸一次輸出的對比示意

兩種模型的底子:一個一次吐完,一個一個字慢慢吐

Whisper 是標準的 Transformer 編碼器加解碼器(encoder-decoder)架構。OpenAI 在論文 裡寫的訓練資料是 68 萬小時多語言、多任務的弱監督資料。解碼器是自回歸(autoregressive)的,每一步都要看前面已經產生的字,才決定下一個字是什麼,所以句子越長、要跑的步數就越多。

SenseVoice-Small 走的是另一條路:非自回歸(non-autoregressive)的端到端架構,整段音訊編碼完,一次就把所有字吐出來。官方 README 寫的是訓練資料超過 40 萬小時,在相近參數量下比 Whisper-Small 快 5 倍以上、比 Whisper-Large 快 15 倍。開源的 Small 版支援華語、粵語、英語、日語、韓語五種,另外附帶語言辨識、情緒辨識、音訊事件偵測(笑聲、掌聲、咳嗽)和反正規化(ITN,把「九點」轉成「9點」)。

音訊 → 特徵擷取 ─┬→ Whisper Encoder → Decoder 第 1 步 → 第 2 步 → … → 第 N 步 → 文字
                 │
                 └→ SenseVoice Encoder → 一次輸出全部文字

上面那條路要繞 N 圈,下面那條一步到位。這是速度差到幾十倍的主因之一。另一個因素是推論框架不同(onnxruntime 對上 CTranslate2),本文沒有拆開控制;sherpa-onnx 其實也能跑 Whisper,有興趣可以自己補這組對照。

自回歸的代價和好處都很直觀:解碼器本質上就是一個語言模型,能靠上下文「猜」出聽不清楚的字,所以對口音和雜音比較寬容;但同一個機制也會讓它在沒聲音的地方自己編故事,這點後面踩坑段會講。

授權方面,Whisper 的程式碼和權重都是 MIT。SenseVoice 的程式碼是 MIT,模型權重則走 FunASR 的模型授權協議,官方說明遵守協議即可商用。

實測:台灣華語、多語言與速度

先講清楚這份測試的範圍:一台機器、只用 CPU、素材以 TTS 合成語音為主,每組只跑一次。它能看出趨勢,但不是嚴謹的 benchmark。素材都是中性內容:

  1. SenseVoice 模型內附的 5 段短音檔(華、英、日、韓、粵,各 4 到 7 秒)
  2. 一段 192 字的台中一日遊短文,用 macOS 內建 TTS 的 Meijia(台灣華語)語音合成三個版本:正常語速(48.4 秒)、快語速(30.4 秒)、正常語速再疊加粉紅噪音

字錯誤率(CER)的算法是編輯距離除以參考文字長度。計算前先去掉標點、統一「臺/台」,也把「三點」和「3點」這類數字寫法視為相同,避免 ITN 的格式差異被算成錯字。

兩種語音辨識模型速度競賽的示意圖

準確度

素材 sherpa-onnx SenseVoice Whisper medium Whisper large-v3-turbo
正常語速(48.4 秒) 3.6% 3.1% 4.2%
快語速(30.4 秒) 3.1% 7.8% 63.5%
加噪音(48.4 秒) 2.6% 2.6% 4.2%

清楚語音三者都落在 2.6% 到 4.2%,真的差不多。快語速就不一樣了:SenseVoice 照樣 3.1%,Whisper 兩個模型都翻車。medium 在結尾多出一句音檔裡沒有的話,large-v3-turbo 更誇張,句子講完之後又自己生出一大段胡言亂語,字錯誤率直接飆到 63.5%。turbo 明明是比較新的模型,這結果我也沒料到。

兩邊共同的錯字幾乎都是同音字和地名:「審計新村」被聽成「沈紀新村」或「沈濟新村」,「搭高鐵」變成「大高鐵」。SenseVoice 另外會把「肉燥飯」寫成「肉灶飯」,斷句也常把逗號標成句號。

多語言短音檔的結果:

語言 sherpa-onnx SenseVoice Whisper medium
華語 開飯時間早上9點至下午5點。(全對) 開放時間早上9點至下午5點(「開飯」聽成「開放」,turbo 也一樣)
英文 全對 全對
日文 全對 「弁当制」寫成「弁当製」(turbo 全對)
韓文 內容正確,但詞間空格斷錯(조 금만 생각 을) 全對
粵語 呢幾個字都表達唔到,我想講嘅意思。(保留粵語用字) 這幾個字都表達不到我想說的意思(轉成書面華語)

速度

素材 長度 sherpa-onnx Whisper medium Whisper large-v3-turbo
台灣華語正常語速 48.4 秒 0.76 秒(RTF 0.016) 31.0 秒(RTF 0.64) 22.6 秒(RTF 0.47)
台灣華語快語速 30.4 秒 0.47 秒(RTF 0.016) 25.1 秒(RTF 0.83) 36.5 秒(RTF 1.20,含幻覺段落)
內附短音檔 4.6–7.2 秒 0.05–0.10 秒 3.7–5.0 秒 5.4–5.8 秒

模型載入時間另計:SenseVoice 約 0.6 秒,Whisper medium 約 2.0 秒、large-v3-turbo 約 2.4 秒(首次執行還要下載模型)。

RTF(Real-Time Factor)是「處理時間 ÷ 音訊長度」,越小越快。sherpa-onnx 的 RTF 穩定在 0.016 左右,換算成 1 小時的錄音大約 1 分鐘就跑完。

速度這一項要講公道話:faster-whisper 在 Mac 上只能用 CPU,而且我開了 beam search(beam size 5),本來就比較吃運算。如果改用 whisper.cpp 搭 Metal 或 Core ML,Whisper 會快不少。不過就算快個幾倍,跟 SenseVoice 還是不同量級。

這份測試的侷限

TTS 合成語音發音很標準,跟真人錄音差很多。一般經驗是自回歸的 Whisper 對口音比較寬容,帶口音的真人錄音結果可能會反過來。噪音條件也只測了一種,沒有量化訊噪比。數字當作方向參考就好,正式選型請用你自己的錄音再跑一次。

踩坑紀錄

麥克風聲波末端化為幻影,象徵 Whisper 的幻覺問題

faster-whisper 讀檔直接噴 TypeError

裝完 faster-whisper 1.2.1,第一次跑就炸:

TypeError: open() got an unexpected keyword argument 'metadata_errors'

原因是 faster-whisper 用 PyAV 解碼音檔,但環境裡的 PyAV(我這邊是 19.0.2)跟它預期的參數對不上。最省事的解法是不要讓它讀檔,自己用 soundfile 讀成 numpy 陣列再丟進去:

import soundfile as sf
from faster_whisper import WhisperModel

model = WhisperModel("medium", device="cpu", compute_type="int8", cpu_threads=4)
audio, sr = sf.read("tw_normal.wav", dtype="float32")  # 必須是 16kHz 單聲道
segments, info = model.transcribe(audio, language="zh", beam_size=5, vad_filter=True)
print("".join(s.text for s in segments))

傳 numpy 的時候,faster-whisper 會假設取樣率是 16kHz,所以音檔要先用 ffmpeg 轉好:ffmpeg -i input.m4a -ar 16000 -ac 1 output.wav。

Whisper 會「腦補」不存在的句子

Whisper 的幻覺(hallucination)是有名的問題。康乃爾大學 Koenecke 等人的研究 Careless Whisper 發現,大約 1% 的轉錄裡會出現整句音訊裡根本沒有的內容,而這些幻覺有 38% 帶有明確的傷害性,例如暴力描述或捏造的關聯。停頓越長的說話方式越容易觸發。

這次我自己也撞到了。快語速版本裡,Whisper medium 在最後多了一句「謝謝觀看,下集再見」,音檔裡根本沒這句話,一看就是從大量 YouTube 影片字幕學來的口頭禪。large-v3-turbo 更誇張,該講的都講完之後,又自己接了一大段「對方在海外的水平準設計劃照片……」這種完全不存在的內容,而且這還是在開了 vad_filter=True 的情況下。

比較保險的做法是設定 condition_on_previous_text=False,減少前文錯誤一路往下傳;後處理時再掃一遍「謝謝觀看」「請訂閱」這類高頻幻覺句。這些只能降低機率,沒辦法根治。

非自回歸的 SenseVoice 沒有「接著往下編」的機制,這次測試也沒看到它憑空生出句子。它的錯比較像「聽錯字」,而不是「編故事」。要做會議紀錄、醫療或法律逐字稿這種不能亂加內容的場合,這個差異很重要。

SenseVoice 長音檔一定要先切段

SenseVoice 是整段一次處理,直接丟幾分鐘的音檔進去,記憶體和準確度都會出問題。正確做法是先用 VAD(語音活動偵測)切成一句一句。sherpa-onnx 內建 Silero VAD,接起來很簡單:

import soundfile as sf
import sherpa_onnx

rec = sherpa_onnx.OfflineRecognizer.from_sense_voice(
    model="model.int8.onnx", tokens="tokens.txt", use_itn=True, num_threads=4)

cfg = sherpa_onnx.VadModelConfig()
cfg.silero_vad.model = "silero_vad.onnx"
cfg.silero_vad.min_silence_duration = 0.25   # 靜音 0.25 秒就切
cfg.silero_vad.max_speech_duration = 15      # 單段最長 15 秒
cfg.sample_rate = 16000
vad = sherpa_onnx.VoiceActivityDetector(cfg, buffer_size_in_seconds=200)

audio, sr = sf.read("long.wav", dtype="float32")
for i in range(0, len(audio), 512):
    vad.accept_waveform(audio[i:i + 512])
    while not vad.empty():
        s = rec.create_stream()
        s.accept_waveform(sr, vad.front.samples)
        rec.decode_stream(s)
        print(f"[{vad.front.start / sr:6.2f}s] {s.result.text}")
        vad.pop()
vad.flush()
while not vad.empty():
    s = rec.create_stream()
    s.accept_waveform(sr, vad.front.samples)
    rec.decode_stream(s)
    print(f"[{vad.front.start / sr:6.2f}s] {s.result.text}")
    vad.pop()

模型和 VAD 檔案從 sherpa-onnx 的 release 頁 下載,pip 裝 sherpa-onnx soundfile 就能跑。

簡轉繁會誤傷日文

SenseVoice 輸出的中文是簡體,台灣讀者得自己接 OpenCC。我一開始很懶,把所有輸出都丟進 s2twp 轉換,結果日文的「中学」「弁当」被轉成「中學」「弁當」,整個傻眼。OpenCC 只看字,不知道那是日文。解法是只對語言判定為中文的段落做轉換。另外,s2twp 會把「台」轉成「臺」,介意的話要自己再處理。

台語:兩邊都不行

這是台灣使用者最常撞到的牆。SenseVoice 和 Whisper 的支援語言都不包含台語(台灣閩南語)。遇到台語時,前者通常輸出一堆亂碼,後者會硬轉成意思不通的華語字。有台語需求的話,要往下一段提到的台語專用模型找。

2026 年還有哪些 STT 技術可以選

各種語音轉文字技術分布在不同裝置上的地圖示意

Whisper 和 SenseVoice 只是冰山一角。依我查到的資料,整理成下面這張表:

技術 類型 亮點 適合
whisper.cpp Whisper 的 C/C++ 推論 無依賴,Apple Silicon 可用 Metal 與 Core ML,支援整數量化 Mac/iOS 本機、嵌入到 App
faster-whisper Whisper 的 CTranslate2 推論 官方宣稱同準確度下比 openai/whisper 快最多 4 倍、更省記憶體 Python 批次轉錄、伺服器端
FunASR/Paraformer 阿里巴巴工具包與中文模型 Paraformer-zh 約 220M 參數,含時間戳;有串流版、VAD、標點、說話人分離 中文為主的正式產品
Moonshine Useful Sensors 的邊緣模型 10 秒音訊的運算量比 Whisper tiny.en 少 5 倍,錯誤率不升;可在 sherpa-onnx 跑 語音指令、穿戴裝置、即時字幕
NVIDIA Parakeet TDT 0.6B v2 FastConformer-TDT Open ASR Leaderboard 平均 WER 6.05%、RTFx 約 3,380(GPU、batch size 128);只支援英文(v3 擴充到 25 種歐洲語言) 有 GPU 的英文大量轉錄
Breeze-ASR-25 聯發科創新基地,Whisper-large-v2 微調 針對台灣華語與中英夾雜,CommonVoice zh-TW 的 WER 從 9.84 降到 7.97 台灣口音、中英混講的會議與課程
Breeze Taigi 台語辨識研究與基準 用約 1 萬小時合成台語語音微調 Whisper,在其台語基準上平均 CER 30.13% 台語研究與實驗
Vosk Kaldi 系離線工具包 每個語言模型約 50 MB,支援串流與自訂詞彙 樹莓派、低階 Android
雲端 API(如 OpenAI gpt-4o-transcribe) 商用服務 免部署、持續更新;音檔要上傳,依用量計費 不在意資料外送、要快速上線

幾個重點補充一下。

sherpa-onnx 本身就能跑 Moonshine、Paraformer、Parakeet 和串流版 Zipformer,所以它更像一個「本機語音模型的萬用插座」。今天選 SenseVoice,明天想換 Moonshine,程式碼只改載入那一行,這彈性很實用。

台灣使用者特別值得看 Breeze-ASR-25。它是在 Whisper-large-v2 上針對台灣華語和中英夾雜微調的,在 CSZS 中英混講資料集上 WER 從 29.49 降到 13.01,幾乎砍半。工程師開會那種「這個 feature 的 deadline 要再 confirm 一下」的講法,它處理起來比原版 Whisper 穩很多。代價是它跟 Whisper large 一樣大,CPU 跑起來不會快。這個模型我沒有實測,以上數字都來自模型卡。

台語目前仍是低資源語言。Breeze Taigi 的 30% CER 在研究上已經算進步,但距離能直接拿來產生逐字稿還有一段路。HuggingFace 上也有個人用 LoRA 微調的 Whisper 台語模型,多數模型卡寫著「More information needed」,用之前務必自己驗證。

雲端 API 我沒有實測。順帶一提,OpenAI 開發者論壇上有一位使用者回報,在吵雜或多人對話的錄音上,gpt-4o-transcribe 的表現反而不如舊的 Whisper。這只是單一個案、沒有量化數據,但也提醒我們:選型前最好拿自己的音檔試過。

依場景怎麼選

要做語音轉文字
 └─ 音檔能不能離開本機?
     ├─ 可以 → 雲端 API 或任一本機方案
     └─ 不行 → 需要即時嗎?
         ├─ 要(裝置端)→ sherpa-onnx + SenseVoice/Moonshine/串流 Zipformer
         └─ 不用(批次)→ 錄音品質?
             ├─ 清楚、標準口音 → sherpa-onnx + SenseVoice(最快)
             ├─ 口音重、中英夾雜 → Whisper 系列或 Breeze-ASR-25(需人工校對)
             └─ 含台語 → 台語微調模型(結果需人工校對)

用文字講就是:

  • 即時字幕、語音指令、手機或嵌入式裝置:sherpa-onnx。RTF 0.016 的速度加上完整的跨平台支援,是這類場景最省事的起點。
  • 大量清楚的錄音要批次轉文字(Podcast、課程錄影):先用 sherpa-onnx + SenseVoice 跑一輪,成本最低。
  • 口音重、中英夾雜、品質不穩的現場錄音:Whisper 系列,台灣場景可以試 Breeze-ASR-25。語速快的段落要特別注意幻覺,本文測試中 large-v3-turbo 就在這裡翻車。
  • 不能容忍憑空多出內容的場合(醫療、法律):非自回歸模型的錯誤比較好預期;用 Whisper 的話,務必搭配 VAD 並人工校對。
  • 日、韓、粵語混合內容:SenseVoice 不用指定語言就能自動判斷,粵語還會保留粵語用字(「嘅」「唔」),這點 Whisper 做不到。

結語

以前講到語音轉文字,大家直接想到 Whisper,這沒有錯,它的口音容忍度和生態系到現在還是很強。但如果你的需求是在本機、要快、要能塞進手機或樹莓派,sherpa-onnx 搭 SenseVoice 是很實際的選擇:48 秒音檔不到 1 秒跑完,在發音清楚的語音上準確度跟 Whisper 差不多,快語速時也沒有出現幻覺。

我最大的體悟是:在我測過的範圍裡,沒有一個模型通吃。框架選 sherpa-onnx 的好處,就是模型可以隨時換。

我的測試缺了真人錄音這一塊。如果你手上有台灣口音或中英夾雜的錄音,很推薦拿同一段音檔,同時跑 SenseVoice、Whisper 和 Breeze-ASR-25 比一比。跑出什麼有趣的結果,歡迎留言分享,特別是台語的部分,我也很想知道有沒有更好的解法。

參考資料

沒有留言:

張貼留言

91APP 被駭的起點竟是 Appsmith:自架低代碼工具為何成了企業後門

上個月有朋友傳來一則簡訊截圖問我是不是詐騙。對方報得出她在某品牌官網買了什麼、寄到哪裡、哪天下單,然後說「訂單設定錯誤,請加 LINE 協助解除分期」。這種劇本大家都聽過,但這次的細節準到讓人頭皮發麻,因為資料是真的。 兩週後答案揭曉:台灣電商 SaaS 龍頭 91APP 的...