Communitygithub.com

kevin-burns/transcribe-summarize

Claude Code / Codex 技能,用於本機優先的會議轉錄。在 macOS、Windows 和 Linux 上執行 Whisper,過濾靜音時 Whisper 虛構的片段,並將結果撰寫為事實性會議記錄和 PDF。託管 API 為選擇加入,並在發送前告知其將發送的內容和費用。

transcribe-summarize 是什麼?

此技能提供一個完整的本地優先音頻轉錄與會議記錄管線。與直接呼叫 Whisper 不同,它能過濾掉 Whisper 在靜音時頻繁虛構的語音片段,並在側車檔案中記錄這些片段及其被拒絕的指標,以保持可稽核性。它還包含音訊清理(標準化和靜音修剪)功能,據實測可顯著提高準確性。支援多種後端:Apple Silicon 預設使用 `mlx-whisper`,其他平台使用 `faster-whisper`,以及可選的 `parakeet` 和四個網路後端(Groq、ElevenLabs、Gemini、OpenAI)。網路後端是嚴格的選擇加入制,絕非預設回退;工具會在發送任何資料前打印提供者、端點、檔案大小、持續時間和估計費用,並等待使用者確認。此技能也支援將平台(Teams、Zoom)提供的 `.vtt` 或 `.srt` 檔案標準化為 prose 格式,無需重新轉錄。強烈包含人工審查步驟:轉錄稿被視為草稿,技能會提示使用者驗證名稱、數字和日期。會議記錄的撰寫有嚴格規則(僅事實性摘要,不包含推論或“下一步行動”),並可透過一個檢查器強制執行。最終輸出包括帶時間戳的轉錄稿(作為 Markdown 和 SRT)、一個包含所有區段的 JSON 檔案、一個記錄執行的 JSON 檔案,以及可選的、由 headless Chrome/Chromium/Edge 渲染的 PDF。支援 Apple Silicon、macOS、Windows 和 Linux。

相容平台✓Claude Code✓Codex CLI~Cursor✓Gemini CLI
npx skills add kevin-burns/transcribe-summarize

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

transcribe-summarize 是做什麼的?

輸入音訊,輸出轉錄稿,並可選擇輸出會議記錄。預設路徑完全在使用者的機器上執行。

有兩件事讓此技能與直接呼叫 Whisper 不同,這兩件事都源於一整天的測量而非設計:

  1. Whisper 會在有靜音時虛構語音,更大的模型也無濟於事。 在一個有 40 秒加入靜音的實際通話中,large-v3 產生了一個 18 秒的片段,內容是重複一個詞 55 次。此技能會過濾掉這些片段,並將它們連同拒絕它們的指標保留在一個側車檔案中,以便決策過程可被稽核。
  2. 清理音訊勝過選擇模型。 標準化和修剪靜音將虛構的片段從 2 個減少到 0 個,並修正了一個 large-v3 和 turbo 都搞錯的詞。此功能預設為開啟。

設定

ffmpeg 和 ffprobe 必須在 PATH 中 — macOS brew install ffmpeg,Windows winget install Gyan.FFmpeg,Linux apt install ffmpeg。

其他所有東西都是標準函式庫(stdlib)。後端使用自己的函式庫,並且只會載入選定的那個,因此使用 uv run --with 來選擇:

後端平台--with 規格
mlx-whisper — Apple Silicon 預設僅 macOS arm64'mlx-whisper>=0.4.2'
faster-whisper — 其他平台預設mac / Windows / Linux'faster-whisper>=1.2'
parakeet — 選擇加入Apple Silicon 已驗證'parakeet-mlx'
groq, openai, elevenlabs, gemini — 選擇加入,需網路任意無需安裝

如果缺少函式庫,錯誤訊息會打印出確切的命令。無需猜測。

執行

在每個命令區塊的開頭宣告輔助函數 — shell 狀態不會在工具呼叫之間保留:

ts() {
  UV="$(command -v uv || ls "$HOME/.local/bin/uv" "$HOME/.cargo/bin/uv" \
        /opt/homebrew/bin/uv /usr/local/bin/uv 2>/dev/null | head -1)"
  "$UV" run --with "$1" --script "$HOME/.claude/skills/transcribe-summarize/scripts/transcribe.py" "${@:2}"
}

