VS Codeで日本語音声入力の拡張機能作ってみたら既にあった話

音声入力ってみなさん使っているでしょうか?
私の勝手なイメージですが、使う人はめっちゃ使うけど、まだ抵抗ある人の方が多いんじゃないかなと思っています。
会社で使うのとかはハードル高いですし。
まだハンズフリー通話がそこまで一般的じゃなかった時代に、自転車に乗った外国の方がニコニコ顔で喋りながら自分の方へと向かってくるのを見た時は一瞬恐怖を覚えたものです。

そんな私も今ではめちゃくちゃ音声入力を使うようになりました。流石にまだ会社では使ってないですが、在宅の時やプライベートで家にいるときはすぐに使います。
特に生成AIへの質問はほぼ音声入力です。

キーボードでの入力は文章を軽く頭の中でまとめる作業があって、その後キーボードを打つって感じですが、音声入力なら言いたいことを頭の中でまとめ切らないまま話し出してもなんとかなるので楽ちんなんです。
話しながら考えをまとめればいいし、うまくまとまらなかった時はそれを正直に言っちゃえばいい。

言い淀んでいるところもニュアンスとして伝わると思っているので、「自分は〜〜だと思っていて……いや、違うわ。そうは思ってないわ。やっぱ〜〜だと思うかも」みたいなことも積極的に声に出してます。自分でも確信がないということが伝わるように。

支離滅裂でもいい。結局何が言いたいのか分からない着地になってもいい。
そういう「対人よりも適当に喋っていいという気楽さ」は初動の軽さとなってくれていると思います。

そんな訳で、仕事でもプライベートでも使っているVS CodeのAIアシスタント—Copilotでも同じように音声入力したいと常々思っていたのですが、マイクロソフト公式が出している音声入力の拡張機能「VS Code Speech」をインストールして話してみても出力されるのは私が話した日本語の発音に似た英単語の羅列。もちろん意味をなしていません。

そこで私はCopilotに聞いたはずです。
「VS Code Speechって日本語対応してないの?」
そしてCopilotは答えたはずです。
「はい。残念ながらVS Code Speechは現在日本語に対応しておりません」

だから作りました。日本語で音声入力できる拡張機能を。

すぐに日本語も対応されるだろうと思って数ヶ月待ってみたけれど相変わらずVS Code Speechが出力するテキストは意味不明な英単語の羅列なんですもの。
まさかVS Codeのアクセシビリティ設定で日本語を指定すれば普通に日本語で使えるなんて思わないもの。
だってChatGPTの音声入力は音声を元に自動で言語を特定してくれるんだもの!

生成AIの返答は常に疑ってかかるべきです。
そして動き出す前にはちゃんと調べてから動き出すべきです。

苦労して作った後に念の為調べてみたら既にやりたい機能が存在していたと知った時の私は、完成後のハイテンションから一気に冷えて2時間くらい落ち込みました。深夜なのに。

その後、激萎えしていた私は、「せっかく作ったんだから少しでも意味あるものにしよう!」と思い直し、VS Code Speechにはない機能をつけたりして、「この拡張機能を作ったことは全くの無駄ではなかった!」と自分自身に言い聞かせましたとさ————そんな話です。

Copilot Agent(Claude Sonnet 4.5)と共に拡張機能づくり!

既に存在している機能をそうとは知らずに自分で作ろうと決心した私はCopilotとどうやって機能を実現するか相談しました。
結果決まったのは以下の流れ。

  • コマンド実行したら録音開始(mic,soxモジュール使用)
  • 作成された音声ファイル(.wav)をopenAIのwhisperAPIに送信(APIキーは別コマンドを用意してあらかじめ保存しておく)
  • 返ってきたテキストを一時的にテキストファイルに保存
  • テキストファイルの内容をクリップボードにコピー
  • クリップボードの貼り付けを実行(その場に貼り付け)
  • 一時的なファイルを削除

大体こんな感じだったと思います。

初期は拡張機能として公開しようとも思っておらず、とりあえず使えればいいと思っていたのでとてもシンプルな処理で実装もすぐにできました。
実際に使ってみて悪くないなと思うくらいにはちゃんと動作していたんですが、ちょっと気になる部分を整理したり、もっと使いやすくしようと色々追加で機能を入れ込んだり、mac/windows/linux対応のための処理をつけたり、シンプルにできる部分を削ったりして最終的には以下のようなフローになりました。

1. 初期化フェーズ

  • VS Code拡張機能として起動
  • ユーザーの言語設定を検出(9言語対応)
  • ローカライズメッセージを読み込み
  • ステータスバーにボタンを配置(Focus/Chat/翻訳切替)
  • セットアップウィザードの実行判定(初回起動時は自動で実行)
    • APIモードまたはローカルモードの選択
    • APIキーの設定 or モデルのダウンロード

