🎤

superwhisperを自作して格安の音声入力環境を構築した

に公開

はじめに

こんにちは!株式会社ispecでEMをしているshinyaです。

最近、仕事でもプライベートでも生成AIを使う機会が増えてきたので、ChatGPTやcursorを触らない日はないんじゃないか、くらいの感覚があります。

そんな中で強く感じているのが、インプットの質と量が、生成AIのアウトプットに直結するということです。
こちらが何をどう伝えるかによって、返ってくる答えの精度や使いやすさが全然変わってきますよね。

ただ、しっかりとしたインプットを作ろうとすればするほど入力にかかる労力が大きくなるので、例えばコーディングの場合だと 「これ結局自分で書くのと変わらなくね?」 と感じる場面にも度々遭遇していました。

そんな、生成AIの精度は高めたいけど入力は楽にしたい、という矛盾する欲求を満たすための方法を探していたところ音声入力という選択肢に行き着いたので、今回は格安で音声入力を利用する方法をご紹介します!

既存の音声入力サービス

音声入力って実際どうなんだろう?と思って調べていたときに、superwhisperというサービスを見つけました。

https://superwhisper.com/

実際に導入してみたところ音声認識の精度も良く、個人的な感覚としては圧倒的に音声入力の方がキーボード入力と比べて気軽に使えました。
その結果として、キーボードで入力をしていた頃は 「まぁこのぐらいはAI側でくみ取ってくれるだろう」と思って省略していた部分 も、漏れなく生成AIのインプットとして渡せるようになった感覚が得られました。

ただ、superwhisperは月額1,000円ほどの有料サービスで、サブスクの解約忘れをしがちな僕としては料金部分を不安視していました...
普段使っているcursorやclaudeなどが今後標準で音声入力をサポートする可能性もあるよなぁと思うと、「今すぐサブスク契約するのはちょっともったいないかも」という気持ちがありました。かといって、音声入力の快適さからはもう戻れない体になってしまっている...

superwhisper以外のサービスも調べてみたのですが、質とコストの面からあまりハマるものはなく途方に暮れていたところ、 「なら作っちゃえばいいか...!」 という脳筋すぎる閃きをしてしまったのがことの始まりです。

作ったものの概要

今回は個人用途での利用なので、まずは自分が求める要件をざっと洗い出しました。

  • 料金は従量課金制が良い
  • キー操作をトリガーとして起動して欲しい(個人的には option + space の組み合わせ)
  • 音声を入力として、文字起こし文字列がクリップボードにコピーされて欲しい

上記のような必要最低限の機能だけであれば、意外とシンプルな構成で実現できそうでした。

💡 全体構成

全体の構成としては、以下のような流れになります。

キー操作のトリガーには Karabiner-Elementsを使い、それに応じて Automator(Macの標準アプリ)を呼び出します。

Karabiner-Elementsにはcomplex modificationという機能があり、特定のキー入力をトリガーとしてアプリを開いたりshellスクリプトを実行したりすることができます。

今回は以下のような設定で、Automatorで作成したアプリを呼び出すような状態としています。

karabiner.json
{
    "description": "自作whisperを実行して、話した内容をクリップボードに保存する",
    "manipulators": [
        {
            "from": {
                "key_code": "spacebar",
                "modifiers": { "mandatory": ["option"] }
            },
            "to": [{ "shell_command": "open {{YOUR_PATH}}/WhisperLauncher.app" }],
            "type": "basic"
        }
    ]
}

Automatorでシェルスクリプトを呼び出し、シェルスクリプト内で録音をした後に文字起こし処理を書いているpythonのスクリプトを実行、そして結果をそのままクリップボードに保存する、という流れです。

なお、録音にはsoxというshellスクリプトで呼び出せるツールを利用しており、文字起こしにはopenAIのwhisperという音声認識モデルを利用しています。

技術的な構成と詰まったポイント

