Whisper文字起こしアプリの作り方 — 録音から Word 出力までローカルで完結させる

アプリの作り方

Whisper文字起こしアプリの作り方 — 録音から Word 出力までローカルで完結させる

会議や取材の録音を、聞き直しながら手で打ち直す。あの時間が、何より惜しい。しかもクラウドの文字起こしは、音声をどこかへアップロードするのが気になる場面もある。録音から Word 出力まで、手元だけで完結させる。

目次
  1. このガイドで作るもの
  2. 手起こしの時間は、どこへ消えているのか
  3. 設計の起点:Whisper をローカルで動かす
    1. モデルサイズの選び方
    2. 入れられる音声の形式
    3. クラウド型サービスとの使い分け
  4. 作り方の要点
    1. 1. ローカル Whisper で文字起こしする
    2. 2. ハルシネーション(幻聴)対策
    3. 3. 重い処理は別スレッドへ逃がす
    4. 4. 入力デバイスは「選べる」ようにする
    5. 5. 結果を編集してから Word へ
    6. 6. 精度の半分は「録音の質」で決まる
    7. 7. 起こした後は、AIチャットに整形させる
  5. つまずきと対策
  6. 使用ライブラリと順守メモ
  7. まとめ

このガイドで作るもの

マイク録音や音声ファイルを Whisper でローカル文字起こしし、そのまま Word(.docx) に書き出す Windows デスクトップアプリ(CustomTkinter 製)。ネット接続なしで動き、結果はアプリ上で編集してから保存できる。

構成は役割ごとに分けてある。文字起こしは transcriber/whisper_engine.py、録音は audio/recorder.py、Word出力は exporter/docx_writer.py、画面は gui/app.py

手起こしの時間は、どこへ消えているのか

例えば1時間の会議録音を手で起こすと、再生時間の何倍もかかる。タイピングが速くても、実際の作業は「数秒聞く→止める→打つ→聞き逃して巻き戻す」の繰り返しで、再生1に対して作業3〜5倍は珍しくない。夕方の1時間会議が、翌日の午前を丸ごと食う計算だ。

文字起こしサービスを使えば時間は解決するが、今度は「音声を外部にアップロードする」ことが引っかかる場面が出てくる。社外秘の会議、取材相手との約束、家族の記録。内容がセンシティブなほど、時間の問題とプライバシーの問題が同時に立ちはだかる。このアプリは、その2つを一度に潰すための道具だ。

Voice Docs Converter のメイン画面
Voice Docs Converter のメイン画面。左でマイク録音かファイル読み込みを選び、右に文字起こし結果が出る。そのまま Word(.docx)やテキストに保存できる。Whisper はローカルで動く。

設計の起点:Whisper をローカルで動かす

精度とプライバシーを両立させるため、文字起こしは Whisper をローカル実行にした。クラウドに音声を送らずに済む。日本語なら small 以上が精度・速度のバランスが良く、GPU が無くても small で実用になる。モデルは初回使用時に自動ダウンロードされる。

モデルサイズの選び方

Whisper には大きさ違いのモデルが用意されている。パラメータ数と必要メモリは公式READMEの公表値だ。

モデル パラメータ 必要VRAMの目安 向き
tiny 3,900万 約1GB まず動かす・速度最優先
base 7,400万 約1GB 短いメモの下書き
small 2億4,400万 約2GB 日本語の実用ライン(このアプリの既定)
medium 7億6,900万 約5GB 精度重視・GPUがあるなら
large 15億5,000万 約10GB 最高精度・GPU前提

迷ったら small から。日本語は tiny/base だと誤変換が目立ち、medium 以上を CPU で回すと待ち時間が実用の線を超えやすい。small で全体を起こし、精度が足りない箇所だけアプリ上の編集で直す運用が現実的だ。

入れられる音声の形式

mp3 / wav / m4a など、一般的な音声はほぼそのまま入る。変換を裏で担っているのは ffmpeg で、Whisper は音声の読み込みに内部で ffmpeg を使う。「ファイルを読み込めない」系のエラーが出たら、まず ffmpeg が入っているかを疑うと早い(無ければ「Windows で ffmpeg を入れる手順」をAIに聞けば数分で済む)。スマホの録音(m4a)をそのまま投げ込めるのは、この仕組みのおかげだ。

クラウド型サービスとの使い分け

ローカル実行が常に正解というわけでもないので、線引きを書いておく。

  • ローカル(このアプリ)が向く … 外に出せない音声・毎月大量に起こす・ネットの無い環境。回数無制限でランニングコストがかからないのは、量が増えるほど効く。
  • クラウド型が向く … 非力なパソコンしか無い・話者の自動分離など高度な機能が欲しい・たまにしか使わない。処理を向こうのサーバーが担うぶん、手元の性能を問わない。

判断軸は「音声を外に出せるか」と「月に何時間ぶん起こすか」の2つ。出せない音声が1本でもあるなら、ローカルの選択肢を手元に持っておく価値がある。両方使い分ける形に落ち着く人も多い。

作り方の要点

1. ローカル Whisper で文字起こしする