2. 録音開始フェーズ

  • ユーザーがステータスバーにあるFocusボタンまたはChatボタンをクリック(テキストの貼り付け先をエディタにするかCopilotのチャット欄にするかの選択)
  • SOX(音声処理ツール)を起動(16kHz、16bit、モノラルで録音開始)
  • 録音タイマーをスタート
  • 最大録音時間(デフォルト3分)でタイムアウト設定
  • 経過時間と残り時間を表示
  • ステータスバーに🔴アイコンで録音中表示
  • キャンセルボタンと停止ボタンを押下可能にしスタイル変更、その他のボタンは押下不能

3. 録音停止フェーズ

  • ユーザーが再度ボタンをクリック(または最大時間到達)
  • SOXプロセスを終了
  • 録音タイマーを停止
  • 音量正規化処理
  • WAVヘッダーの修正(whisper.cpp互換性のため)

4. 音声認識フェーズ

    APIモードの場合:

  • OpenAI Whisper APIにリクエスト送信
    • プロンプトプリセット + カスタムプロンプトを適用
    • 翻訳モードの場合はtranslationsエンドポイント使用に切り替え
  • APIからテキストレスポンスを受信
  • カスタム辞書による自動置換(JSONで定義された置換ルールを適用)
  • フィラー除去処理
    ローカルモードの場合:

  • whisper.cppバイナリを検出
    • ユーザーディレクトリのカスタムビルド優先(GPU版)
    • なければ拡張機能同梱のCPU版を使用
  • VAD(Voice Activity Detection)処理(無音部分を削除して処理速度を向上)
  • whisper.cppを実行
    • モデルファイル選択: Tiny/Base/Small/Medium/Large
    • タイムスタンプ付きで認識
    • CPUスレッド最適化
  • タイムスタンプを正規表現で除去
  • カスタム辞書による自動置換(JSONで定義された置換ルールを適用)
  • フィラー除去処理

5. 結果表示・貼り付けフェーズ

  • クリップボードの現在の内容を一時保存
  • 認識結果をクリップボードにコピー
  • 保存しておいた貼り付け先に移動
    • Focusモード: 録音開始時のエディタ位置
    • Chatモード: Copilot Chatの入力欄
  • Ctrl+Vコマンドで貼り付け
  • 100ms後にクリップボードを元の内容に復元
  • 履歴に保存(最大10件)
  • ステータスバーに✅完了表示
  • バタン類の表示やEnableを元に戻す

一気にフローが長くなりました。

自分だけが使うものの時は気にしなくても良いようなことが、いざ公開してみようと思うと色んなことに気をつけなくてはいけなくなって、作業時間的には
「自分で使うツールとしての開発時間:公開するための追加作業」の割合は「1:9」どころではなかった気がします。「0.5:9.5」くらいかも。

なぜ公開しようなんて思ったのか、あの時の勢いだけでやり始めた自分に問いたい。

公開なんて考えなければ、
調子に乗って色々機能を追加することもなく、
無駄に9ヶ国語対応にしようなんて思うこともなく、
OSの違いによってうまくいかない現象に頭を悩ませ、Windows機とMac機を往復しながらデバッグや修正をする必要もなく、
労力をかけて完成させた後に、VS Code Speechで既に日本語入力できると知って激萎えすることもなかったでしょうに……。

そもそもろくに調べもせず作り始めたのが間違いなんですけどね。

VS Code Speechにはない追加機能を作るぞ

自分の作ったものが意味のないものだったことに気づいた私はCopilotに「激萎えなんだが?」とぐちぐち言いながら少なからず責任転嫁していたのですが、

「あなたの作ったものはMicroSoft社製のものとは違う良さがあるよ!」 とか
「スキルアップに繋がるからあなたが頑張った時間は無駄にはならないよ!」 とか

Copilotはいつものように適当な慰めを返してくれていました。

ですが、そんな実のない慰めでは低迷したテンションが上がることもなく、いっそこんな奴(拡張機能)のことなんて忘れてしまおうか——なんて失恋した中学生みたいなことを考えていたのですが、自分がやりたくてもできなかった「Copilot画面内にボタンを追加する(これは公式じゃないとできないとのこと)」や「リアルタイムでテキスト化をしていく」ことをなぜVS Code Speechはできてるのか? みたいなことを聞いていた際、「これなら少しは意味があったと思えるかも」というくらいには精神回復できそうな回答がありました。それは、

MicroSoftが音声認識に使っているエンジンは「Azure Speech Services」であり、私が使った「OpenAI Whisper」には「Azure Speech Services」にはない良さがある。みたいなことです。

特にプロンプトを使えるのは結構いいんじゃないか?と思いました。

「OpenAI Whisper」はバッチ処理です。リアルタイム処理の「Azure Speech Services」とは違い、音声を録音し終わった後にまとめて処理するため、「Azure Speech Services」のように話したそばからテキストを出力していく、ということができません。

