Mac で無料&オフライン文字起こしアプリを自作した話:whisper.cpp + CoreML でリアルタイムに近い精度を実現

結論から言うと: Apple Silicon Mac 上で動作する完全オフラインの文字起こしアプリ「Local Whisper」を自作しました。whisper.cpp + CoreML + Silero VAD の組み合わせで、約7秒の音声を1秒程度で処理できます。マイク音声だけでなく、Web会議の相手の声(システム音声)も取得できるため、クラウド不要・サブスク不要で実用的な会議文字起こしが実現できます。


Mac で使える文字起こしアプリを探していて、こんな悩みはありませんか?

  • Web会議の相手の声も文字起こしに含めたい
  • 月額サブスクは払いたくない、たまにしか使わないのに
  • 音声データをクラウドに送信することに抵抗がある
  • 完全ローカルで動作し、中身が分かる OSS ベースのツールが欲しい

この記事では、上記をすべて満たす Mac 向け完全オフライン文字起こしアプリ「Local Whisper」を開発した経緯と、リアルタイム化を実現した技術的な工夫を詳しく解説します。

GitHub: https://github.com/y-dai20/local-whisper


Local Whisper とは?

Local Whisper は、OpenAI が開発した音声認識モデル「Whisper」を完全にローカル環境で動かす Mac 向け文字起こしアプリです。名前はそのまま「ローカルで Whisper を動かす」から来ています。

Windows でも動作しますが、CoreML(Apple の機械学習高速化フレームワーク)を活用できる macOS — 特に Apple Silicon Mac — の方が大幅に高速に動作します。

機能一覧

機能対応状況
完全オフライン動作(データ外部送信なし)
サブスク不要・無料
マイク音声の文字起こし
システム音声(相手の声)の文字起こし
Web会議をBot参加なしで文字起こし
OSS ベースで中身を確認可能

なぜ自作したのか

文字起こしアプリは世の中にたくさんあります。ただ、ほとんどのサービスには次のいずれかの問題があります。

  • 月額課金が必須 — 週に数回使う程度なのに毎月固定費がかかる
  • 音声データをクラウドに送信する — 機密情報を含む会議音声が外部に出る
  • Web会議はBot参加が必要 — 別アカウントで会議に参加させる形式で、相手に分かってしまう

特に音声データのプライバシーは、企業での利用や個人的な会話において無視できない問題です。

そこで目指したのは:

ローカルで完結し、OSS ベースで中身が監査できる文字起こしツール


コア技術:whisper.cpp + CoreML

完全オフラインかつ高精度を両立するために採用したのが whisper.cpp です。

whisper.cpp は、OpenAI の Whisper モデルを C/C++ で再実装したプロジェクトです。Apple Silicon の CoreML、NVIDIA GPU の CUDA など複数のバックエンドに対応しており、Python 版と比べて大幅に軽量・高速に動作します。

モデル構成

text
モデル:       Whisper large-v3-turbo
量子化:       Q5_0
高速化:       CoreML(Apple Neural Engine)

large-v3-turbo を選んだ理由
large-v3-turbo は Decoder を軽量化しながら Encoder を large-v3 と同等に保った派生モデルです。large-v3 と比べて推論速度が大幅に向上しつつ、精度の差は実用上ほぼ感じられないレベルに収まっています。

Q5_0 量子化を選んだ理由

量子化(Quantization) とは、モデルの重みを浮動小数点(fp16 など)から低精度の整数(5bit など)に変換する技術です。モデルサイズを大幅に削減しつつ、精度の低下を最小限に抑えられます。

Q5_0(5bit 整数量子化)を選択した結果:

  • モデルサイズが fp16 比で約 65% 削減
  • 文字起こし精度への影響は最小限(WER の変化は 1〜2% 程度)
  • Apple Silicon の Neural Engine との相性が良好

実測値

CoreML 有効化・Apple Silicon Mac での計測結果:

約7秒の音声 → 約1秒で文字起こし完了(RTF ≈ 0.14)

RTF(Real-Time Factor)とは「音声1秒を処理するのに何秒かかるか」の指標で、0.14 は実時間の約7倍速で処理できることを意味します。これにより、Apple Silicon Mac であればリアルタイム運用が十分に現実的です。


リアルタイム文字起こしを実現する2つの最適化

whisper.cpp 単体でも高速ですが、長時間音声をそのまま渡すと推論時間が蓄積し、徐々に遅延が増大します。以下の2つの最適化でこれを解消しました。


最適化①:Silero VAD による無音区間の除去

VAD(Voice Activity Detection / 音声区間検出) とは、音声ストリームの中から「発話している区間」と「無音・雑音区間」を分離する技術です。Silero VAD は Silero AI が開発した軽量な Neural VAD モデルで、CPU 上でも高速に動作します。

Whisper は無音部分も含めてそのまま処理してしまうため、VAD なしでは以下の問題が発生します。

  • 無音部分で Encoder が無駄に計算される
  • 長時間使用でレイテンシが蓄積し続ける
  • リアルタイム性が失われる

Local Whisper のパイプライン:

text
音声ストリーム
    ↓
小チャンクに分割(例:512 サンプル単位)
    ↓
Silero VAD → このチャンクは発話?
    ↓ (YES)            ↓ (NO)
Whisper へ送信        破棄(処理しない)
    ↓
文字起こし結果

さらに、1秒以上の無音が続いた場合はセッションを終了し、次の発話を新しいセッションとして処理します。これにより、コンテキストバッファが際限なく膨らむのを防ぎます。

体感ベースでも、VAD あり/なしの差は明確に分かるレベルの改善です。


最適化②:audio_ctx 削減で Encoder 時間を半減

Whisper の推論時間のほとんどは Encoder — 音声スペクトログラムを潜在表現に変換する部分 — が占めています。

Whisper は Transformer の Encoder-Decoder 構造を持ちます。Encoder が音声全体を処理してボトルネックになりやすく、Decoder はトークンを逐次生成しますが相対的に高速です。

デフォルトの audio_ctx = 1500 は約30秒分の音声コンテキストに相当しますが、リアルタイムで短いチャンクを処理する用途には過剰です。

text
変更前:audio_ctx = 1500(約30秒)→ Encoder 処理時間:約 1000ms
変更後:audio_ctx = 750 (約15秒)→ Encoder 処理時間:約  500ms

結果:Encoder レイテンシが約 50% 削減

リアルタイム文字起こしにおけるトレードオフの判断:

「長いコンテキストを正確に処理できる能力」よりも「低レイテンシ」の方が圧倒的に重要

実際の会話では1文が数秒程度であることがほとんどのため、15秒のコンテキストで実用上の問題はほぼありません。


2つの最適化の組み合わせ効果

最適化効果
Silero VAD(無音除去)セッション依存で大幅なレイテンシ削減
audio_ctx 1500 → 750Encoder 時間を約 50% 短縮
CoreML 高速化ベースラインで RTF ≈ 0.14(約7倍速)

3つを組み合わせることで、Apple Silicon Mac 上でリアルタイムに近い低遅延文字起こしが実現できています。


Mac でシステム音声を取得する方法:ScreenCaptureKit

開発の中で最も難しかった部分がシステム音声(Zoom や Google Meet などアプリの音声出力)の取得です。

一般的な方法は BlackHole などの仮想オーディオデバイスを使うものですが、配布アプリにバンドルするにはカーネル拡張のインストールが必要になるなど、ユーザー体験が悪くなります。

そこで採用したのが Apple 公式の ScreenCaptureKit(macOS 12.3 以降で利用可能)です。

text
アーキテクチャ構成:
┌──────────────────────────────────┐
│  ScreenCaptureKit (Swift)        │  ← システム音声・画面キャプチャ
│    ↓                             │
│  ブリッジ層                      │  ← Swift ↔ Rust FFI
│    ↓                             │
│  Tauri (Rust)                    │  ← アプリロジック
│    ↓                             │
│  whisper.cpp                     │  ← 文字起こしエンジン
└──────────────────────────────────┘

ScreenCaptureKit は macOS 12.3 で導入された Apple 公式のスクリーン・オーディオキャプチャ API です。仮想オーディオデバイスなしに、特定のアプリやウィンドウの音声を取得できます。

ScreenCaptureKit を使用したシステム音声取得には macOS 12.3 以降が必要です。それ以前の macOS ではシステム音声のキャプチャはできません。

この構成により同時取得できるもの:

  • マイク音声(自分の声)
  • システム音声(Web会議の相手の声、ブラウザ音声など)
  • 画面録画(将来的な機能拡張用)

結果として、Bot 参加不要・外部 API 不要で会議の両者の声を文字起こしできるツールになっています。


技術スタック全体

text
音声認識:         whisper.cpp
モデル:           Whisper large-v3-turbo(Q5_0 量子化)
ハードウェア高速化: CoreML(Apple Neural Engine)
VAD:              Silero VAD
UI フレームワーク: Tauri(Rust + Web フロントエンド)
システム音声取得:  ScreenCaptureKit(Swift → Rust ブリッジ)

Electron ではなく Tauri を選んだ理由

TauriElectron
バイナリサイズ小(5〜20MB 程度)大(100MB 超)
ランタイムネイティブ WebViewChromium 同梱
実装言語RustNode.js / JS
ビルド速度高速低速
ネイティブ API アクセスRust プラグイン経由Node.js 経由

Swift の ScreenCaptureKit を呼び出し、C++ の whisper.cpp とも連携する必要があるため、Rust ベースの Tauri が最適な選択でした。


開発期間

約3日でプロトタイプを完成させました。

Rust/Swift ブリッジのボイラープレート、Silero VAD の統合、Tauri プラグインの雛形など、定型的なコードは AI アシスタントを活用して高速に実装しました。アーキテクチャの判断は手動で行いましたが、実装速度は大幅に向上しました。


他の文字起こしアプリとの比較