# Apple Silicon
ts 'mlx-whisper>=0.4.2' meeting.m4a

# Windows / Linux
ts 'faster-whisper>=1.2' meeting.m4a --backend faster-whisper

# 偏化解碼器朝向已知的行話,並修正它總是搞錯的名稱
ts 'mlx-whisper>=0.4.2' meeting.m4a --prompt 'Terragrunt, EKS' --replace 'north wind=Northwind'

請使用絕對路徑。相對路徑僅在當前工作目錄恰好是技能目錄時才能解析。

輸出契約

<outdir>/
  <stem>.md                    轉錄稿,帶有 [hh:mm:ss] 錨點
  <stem>-artifacts/
      <stem>.srt              字幕
      <stem>.json              所有區段,包括被抑制的區段
      <stem>.run.json          後端、模型、修剪偏移量、防護計數

--json 將這些路徑以 JSON 格式輸出到標準輸出。請向使用者報告絕對路徑;需要他們四處尋找的檔案不能算作可交付成果。

時間戳是基於原始錄音的時鐘。 修剪會在解碼期間縮短音訊,而在寫入任何內容之前,偏移量會被映射回去,以便 .srt 與使用者自己的檔案對齊。

網路規則 — 先說明,再遵守

網路後端僅當使用者在該次調用中要求使用時才可連接。絕不能作為備用方案,絕不能在本地後端失敗後使用,絕不能因為它更快而使用。--backend auto 無法連接網路後端;沒有相關的程式碼路徑。

在發送任何內容之前,工具會打印提供者、端點、檔案大小、持續時間和估計費用,然後等待。使用 --dry-run 可在提交前向使用者顯示該資訊區塊。在非互動式會話中,未經確認的上傳將被拒絕。

金鑰來自環境變數,每個後端一個變數,除此之外別無他處。絕不接受金鑰作為旗標,絕不回顯金鑰,絕不將金鑰寫入檔案。

後端金鑰模型費用/小時區分說話者
groqGROQ_API_KEYwhisper-large-v3-turbo0.04否
groqGROQ_API_KEYwhisper-large-v3 (預設)0.111否
elevenlabsELEVENLABS_API_KEYscribe_v20.22多達 32 位
geminiGEMINI_API_KEYgemini-3.5-transcribe0.306多達 3 位
openaiOPENAI_API_KEYwhisper-10.36否

--backend gemini — 執行前必須說的兩件事

ts '' /path/to/audio.m4a --backend gemini --dry-run     # 顯示資訊區塊,不發送任何內容
ts '' /path/to/audio.m4a --backend gemini               # 然後執行

無需安裝 — 它使用的是標準函式庫 http.client,因此 --with 參數為空。在告訴使用者執行此命令之前,有兩個事實必須包含在句子中,因為從命令列都看不出來:

  • 音訊會被上傳兩次。 Gemini 沒有單次請求的端點:檔案會先被發送到 Google 的 Files API,然後轉錄請求只攜帶返回的 URI。Google 會保留該上傳內容 48 小時。 揭露資訊區塊會打印此訊息;不要跳過它。
  • 30 分鐘是上限,而不是 Google 自己頁面上宣傳的一小時。一小時的時長僅在沒有時間戳記或說話者辨識的情況下適用,而此後端始終會請求這兩者 — 沒有時間偏移量就無法將時鐘映射回使用者的檔案。較長的錄音在上傳開始前就會被拒絕。

不要提供 Gemini 的 smart 模式。 它沒有被接上,這是刻意的。如果使用者詢問它(這是該模型的主要功能,它可以移除填充詞並改寫口語上的自我修正),答案是 Google 的 API 會拒絕同時提供時間戳記和說話者標籤,因此它不會產生 .srt 檔案和說話者資訊,並且它會更改文字。填充詞移除改在筆記步驟進行,在那裡它被標記為摘要並接受檢查。請參閱 references/backends.md。

品質防護

預設為開啟。被抑制的區段會保留在 .json 中,附帶原因和指標;它們會從 .md 和 .srt 中刪除。--guard mark 會將它們標記在行內,--guard off 則會停用防護。

