·7 min read·alesion30.tech

scribeでローカル完結の文字起こし

ON THIS PAGE

はじめに

打ち合わせを録音して文字起こししたいのですが、音声には外に出しにくい話が混ざることがあります。仕事では基本的にPCを持ち歩いているので、録った音声を外部サービスに預けずに手元だけで処理できる形が欲しくなり、macOS向けのCLIツールを作りました。

下記リポジトリで開発しています。

https://github.com/Alesion30/scribe

現時点の最新リリースはv0.2.1になります。

scribeとは?

マイクとシステム音声を録音して、whisper.cppでそのまま文字起こしするmacOS向けのコマンドラインツールです。音声の取り込みにScreenCaptureKit、音声処理にAccelerate(vDSP)を使い、whisper.cppは同梱してMetalで動かしています。録音した音声も推論も端末内で完結するので、外部の文字起こしAPIに音声を送ることはありません。

※ ネットワークを使うのは、モデルの初回のダウンロードだけになります。落ちてくるのは文字起こし用のモデルと、無音を飛ばすために使うVADのモデルで、どちらも~/.scribe/models/に置かれて次回以降は再利用されます。

既存のサービス

会議の録音から文字起こし、議事録まで面倒を見てくれるサービスは既にたくさんあります。

いずれも、文字起こしに加えて要約や検索、共有、他ツールとの連携といった機能が、サービスやプランに応じて提供されています。そこまで含めて任せたいのであれば、こちらのほうが早いと思います。今回は機能を比べた結果というより、音声の置き場所を手元から動かしたくなかった、という好みの話になります。

インストール

録音に使っているScreenCaptureKitのサポートの都合で、動作にはmacOS 15以降が必要になります。

導入はmiseを使うのが手軽です。

mise use -g "github:alesion30/scribe"
scribe --help

モデルは事前に落としておくことができます。標準で使うlarge-v3-turboは約1.5GB、軽いbaseは約141MBです。

scribe model download large-v3-turbo
scribe model download base

macOSのマイクと、画面収録およびシステム音声の録音の許可も必要になります。許可はターミナルアプリに対して与える形になるので、システム設定から使っているターミナルを追加してください。

録音して文字起こしする

引数なしで実行すると録音が始まり、Ctrl+Cで止めるとそのまま文字起こしに入ります。

scribe

録音した音声は文字起こしのための途中のファイルという扱いになっているので、既定では文字起こしが終わった時点で削除されます。手元に残しておきたい場合は、--keep-audioを付けるか、-wで残す先を指定してください。

片方だけを録りたい場合は、落としたいほうを--no-で切ります。--no-micでマイクを切るとシステム音声だけ、--no-systemでシステム音声を切るとマイクだけになります。

# システム音声だけを録音する
scribe --no-mic

# マイクだけを録音する
scribe --no-system

モデルは-m、言語は-lで指定することができます。

scribe -m base -l ja

出力先は-o、出力形式は-ftxt / srt / vtt)で指定します。

scribe -o transcript.srt -f srt

録音済みのファイルを後から文字起こしすることもできます。

scribe transcribe recording.wav

長い録音は既定で600秒ずつに区切って処理し、Silero VADで無音を飛ばすようになっています。

モデルごとの速度

文字起こしにかかる時間はモデルによって変わるので、手元のMacBook Air(M2 / メモリ24GB / macOS 26.5.2)で測ってみます。使ったのはscribe v0.2.1になります。

テスト音声はmacOSのsayで合成します。会議を模した339文字の原稿を読み上げさせて、同じ原稿を繰り返すことで長さの違う3本を作ります。

say -v Kyoko --file-format=WAVE --data-format=LEI16@16000 -o base.wav -f base.txt

計測はモデルを変えながらscribe transcribeを回すだけで、VADと分割は既定のままです。

scribe transcribe base.wav -m large-v3-turbo -l ja -o transcript.txt

結果は下記のようになりました。各3〜6回実行したうちの最短値になります。

モデル サイズ 1分5秒 5分24秒 16分13秒
tiny 約74MB 1.6秒 5.6秒 16.3秒
base 約141MB 2.1秒 7.7秒 22.8秒
small 約465MB 4.1秒 15.7秒 50.6秒
large-v3-turbo 約1.5GB 7.7秒 25.8秒 114.0秒