モデルを読み込み、日本語指定で transcribe する。download_root を渡せばモデルの保存先を制御できる。

# transcriber/whisper_engine.py
import whisper

model = whisper.load_model("small", download_root=MODELS_DIR)   # 初回に自動DL
result = model.transcribe(
    audio_path, language="ja", verbose=False,
    condition_on_previous_text=False,      # ← 幻聴対策(後述)
    no_speech_threshold=0.6,
    logprob_threshold=-1.0,
    compression_ratio_threshold=2.4,
)

2. ハルシネーション(幻聴)対策

ここが地味に効く本題だ。Whisper は無音や短い音声で「ご視聴ありがとうございました」のような幻聴文を生成することがある。知らないと「謎の一文が混入する」と延々悩むことになる。対策は二段構え。

① パラメータで抑える(上のコード):condition_on_previous_text=False で直前テキストへの依存を切り、no_speech_threshold / logprob_threshold を調整する。

② セグメント単位で無音を捨てる:各セグメントの no_speech_prob(無音である確率)を見て、無音らしいものを結果から落とす。閾値 0.7 の調整方向も知っておくと迷わない。幻聴が残るなら閾値を下げて厳しくし、実際の発言まで消えるなら上げて緩める。会議のような「静かな間が多い録音」ほど幻聴は出やすいので、素材によってはここを触る価値がある。調整するときは同じ音声で before/after を見比べるのが確実だ。

# 無音由来の幻聴セグメントを no_speech_prob で落とす
parts = [
    seg["text"] for seg in result["segments"]
    if seg.get("no_speech_prob", 0) < 0.7
]
text = "".join(parts) if parts else result["text"]

3. 重い処理は別スレッドへ逃がす

文字起こしは時間がかかる。メインスレッドで走らせると GUI が固まる。別スレッドで実行し、UI更新はメインスレッドへ戻す(CustomTkinter/tkinter は after でマーシャリングする)。「固まらない」ことは、それだけで品質になる。

# gui/app.py — 重い transcribe は別スレッド、UI更新はメインへ戻す
def run():
    text = engine.transcribe(path)
    self.after(0, lambda: self._show_result(text))   # メインスレッドで反映

threading.Thread(target=run, daemon=True).start()

4. 入力デバイスは「選べる」ようにする

環境によっては既定の入力がミックス出力等になっていて、録音すると無音になる。sounddevice で入力可能なデバイスを列挙し、ユーザーが選べるドロップダウンを用意する。

# audio/recorder.py — 入力可能なデバイスだけ列挙して選ばせる
import sounddevice as sd

def get_input_devices():
    return [
        {"index": i, "name": d["name"]}
        for i, d in enumerate(sd.query_devices())
        if d["max_input_channels"] > 0       # 入力チャンネルがあるものだけ
    ]

# 選択したデバイスで録音(16kHz / mono)
stream = sd.InputStream(samplerate=16000, channels=1, dtype="float32",
                        device=device_index, callback=audio_callback)

5. 結果を編集してから Word へ

文字起こしは完璧ではない。結果をアプリ上で直してから python-docx で .docx に書き出す。日本語が化けないよう、東アジアフォントを明示設定するのがコツだ。

# exporter/docx_writer.py — 日本語フォントを東アジア設定して .docx 出力
from docx import Document
from docx.oxml.ns import qn

doc = Document()
font = doc.styles['Normal'].font
font.name = font_name
font._element.get_or_add_rPr().get_or_add_rFonts().set(qn('w:eastAsia'), font_name)

for line in text.split("\n"):
    doc.add_paragraph(line)
doc.save(output_path)

6. 精度の半分は「録音の質」で決まる

モデルをいくら大きくしても、元の音が悪ければ結果は崩れる。録音側で効く工夫は素朴だ。マイクを話者に近づける(会議ならテーブル中央へ)、エアコンや換気扇から離す複数人が同時に話す時間を減らす。コードで samplerate=16000, channels=1(16kHz・モノラル)にしているのは、Whisper が内部で16kHzに変換して処理するためで、最初からこの形式で録れば無駄がない。高音質48kHzステレオで録っても、精度は上がらずファイルだけ重くなる。

7. 起こした後は、AIチャットに整形させる

Whisper の出力は「話し言葉がそのまま文字になった」状態だ。えー、あのー、が混ざり、句読点も話し言葉のリズムで付く。ここからの整形は、AIチャットの得意分野になる。出力テキストを Claude や ChatGPT に貼り、「会議の議事録として整形してください。発言の要旨を保ち、フィラー(えー、あのー)を除去、決定事項とTODOを最後にまとめて」と頼めば、読める議事録まで一気に進む。ローカルWhisperで起こし、チャットAIで整える。この二段構えが、実務で一番速い組み合わせだ(機密の音声は起こすまでをローカルで完結させ、整形に出すテキストの中身は自分で判断する)。

つまずきと対策

  • 謎の一文が混入する:無音区間の幻聴。パラメータ調整+no_speech_prob でのセグメント除去で抑える。
  • 録音が無音になる:入力デバイスの取り違え。デバイス選択UIで明示的に選ばせる。
  • GUIが固まる:重い transcribe をメインスレッドで実行している。別スレッド+after でUIへ戻す。