最終的に出来上がった構成はシンプルですが、実際に作っている中で地味にハマりポイントがいくつかありました。
中でも一番詰まったのは「Karabiner-Elements 経由で起動したスクリプトではマイクが使えない」という問題です。

最初は、Karabinerで直接シェルスクリプトを呼び出して、その中で Python を動かせばいけるだろうと思っていたんですが、いざ録音をしようとするとマイクの入力が許可されないという壁にぶち当たりました。

🤖 CLIからのマイク録音はセキュリティ的にNG?

Macでは、マイクやカメラの使用に対して明示的な許可が必要です。
通常であれば、アプリを初めて使うときに「このアプリにマイクを許可しますか?」と聞かれるやつですね。

ところが、Karabiner経由で呼び出すスクリプトはCLIであるためマイクの使用許可を出すためのGUIが出てこず、無音で録音され続けてしまう問題が発生しました。

💡 Automatorを使ったアプリ化で解決

いろいろと調べた結果、Automatorを使えばシェルスクリプトを「アプリ化」できるという情報にたどり着きました。

↓Automatorの使い方で参考にさせていただいた記事↓
https://qiita.com/takatoshi0905/items/0a4abf3e1ecd483db911

Automatorでアプリ形式にすれば、macOS側でアプリとして認識され、マイクの使用許可も GUI 経由で出せるようになるようです。

automatorで実行しているshellスクリプト.sh
#!/bin/bash

# OpenAI APIキーを設定
export OPEN_AI_API_KEY="{{OPEN_AI_API_KEY}}"

cd {{PROJECT_ROOT}}

touch sox_test.log
echo "録音テスト開始 $(date)" >> sox_test.log
# 録音テスト(静音が3秒続くと録音が終了する)
/opt/homebrew/bin/sox -d -c 1 -r 16000 -b 16 audio.wav silence 1 0.1 1% 1 3.0 1%
echo "録音テスト終了 $(date)" >> sox_test.log

# 録音ファイルをwhisperで文字起こし
{{UV_ROOT_PATH}} run main.py

(shellスクリプトにある通り、現状だと3秒間無音状態が続くと録音が終了する処理となっています)

まとめと今後の展望

というわけで、格安で音声入力を利用する方法をご紹介してみました。
今回の構成だと文字起こしモデルのwhisperのみ料金がかかっているのですが、料金体系としては大体1時間50 ~ 60円程度なので、かなり気軽に使える体制にできたのではないかと思っています!

まだまだプロトタイプ的な感じでもっと体験をよく出来る場所はたくさんあるので、

  • 録音の終了ロジックを見直す(無音3秒 → キー操作で明示的に終了したい)
  • GUIを用意してもう少し使いやすくする
  • 文字起こしを綺麗な状態に整形してクリップボードにコピーする

などを余裕があるときに追加していけたらと考えています。(これらの機能はsuperwhisperに標準搭載されているので、やはりサービス自体の質は高いと感じられますね)

今回作成したアプリのrepositoryは以下になるので、ご興味がある方は導入してみていただけると...!
https://github.com/mokoshin0720/whisper-launcher

趣味開発ではありましたが、自分の生活を快適にするツールを自分で作るというのはカスタマイズ性が無限大なので夢が広がる感じがして楽しいですね🤘

おわりに:採用情報

ispec では更なる事業拡大を見据え、エンジニア職にて新しいメンバーを募集しています。
採用サイトでは各求人の詳細だけでなく、ispec で大切にしている価値観や、メンバーの紹介記事も掲載しております。

  • 技術へのこだわりやプロダクト愛を活かして働きたい
  • フルリモート、フルフレックス下で最大限のバリューを発揮したい
  • 心理的安全性の高い環境の中、チームで成果をあげてみたい

そんな思いを持った方がいらっしゃいましたら、ぜひ一度カジュアルにお話ができたらと思います。

ispec inc.

Discussion