tinyは実時間の約60倍速、既定のlarge-v3-turboでも8倍から12倍速になります。16分の音声が2分弱で終わるので、打ち合わせを止めてから議事録を待つ時間としては許容できる範囲だと思います。

※ ばらつきは大きめでした。large-v3-turboの16分13秒は114秒から176秒まで振れています。ファンレスのMacBook Airなので、長い処理では発熱で落ちているのだと思います。ほかの作業を走らせながら測ると、どのモデルも1.5倍ほど遅くなりました。

※ 合成音声には無音がほとんど無いため、VADで飛ばせたのは0.2%だけでした。実際の会議の録音であれば、無音が多いぶんもう少し速くなります。

モデルごとの精度

同じ1分5秒の音声を、読み上げさせた原稿と突き合わせてみます。原稿の冒頭は下記になります。

本日の定例を始めます。まず前回からの進捗を共有します。検索機能の改修は実装が終わり、今はレビュー待ちの状態です。想定より時間がかかった理由は、インデックスの再構築にかかる時間が本番データで大きく伸びたためです。

tinyの結果になります。

本日の定例を始めます まず前回からの新直を共有します
検索機能の回収は実装が終わり 今はレビューマチの状態です
相提より時間がかかった理由は インデックスの最高地区にかかる時間が
本番データで大きく伸びたためです

large-v3-turboの結果になります。

本日の定例を始めます。
まず前回からの進捗を共有します。
検索機能の回収は実装が終わり、今はレビュー待ちの状態です。
想定より時間がかかった理由は、インデックスの再構築にかかる時間が本番データで大きく伸びたためです。

tinyは「進捗」が「新直」、「再構築」が「最高地区」になっていて、読み返しても何の話か分かりません。large-v3-turboは同音異義語の「改修」が「回収」になっている程度で、句読点も入ります。

原稿と比べた文字単位の誤り率は下記のようになりました。句読点と空白を除いて数えています。

モデル 誤り率
tiny 18.3%
base 8.2%
small 3.5%
large-v3-turbo 1.3%

文字起こしをそのまま読み返すのであればlarge-v3-turbo、動作確認や録音が拾えているかの確認であればtinyやbase、という使い分けになると思います。

※ 合成音声なので、雑音が入ったり複数人の声が重なったりする実際の会議より条件は良くなります。数値は目安として見てください。

議事録に整える

文字起こしはObsidianのVaultに置いていますが、自動生成されたそのままのログと、読み返すための議事録はディレクトリを分けています。ログのほうは長いうえに認識ミスも残るので、後から探すのは整形したノートだけで済ませたいためです。

録音から議事録までは、Vaultに置いたラッパースクリプトで繋いでいます。やっていることは、出力先を決めてscribeに渡し、終わったらClaude Codeを呼ぶだけです。

#!/bin/bash
# Vaultのルートを基準に、文字起こしを実行時刻の名前で吐く
vault="$(cd "$(dirname "$0")/.." && pwd)"
output="$vault/logs/transcripts/$(date +%Y%m%d_%H%M%S).md"

scribe "$@" -o "$output"
claude -p "/meeting-minutes $output"

引数はそのままscribeへ渡しているので、--no-micやモデルの指定はラッパー越しでも同じように使えます。打ち合わせが終わって録音を止めると、文字起こしから議事録の生成まで続けて走ります。

/meeting-minutesはVaultに置いた自作のスキルで、渡された文字起こしを読んで議事録用のディレクトリにノートを作ります。毎回プロンプトを書かずに済むほか、書かれていない内容は補わないことや、関連するノートへのリンクは対応が明らかなときだけ張って曖昧なら推測で紐付けないことを、あらかじめ決めておけます。

scribeの責務は録音と文字起こしだけなので、議事録にまとめたりなどの加工については、利用者各々のユースケースに合わせることができるのが、scribeの強みになります。私はObsidian・Claude Codeという運用方法に落ち着いていますが、ローカル完結のツールなので、利用者の環境に合わせてそれぞれ好きなツールやエージェントに適用することが可能です。

参考URL