使用ライブラリと順守メモ

  • openai-whisper … MIT ライセンス(コード・モデル重みとも)。モデルは初回に公式から各自ダウンロードされる。
  • その他の依存(CustomTkinter/sounddevice/soundfile/pydub/python-docx)は MIT・BSD 系、torch は BSD-3。
  • 録音・文字起こしする音声は、自身が権利を持つ、または録音・利用の同意を得たものに限ること(会議・通話の録音は相手の同意や各地域の法令に注意)。
  • 本アプリはローカル処理のため音声を外部送信しないが、出力した文書の取り扱いは利用者の責任で行う。

まとめ

土台は4つ。① ローカルWhisperで精度とプライバシーを両立② 幻聴はパラメータ+セグメント除去で抑える③ 重い処理は別スレッド+afterでUIへ戻す④ 入力デバイスは選ばせる。これらは音声を扱うデスクトップアプリの共通の足場として、そのまま使える。録音の質と後工程の整形まで含めて1本の流れにすれば、手起こしの時間は道具に置き換わる。


👉 関連: 開発実例:Voice Docs Converterほかのアプリの作り方

YouTubeトレンドのサムネイルを一括取得するツールの作り方 — Data API v3で集めて保存するYouTubeトレンドのサムネイルを一括取得するツールの作り方 — Data API v3で集めて保存する前のページ

バイブコーディングのやり方 — AIで「動くアプリ」を最後まで完成させる進め方を、実例7本で全部見せる次のページバイブコーディングのやり方 — AIで「動くアプリ」を最後まで完成させる進め方を、実例7本で全部見せる

ピックアップ記事

  1. 競艇予想AIの作り方 — LightGBMで「当たる順位」を学習させる実装ガイド…

  2. New Eden Intelligence Hub の作り方 — EVE Onl…

  3. 高精度OCRデスクトップアプリの作り方 — PaddleOCR-VLとPyIns…

  4. Claude Mission Control の作り方 — Tauri+Pyth…

関連記事

  1. Claude Mission Control の作り方 — Tauri+Python+MCPで複数AIエージェントを1画面に統合する

    アプリの作り方

    Claude Mission Control の作り方 — Tauri+Python+MCPで複数A…

    複数AIエージェントの会話・生成・成果物を1画面に統合するデスクトップ…

  2. YouTubeトレンドのサムネイルを一括取得するツールの作り方 — Data API v3で集めて保存する
  3. 日本語の文字起こし、Whisperより良いモデルはあるのか。測り方を3回間違えながら比べた記録
  4. 都市開発シミュを作る⑤|「面白くない」を目標・施設・イベント・音の4軸で解消【Aurum City制作】

    アプリの作り方

    都市開発シミュを作る⑤|「面白くない」を目標・施設・イベント・音の4軸で解消【Aurum City制…

    「面白くない」を4軸(目標・打ち手・変化・音)で解消する。都市ランクと…

  5. アプリの作り方

    Claude Codeのトークンを削るOSS 11本 — ライセンス本文まで確かめた一覧

    GitHubで「Claude Codeのトークンを削る」と名の付くリポ…

  6. 背景除去アプリの作り方 — PyQt6+ONNX(BiRefNet)でローカル完結の透過ツールを作る

注目

AIで、ここまで作れる

AIで作った2D RPGを、ブラウザでそのまま遊べます。その「作り方=最後まで完成させる進め方」も実例つきで公開中。

▶ ゲームを遊ぶやり方を読む

PR

お名前.com 独自ドメイン取得(PR)

独自ドメイン:お名前.com(本サイトで使用・PR)

  1. 高精度OCRデスクトップアプリの作り方 — PaddleOCR-VLとPyInstaller凍結の実践

    アプリの作り方

    高精度OCRデスクトップアプリの作り方 — PaddleOCR-VLとPyIns…
  2. 背景除去アプリを作る④|BiRefNetをONNXでローカル推論する — モデル別前処理とDirectML→CPUフォールバック【背景除去Studio制作】

    アプリの作り方

    背景除去アプリを作る④|BiRefNetをONNXでローカル推論する — モデル…
  3. Claude Code v2.1.214 で allow ルールの dir/** が「効かなくなる」— 棚卸しスクリプトと書き換えの判断基準

    AI・テック動向

    Claude Code v2.1.214 で allow ルールの dir/**…
  4. WordPress 7.0.1 と 7.1 の React 19 — 自作テーマ・プラグインを今から通す準備

    AI・テック動向

    WordPress 7.0.1 と 7.1 の React 19 — 自作テーマ…
  5. Grokで回すXメディア生成パイプラインの作り方 — 検索から画像・音声・動画まで自動化する

    アプリの作り方

    Grokで回すXメディア生成パイプラインの作り方 — 検索から画像・音声・動画ま…
PAGE TOP

TAG CLOUD

ドラッグで回転・クリックでそのタグの記事一覧へ