今天放了一個小東西上 PyPI,叫 Plaudio。給 Plaud Note 錄音機用的聲紋辨識工具,Python 寫的,AGPL-3.0,只跑在 Apple Silicon Mac 上,v0.1.0。
純粹為自己而做。我開的會通常四到七人,不少是同事。他們的聲音對沒「見過」他們的模型來說,其實都差不多。但逐字稿裡「誰說的」跟「說了什麼」一樣重要——這就是現有工具掉鏈子的地方。
群集合併的問題
pyannote 的標準流程是先分群,再貼標籤。聲音差異大時這招很管用,但四個音高、口音、語氣都接近的人在同一間會議室,pyannote 常常把他們攜成同一個 SPEAKER。模型很有把握,結果篩定地錯了——所有發言全被討到其中一人身上,剩下三個從逐字稿裡消失。
錯得理直氣壯的逐字稿,比沒有逐字稿還糟。你會引用它、轉述它、分享它——然後把某個決定討到一個根本沒做這個決定的人頭上。
另一條路
Plaudio 的做法不一樣。它不去先分群再把整群配對到 profile,而是逐窗匹配。
你為每位經常出現的說話人「登錄」一次:給一段乾淨的 30 秒音檔,並徵得對方同意。登錄時 pyannote 的分離流程會吐出一段 256 維的嵌入向量。Plaudio 把它寫進本地的 JSON 檔,權限設為 0600。
處理新會議時,Plaudio 用 2 秒視窗、1 秒步幅在音訊上滑動。每個視窗交給 pyannote 算一段嵌入,再分別跟所有已登錄的 profile 算餘弦相似度。每個視窗自己挑出匹配的對象。連續同標籤的視窗合併成一段,再把這些段映射回原本的逐字稿區段。
相似的聲音再也不會被合併成同一群,因為這條流程裡根本沒有分群這一步。每個視窗各自決定。沒匹配上的視窗就停在 Unknown,這對於還沒登錄過的人來說,正是該有的答案。
實作不大,幾百行 Python,但實際效果很大。一旦聲紋庫裡有了常客,那種四人語氣相近、原本會被併成單一群組的會議,也能逐窗標對。
v0.1 包含什麼
從音訊出發的這半邊管線:
plaudio transcribe meeting.mp3
plaudio match meeting.mp3 meeting.plaud.json --threshold 0.55
plaudio label meeting.mp3 meeting.plaud.json --enrol # 起步:聲紋庫還是空的時候用
plaudio enrol clean-30s-clip.mp3 --name "Alice Smith" --start 0 --end 30
plaudio db ingest meeting.plaud.json --meeting-id 2026-05-30-team
plaudio db search "deadline" --speaker "Alice Smith"
這幾個指令裡最容易被忽略的是 plaudio label。第一次跑 Plaudio 的時候,你的聲紋庫是空的,所以每個群最後都會被標成 Unknown,根本沒有 profile 可以拿去匹配。互動式標記介面就是為這個情境做的:它從每個未知的群裡挑出最長的一段乾淨獨白,背景播放給你聽,請你輸入名字,把標籤寫回逐字稿,並在你加上 --enrol 的時候,順手把這個聲紋也登錄進庫裡。大概跑過十場左右的會議之後,常出現的人就都進庫了,這個互動步驟也自然就不需要了。如果你早就知道誰是誰,還可以用 --batch-label "SPEAKER_00=Alice,SPEAKER_01=Bob" 這個形式,完全跳過音訊播放。
另外還有一個聲紋庫管理工具(plaudio voicebank list / export / import / migrate / remove),以及一個 doctor 指令,會直接告訴你缺哪一個依賴。
技術棧上,ASR 用的是 mlx-whisper(跑在 Neural Engine 與 GPU 上,在 M 系列晶片上大約有六倍即時的速度),嵌入模型來自 pyannote-audio 3.1,可搜尋的語料庫則是 SQLite 加上 FTS5 的 trigram 分詞器。trigram 分詞器是讓中英文混雜搜尋能順利運作的關鍵,這對我參與的會議很重要。
Plaud 雲端同步留在 v0.2 再做。完整的 README 與 技術棧理由 都放在 GitHub 上。
從這個過程中我學到的
三個觀察。
第一,先為自己做,是一種紀律,不是退而求其次的選擇。我從一開始就有清楚的測試情境(我自己開的會議)。我知道什麼叫做成功(正確的名字出現在逐字稿裡)。我是第一個使用者、第一個 bug 回報者,也是第一個受益者。發佈開源專案最大的誘惑就是太早把範圍擴大。紀律就是先把窄窄的事情做好,要不要擴大,留給後續別人感不感興趣去回答。
第二,審查關卡比程式碼本身更重要。我從工作的 vault 裡自動生出一份私人詞表:同事的姓氏、計劃代號、內部縮寫。每一次 commit、每一次 CI build 都會把差異拿去比對這份詞表。pre-commit hook 是強制執行的;我給自己定了規矩:不准用 --no-verify 繞過。在我寫任何一行 Plaudio 程式碼之前,我就先把這套審查工具搭好了,因為程式碼一旦進了公開倉庫,就等於永久發佈了。洩漏比缺一個功能還難回復。
第三,垂直切片比水平分層出貨快。Plaudio 的每一個子指令都是端到端做完才開始下一個:測試、實作、CLI 全部包在同一個切片裡。把一個函式庫抽出來時,誘惑是先把所有核心演算法寫好,再去包所有的 CLI。紀律是先讓單一個指令從頭到尾跑得起來,再去做下一個。
接下來
v0.1 已經上線。v0.1.1 已知還有一份小型的待辦清單:有個預設參數設錯了、某條錯誤路徑直接吐原始的例外而不是友善訊息、兩個棄用警告需要清掉。v0.2 會加上 Plaud 雲端同步。
如果你手邊有一台 Apple Silicon 的 Mac,用的也是 Plaud Note Pro,並且遇到同樣的群集合併問題,請用 pip install plaudio 安裝。如果不是,那這個工具大概不適合你,這也是有意為之。