比較項目Local Whisper一般的なクラウド型サービス
オフライン動作✅ 常時❌ ネット必須
サブスク費用無料月額 1,000〜3,000 円程度
データプライバシーデバイス外に出ない音声がクラウドに送信される
Web会議の相手の声✅ システム音声で取得△ Bot 参加が必要なことが多い
OSS・監査可能
セットアップの手軽さ中程度簡単
認識精度高(large-v3-turbo)

クラウド型の文字起こしサービスは手軽ですが、機密情報を含む可能性がある会議音声を外部サーバーに送信することになります。セキュリティポリシーや GDPR / 個人情報保護法の観点からも、ローカル処理の方が安全です。


今後の開発予定

  • ローカル LLM との連携 — 会議内容の自動要約をオンデバイスで生成
  • リアルタイム翻訳 — 文字起こしと翻訳を同時に表示
  • 翻訳表示モード — 原文と翻訳を並列表示

最終的な目標は「会議しながら即翻訳」を完全ローカルで実現することです。クラウドへの依存をゼロにしたまま、通訳レベルのリアルタイム支援を実現したいと考えています。


ダウンロード・リポジトリ

GitHub: https://github.com/y-dai20/local-whisper

ビルド済みバイナリとデモ動画をリポジトリで公開しています。モデルファイル(Whisper large-v3-turbo Q5_0)はファイルサイズの都合上、初回起動時に別途ダウンロードが必要です。

動作環境:

  • macOS 12.3 以降(ScreenCaptureKit によるシステム音声取得)
  • Apple Silicon Mac 推奨(M1/M2/M3/M4)— CoreML 高速化が有効
  • Intel Mac でも動作しますが、推論速度が大幅に低下します

FAQ

Q: Windows や Linux でも使えますか?

whisper.cpp 自体は Windows・Linux でも動作しますが、システム音声取得に使っている ScreenCaptureKit は macOS 専用です。Windows・Linux ではマイク入力のみ使用可能で、システム音声キャプチャは利用できません。また CoreML 高速化も macOS / Apple Silicon 限定です。

Q: large-v3-turbo は large-v3 と比べて精度はどれくらい落ちますか?

多くのベンチマークで、large-v3-turbo は large-v3 に対して WER(単語誤り率)が 1〜3% 程度の差に収まっています。日常会話や会議音声の文字起こし用途では、実用上の精度差はほぼ感じられないレベルです。

Q: Q5_0 量子化で精度は下がらないのですか?

Whisper の場合、5bit 量子化(Q5_0)は fp16 と比べて WER の上昇が 1〜2% 程度と非常に小さいです。モデルサイズを約 65% 削減しながら、実用精度は維持できます。

Q: Zoom・Google Meet・Teams でも使えますか?

使えます。ScreenCaptureKit はシステム全体の音声出力をキャプチャするため、Zoom・Google Meet・Teams・Slack ハドル・ブラウザ上の会議ツールなど、あらゆるアプリの音声に対応します。Bot アカウントや API 連携は不要です。

Q: 会議を録音・文字起こしすることに法的な問題はありますか?

日本では、会議参加者全員の同意なく録音することに関するルールが状況によって異なります。会社や組織のポリシー、および適用される法律に従って利用してください。Local Whisper はあくまで技術的なツールであり、利用に際しての法的責任はユーザー側にあります。

Q: Silero VAD は日本語音声でも機能しますか?

はい。Silero VAD は言語非依存の音声区間検出モデルです。発話しているかどうかを判定するだけで、言語の識別は行いません。日本語・英語・その他の言語を問わず同等に機能します。

Q: Intel Mac での動作速度は実用的ですか?

CoreML は Apple Silicon 専用のため、Intel Mac では CPU 推論のみになります。large-v3-turbo モデルではリアルタイム処理が難しい場合があります。Intel Mac をお使いの場合は、medium や small などの軽量モデルを試すことをおすすめします。

Q: OpenAI の Whisper API との違いは何ですか?

OpenAI Whisper API は音声データを OpenAI のサーバーに送信します。Local Whisper はすべての処理がローカルで完結し、データが外部に出ることはありません。また、Whisper API はバッチ処理のみですが、Local Whisper はリアルタイム文字起こしに対応しています。


まとめ

Apple Silicon Mac で無料・オフライン・プライバシー安全な文字起こし環境を構築するために実装した内容をまとめます。

  1. whisper.cpp + CoreML により、GPU なしでリアルタイムに近い推論速度を実現
  2. Silero VAD で無音区間を除去し、蓄積レイテンシを大幅に削減
  3. audio_ctx を 1500 → 750 に削減することで、精度をほぼ維持したまま Encoder 時間を半減
  4. ScreenCaptureKit で仮想オーディオデバイス不要のシステム音声取得を実現

この構成により、会話の両者の声をリアルタイムで文字起こしでき、完全ローカルで動作し、OSS ベースで中身を確認できるツールができました。

サブスクを避けたい方、音声データのプライバシーを重視する方、会議の文字起こしをクラウドに依存せず実現したい方に、ぜひ試してみていただきたいと思います。

GitHub: https://github.com/y-dai20/local-whisper

関連するブログ

この記事に近いテーマのブログをピックアップしています。