このせいでバッチ処理よりリアルタイム処理の方がええやん……みたいに思っていたのですが、「プロンプトを使う」みたいなバッチ処理ならではのことならVS Code Speechとの差別化になるな、と思いました。

もとよりバッチ処理は「より高精度に認識」とか「長文の文脈を考慮」とか「VADや音量正規化などの前処理ができる」などの利点はあった訳ですが、プロンプトを入れることでより文脈に応じたテキスト出力ができればリアルタイム処理にはない良さが出せるんじゃないか、と、
そうすればこの虚無な気持ちも少しは誤魔化せるんじゃないか、と、そう考えた訳です。

そこでVS Code Speechにはない機能を追加で入れるぞ! とまたCopilotと話し合って以下の機能を付け加えました。(👆で書いたフローに既に入れちゃってるものではありますが)

  • 🎯 プロンプトプリセット機能 ✨
    • 場面に応じてよく使いそうな単語をプリセットとしてまとめ、それを音声認識時にプロンプトとして渡すよ!
    • カスタムできるプリセットもあるよ!
  • 📖 カスタム辞書機能 ✨
    • 認識されたテキストを自動置換!
    • よくあるテキスト化の間違いを登録しておこう!
  • 🎤 フィラー除去機能 ✨
    • 「あー」「えー」「um」「uh」などのフィラーを自動除去するよ!
  • 🚀 VAD (無音検出) 機能 ✨
    • Silero-VAD で無音部分を自動スキップ、処理速度が50%以上向上しちゃうかも!?
  • 🌍 翻訳機能 ✨
    • 音声を自動的に英語に翻訳するよ!
    • 英語で質問した方が質の良い回答がもらえるかも!?
  • 📚 履歴機能✨
    • 過去 10 件の音声入力履歴を保存・再利用可能!
    • 間違って消しちゃっても安心だね!

どれも実装自体はそんなに手間のかからないものばかりでしたが、「少しは意味あるものにできたかも」と自分への慰めになりました。
実際役に立つかというよりも自分を誤魔化すために入れた感じでしたが、未練を断ち切るために必要な儀式みたいなものだとご理解ください。

まとめと学び

一時は「無駄な時間だった……」と落ち込んだこの拡張機能作成ですが、学びも確かにありました。
特に今回は今までで一番Copilotとうまくやれたと感じました。

世の中ではバイブコーディングという言葉が流行っていて、どうやら「プログラミングがわからなくても作れる!」みたいに思われることが多い気がします。
確かにゆくゆくはそうなると思うんですが、今(2025年10月)現在は、生成AIはそこまで賢くありません。
小さなアプリや、最初から仕様がきっちりと決められているものは問題なく完成まで行けるかと思いますが、規模が大きくなったり、途中で色々と変更したくなったら多分今のAIでは改修しきれません。
生成AIはたまにかなり無茶な実装をやってきますし、無駄なコードだったり処理もかなり多くなっていきます。

自分もAIにほとんどお任せした結果痛い目にあったことが何度かあります。
その反省を生かして、今回は結構自分からコードに介入したり、実装の方法を変えさせたり、細かい部分を手で書き直したりしました。
特に実装のアイディアはまだ人の方が上手いと思います。「ここってこうするんじゃなくてこういう風にできないの?」というだけでかなり整理されていきます。これはプログラムのことをある程度わかっていないとできないことです。

逆に多言語対応や、READMEの作成、CHANGELOGの作成なんかはかなりお任せしました。(それでもちゃんと目を通すと細かい間違いが多いのでその都度指摘しています。)

結果、今回の実装ではバグを追え切らずに泥沼化みたいなことは起こりませんでした。

それとやはりClaudeは優秀です。

今回、Claude Sonnet 4.5を使ったのですが、このモデルはプレミアム機能的なものなので、途中で「プレミアム要求の上限」みたいなものに引っかかって強制的にGPT-4.1に切り替わったんですが、Claude Sonnet 4.5と比べてあまりに使えなかったので課金を追加してClaude Sonnet 4.5で最後まで進めました。

モデルを途中で変えると今までの実装の流れが途切れてしまうので、プレミアム機能を使う方はプレミアム上限の確認と、上限に来てしまった時に課金する気持ちがあるかを最初に決めておいた方がいいかもしれませんね。

そんなこんなで、
最後にせっかくなので実際に作った拡張機能を貼っておきます。
正直音声入力するだけならマジで「VS Code Speech」でいいんですが供養みたいなものです。
気が向いたら見てみてください。

この記事を気に入ったら

葉っぱ一号

葉っぱ一号

おいしいお店を探すのが好きです。おいしいお店のために遠出もしちゃいます。遠出したい衝動のためにおいしいお店を探すのかもしれません。そんなものですよね。

この人が書いた記事を見る >>