此防護不適用於每個後端。 強規則讀取 Whisper 解碼器指標。faster-whisper、Groq 和 OpenAI 都會返回這三個指標,因此防護使用相同的程式碼。Parakeet、ElevenLabs 和 Gemini 都不返回任何指標,因此只會退回到與後端無關的規則 — 工具會在執行時說明這一點。請參閱 references/backends.md。

如果使用者問為什麼缺少了一段轉錄稿,請閱讀 .json:答案就在那裡,並附有導致此結果的數字。

從你已有的轉錄稿開始

大多數會議已經由平台轉錄,而且通常根本沒有音訊。 Teams 和 Zoom 會提供一個 .vtt(有時是 .srt)檔案,但作為散文難以閱讀:每幾秒一個提示句,句子在提示句之間被切斷,說話者的名字在每行重複,時間碼散佈各處。

這是一個受支援的入口點。不會重新轉錄 — 音訊路徑會被完全跳過:

"$HOME/.claude/skills/transcribe-summarize/scripts/normalise_transcript.py" meeting.vtt
# -> meeting.md,提示句被重新組合成段落,標明說話者,每個段落一個錨點

然後完全像轉錄稿在此解碼產生的一樣繼續進行:閱讀它,詢問會議事實,並在 references/notes-register.md 下撰寫筆記。

--no-speakers 會在來源標籤錯誤或不必要時放棄歸因。

它只是一個格式轉換,僅此而已。 不會更改任何文字,不會移除填充詞,不會修正語法。決定說了什麼是摘要步驟的事,它有自己的一套規則。如果使用者給你一份雜亂的轉錄稿並要求你「整理」,請在此處標準化格式,並在筆記中進行判斷 — 不要靜默地改寫別人在一份應該記錄他們話語的文件中的文字。

說話者資訊保留在轉錄稿中,但禁止出現在筆記中,這並非矛盾:轉錄稿是一個工作產物,可以攜帶來源資訊;而筆記是一份記錄,則不能。notes_check.py 仍然會拒絕筆記中原始的 Speaker 2 標籤。

如果有人將 .vtt 傳遞給 transcribe.py,它會停止執行並指向此處,而不是嘗試解碼它。

影片檔案

.mp4 實際上是 Teams 或 Zoom 下載的東西,它可以直接使用 — 無需先提取音訊。已驗證支援:.mp4、.mov、.mkv、.webm,以及所有音訊容器(.m4a、.mp3、.wav、.flac、.opus)。ffmpeg 會提取音訊軌道;影片部分被忽略,絕不會上傳。

一個沒有音訊軌道的檔案(例如靜音螢幕錄製)會事先被拒絕,不會將其提供給任何網路後端。該檢查特意在出口閘門之前執行,以確保靜音影片不會被上傳和收費。

審查是一個步驟,而非可選的附件

轉錄輸出是草稿。請說明這點,並讓使用者檢查它。

機器轉錄會自信地犯錯,其方式沒有任何閾值可以捕捉。在此專案的實際音訊上測量:large-v3 靜默地遺漏了一個說話者對數字的口頭修正,並且每個後端都將「board pack」聽成「board packs up」。兩者讀起來都非常流暢。品質防護可以捕捉靜音上的虛構;它無法捕捉看似合理的誤聽,你閱讀輸出也無法發現。

因此,工作流程是 轉錄 → 使用者檢查 → 然後筆記:

  1. 轉錄稿 .md 以一個 「值得檢查」 區段結尾 — 排序後的時間戳,這些時間點最值得重新聆聽(最不確定的區段,任何包含數字的區段)。明確地指引使用者到該處。
  2. 名稱、數字和日期是需要驗證的內容。 它們是最先出錯,並且在記錄中錯誤成本最高的部分。
  3. 修正直接寫入 .md,可以手動或使用 --replace 重新執行。然後重新產生任何基於它建立的東西。

絕不要將轉錄稿或一組筆記呈現為已驗證。你沒有聽到音訊;使用者聽到了。說明解碼出了什麼,說明哪些部分最不確定,然後讓他們確認。

編輯與重新產生

.md 是來源。編輯它,然後重建 PDF — 無需重新轉錄:

"$HOME/.claude/skills/transcribe-summarize/scripts/notes_check.py" notes.md
"$HOME/.claude/skills/transcribe-summarize/scripts/render_pdf.py"  notes.md

在任何編輯後再次執行檢查器。手動編輯正是引進來源資訊外洩或推斷出的「下一步行動」的時機。

撰寫筆記

當使用者想要會議記錄而不是轉錄稿時,你來撰寫它們 — 自己閱讀轉錄稿並產生文件。有一個 scripts/summarize.py 備用方案可以呼叫網路模型,但它用於在 Claude Code 會話之外執行此管線;在會話內部,它只是無謂的上傳。

先問清楚 — 音訊無法告訴你的三件事

這裡幾乎沒有後端能識別說話者。 每個 Whisper 引擎和 Parakeet 都不返回說話者資訊。兩個例外:--backend elevenlabs (Scribe) 最多可區分 32 位說話者,--backend gemini 最多可區分 3 位。兩者都返回位置標籤而不是名字 — 分別是 speaker_0 和 spk:0,這些格式是於 2026-09-04 和 2026-09-06 從即時響應中測量得到的 — 並且註冊表禁止在筆記文件中使用任何一種格式的原始標籤。因此,它們只能告訴你有多少人發言以及哪些行是屬於一起的;它們仍然無法告訴你是誰。歸因在任何情況下都來自使用者;說話者辨識只是使從轉錄稿而非記憶中進行映射成為可能。

在撰寫筆記之前,詢問:

  1. 誰在場。 如果沒有名字,則完全不使用歸因來撰寫筆記 — 非人稱的「據稱…」。絕不要虛構一個名字、一個角色或一個位置標籤。如果轉錄稿清楚地顯示誰在發言(某人被直接稱呼名字),你可以歸因;有歧義則不寫名字。
  2. 會議的日期。 今天的日期是預設值,並非事實。音訊常常在對話結束數天後才被寫成文字,而事實記錄上錯誤的日期比沒有日期更糟糕。請確認。
  3. 會議的性質 — 用與會者自己的話來說的標題。

一次性在一條訊息中詢問所有三項,並提供今天的日期作為預設值,以便使用者只需更正即可。如果使用者拒絕提供與會者,則在沒有歸因的情況下進行,並說明你已這樣做。

在寫下任何一個字之前,閱讀 references/notes-register.md。 它很短,而且是完整的規範。它不是風格建議;其中的規則是透過從真實文件中手動刪除段落而學到的,原因來自法律而非美學。

它所實行的兩條規則:

  • 僅事實摘要。 說了些什麼。沒有分析,沒有含義,沒有「下一步行動」,沒有「未涵蓋的內容」,沒有填補空白。
  • 它讀起來像是由在場的人所撰寫的協議記錄。 它絕不提及錄音、轉錄稿、音訊、模型或任何解碼器產物 — 沒有時間碼,沒有 Speaker 2 標籤。

然後每次都要檢查它 — 註冊表並非自我執行,要求進行摘要的模型會未經提示就添加分析:

"$HOME/.claude/skills/transcribe-summarize/scripts/notes_check.py" notes.md

退出碼 0 表示乾淨;退出碼 1 會列出 file:line 指出每個違規。在交付出文件之前修復它們。也要在 PDF 上執行它 — 僅存在於渲染檔案中的外洩仍然算數。

歡迎提供指導,但請在筆記之後,在文件之外。 在對話中提供你的解讀,或者將其寫入一個單獨的檔案。絕不要將其附加到文件後面。

PDF

"$HOME/.claude/skills/transcribe-summarize/scripts/render_pdf.py" notes.md

Headless Chrome、Chromium 或 Edge,會自動發現。如果沒有安裝任何一個,它會寫出 HTML,說明情況,並以退出碼 0 結束 — HTML 仍然是一個可交付成果。

來源

本地解碼使用 mlx-whisper (MLX) 或 faster-whisper (CTranslate2);音訊準備使用 ffmpeg。網路後端透過標準函式庫 urllib 直接呼叫 Groq 和 OpenAI 的轉錄端點 — 無需供應商 SDK。

將來源資訊排除在筆記文件之外會改變文件所說的內容,而不是實際發生的事情。未經同意錄音在許多司法管轄區是刑事犯罪

相關技能