メインコンテンツへ移動 / Skip to main content

nobetsuを作った──日本語音声入力が止まらないためのIME迂回と差分注入【開発記】

日本語を話しながら直接入力するだけならmacOS標準でもできる。それでもnobetsuを作った理由は、長文で詰まりやすいIMEとライブ変換を迂回し、変換済みの未確定文を安全に差分注入するためだった。全ソースを公開した設計を実測と図解で解説する。

日本語の音声が途切れずMacへ流れ込む様子を描いたnobetsuのAI生成イラスト
一般
公開日: 2026年8月23日
読了時間: 13
著者: ぽちょ研究所
読了時間: 13

1. 結論:日本語で「のべつ幕なし」に話せる音声入力を作った

nobetsu(のべつ)は、macOS 26以降のApple Silicon Macで動く、日本語専用の音声入力アプリである。⌘を0.5秒押して離す。すると手をキーボードから放したまま、話した端から、いまカーソルがあるアプリへ文字が入っていく。もう一度⌘を軽く叩くかESCで止まる。

先に境界線を引いておく。日本語を話しながらカーソル位置へ直接入力すること、起動後にキーを押し続けなくてよいこと、無料で使えることは、macOS標準の音声入力ですでにできる。 Apple Silicon Macでは音声入力中もキーボードを併用でき、30秒の無音で自動停止するものの、話し続けているセッションに固定の分数上限は案内されていない。[11] nobetsuは、この基本体験を発明したアプリではない。

それでも別に作った理由は、日本語の長文で詰まりの原因になったIME/ライブ変換の経路を通さず、変換済みの未確定文を自前の差分アルゴリズムで対象アプリへ入れるためである。さらに、その迂回路、差分修正、安全停止の実装と計測を、読めるソースとしてすべて公開した。ここがnobetsuの新規性であり、この記事の中心である。

押している間だけ録音するプッシュ・トゥ・トークではない。停止後に全文をまとめて貼るボイスメモでもない。話し続けている最中に、変換済みの日本語が対象アプリへ入り続ける。アプリ側に時間制限は設けていない。 音声認識は端末内で完結し、アカウントも外部APIキーも要らない。コードはMITライセンスでGitHubに公開した[1]

名前は「のべつ幕なし」から取った。芝居で幕を下ろさず演じ続けること、転じて絶え間なく続くこと。欲しかった体験を、そのまま名前にした。

26秒の実演。⌘を離した後も、話した端から対象アプリへ日本語が入る。動画はGitHubリポジトリでも公開している。

このプロジェクトで面白いのは、音声認識モデルを一から作ったことではない。AppleがmacOS 26で開放した部品を使いながら、日本語入力の詰まりやすい経路だけを外し、未確定文字を安全に他アプリへ同期する小さな機械を組んだことにある。

2. なぜ作ったのか:欲しかったのは「録音」ではなく、思考の通り道だった

長いプロンプトや設計メモをAIエージェントへ渡すとき、頭の中ではもう次の文ができているのに、指が追いつかない。音声なら速い。しかし既存の体験には、どこか一つ引っかかりがあった。

  • macOS標準の日本語音声入力では、長く話すほど認識結果とライブ変換が同じ未確定文を更新し続け、変換表示が追いつかず詰まる現象を実際に経験した。
  • 多くのAIアプリ内マイクは、一回の入力時間や無音判定に区切りがある。
  • 海外の音声入力アプリには、キーを押している間だけ録音し、離した後に全文を貼る設計が多い。
  • 長文用のハンズフリーがあっても、停止するまで入力欄には届かない製品がある。

これらは不具合というより、目的が違う。録音をきれいな文章へ整えてから貼るなら、停止後の一括処理は合理的である。会議の文字起こしなら、対象アプリへ一文字ずつ入れる必要もない。

欲しかったのは、もっと地味で、もっと直接的な道具だった。ひらめいた順に話し、その場の入力欄へ文章を育て、必要なら途中でEnterを押して送信し、そのまま続きを話す。 売るために機能を増やすのではなく、自分が毎日使う摩擦だけを削った。

文章を作るための通常ウィンドウやDockアイコンは持たず、待機中はメニューバーの波形アイコンに収まる。ただし「画面要素が何もない」わけではない。認識中は小さなカプセル型の目印が浮かび、赤い脈動と声量バーでマイクの状態を示す。そこから一時停止、マイクによる再開、設定、終了を操作でき、目印はドラッグして移動できる。必要な人は、認識中の文字を画面下部へ流すオーバーレイも有効にできるが、入力先と重なりやすいため既定では切ってある。設定全体はメニューバーから開く。依存ライブラリはゼロで、SwiftとOS標準フレームワークだけに絞った。

3. 類似アプリは世界にいくつあるのか:固定の総数より「方式」を数える

音声入力アプリには公的な製品台帳がない。App Store外の配布、GitHubの個人開発、会議文字起こしとの兼用、改名や終了があるため、「世界に何個、日本に何個」と固定値を断言するのは不正確だ。

そこで2026年8月23日、macOSでカーソル位置へ音声入力できることを公式情報で確認できた代表的な第三者製品9件を調べた。海外発7件(Superwhisper、Wispr Flow、Willow、Aqua Voice、VoiceInk、MacWhisper、TypeWhisper)、日本発2件(KoeType、いきなりAI 音声タイピング)である。これは市場総数ではなく、方式の違いを見るための標本だ。Apple標準音声入力は別に基準として置いた。[2][3][4][5][6][7][8][9][10]

方式確認できた代表例長文時の主な体験nobetsuとの違い
OS標準の直接入力macOS標準音声入力日本語対応、ハンズフリー、話しながらカーソル位置へ直接入力、無料基本体験はnobetsuと同じ。違いはIME/ライブ変換の経路を選べず、実装が公開されていないこと
押して録音、離して貼るSuperwhisper、Willow、KoeTypeなどまとまった文章を整えてから挿入話している最中の入力欄を育てない
ハンズフリー、停止して貼るWispr Flow、Willow手は自由だが完了まで本文は未挿入。Flowはデスクトップ20分上限nobetsuは途中から直接入り、アプリ側の時間上限なし
リアルタイム型Aqua Voice、いきなりAI 音声タイピング、MacWhisperなど話しながら表示・入力を訴求日本語IME迂回と未確定差分の実装は公開情報で確認できない
エンジン選択・ワークフロー型VoiceInk、TypeWhisperローカル/クラウド、LLM整形、履歴など多機能nobetsuは日本語の連続直接入力だけへ意図的に狭い

日本語対応そのものは、もう珍しくない。Whisper系の多言語モデルや商用サービスが日本語を扱い、国内製品も現れた。何よりmacOS標準音声入力が、日本語、ハンズフリー、発話中の直接反映、無料という主要な体験をすでに満たしている。したがって、これらをnobetsu固有の新機能として数えるのは誤りである。

nobetsuが新しく作ったのは、機能一覧ではなく入力経路である。第一に、変換済みの日本語を受け取り、CGEventのUnicode入力でIMEとライブ変換を丸ごと迂回する。 第二に、確定を待たず未確定文を先に見せ、認識が過去を書き換えたら最長共通接頭辞を使って変化した末尾だけ直す。この二つを、安全停止まで含めて全ソース、テスト、実測とともに公開した。今回確認した製品の公開資料では、この組合せを実装として追える別例は見つからなかった。競合より機能が多いのではなく、標準音声入力で残った日本語固有の詰まりだけを、細く深く解いたのである。

4. 日本語だけにある難所:認識の後ろに、もう一つ「変換」がある

英語の音声認識が good morning を返せば、それはほぼそのまま入力できる。日本語では音から「きょうははしで…」のような読みを得た後、文脈を見て「今日は箸で」「今日は橋で」などを選ぶ必要がある。通常のキーボード入力では、この役目をIMEが担う。

Appleの日本語入力には、ひらがなを入力するそばから文脈に合う漢字かな交じり文へ書き換える「ライブ変換」がある。[12] 短い入力では便利だが、長い音声入力では別の動きが重なる。音声認識も、後続の音を使って直前の推定を更新する。IMEも、伸び続ける未確定文を見て漢字や文節を組み替える。二つの“後から書き直す仕組み”を直列につなぐと、同じ未確定領域を追いかけ続ける。 nobetsuの開発環境では、この経路で変換が追いつかず、連続入力が詰まる現象を観測した。これは「標準音声入力に直接入力機能がない」という問題ではない。直接入力はできるが、日本語の変換経路が長文に耐えなかったという問題である。

複雑な日本語変換経路を避けて音声からMacへ直接届く流れを表現したAI生成イラスト

認識器とIMEの両方に未確定文を持たせない。変換済みの日本語を受け取り、最後の注入だけをnobetsuが管理する。

nobetsuはIMEを速くしようとはしなかった。その工程を通らない。 macOS 26のSpeechAnalyzerへマイク音声を渡し、DictationTranscriberから漢字かな交じりの日本語を受け取る。それをCGEvent.keyboardSetUnicodeStringでUnicode文字列として対象アプリへ送る。AppleのAPIは、仮想キーから通常行われる文字変換をUnicode文字列で上書きできる。[13][14][15]

text
通常の考え方
マイク → 音声認識 → 読み/未確定文 → IMEで再変換 → 対象アプリ

nobetsu
マイク → AVAudioEngine → SpeechAnalyzer + DictationTranscriber
      → 変換済み日本語 → 辞書置換 → CGEvent Unicode → 対象アプリ
                                     (IMEを通らない)

AppleはSpeechAnalyzerを長時間・遠距離音声、会議や講義にも向くオンデバイスAPIとして紹介している。未確定のvolatile resultと、後から変わらない確定結果を非同期に返せる。nobetsuはこの新しい部品を「録音の文字起こし」ではなく、「どのアプリにもつながる日本語入力装置」に組み替えた。[13]

5. 音声から一文字が届くまで:小さな処理を順番どおりにする

開始から入力までの流れは次の通りだ。

  1. CGEventTapが⌘単独の0.5秒長押しを検知する。⌘を押している間に別キー、クリック、ホイールが来たらショートカットと判断して取り消す。
  2. マイクと音声認識の許可を確認し、ja-JPDictationTranscriberを準備する。
  3. AVAudioEngineの入力を、SpeechAnalyzerが求める形式へAVAudioConverterで変換し、AsyncStreamへ流す。
  4. 認識器は同一区間について、変化する未確定全文と確定全文を返す。句読点、遠距離集音、頻繁な確定を有効にしている。
  5. 個人辞書を長い規則から適用する。「苦労してくる」を「Cloneしてくる」のように、認識としては自然だが用途では困る語を直す。
  6. 前回すでに入力した未確定全文と比較し、変わった末尾だけをBackspaceとUnicode入力で更新する。
音声をMacの中で処理し、対象アプリへ文字として届ける流れを表現したAI生成イラスト

音声の取得、端末内認識、辞書、差分注入を小さく分離する。各段階の役割を一つに混ぜないから、遅延や不具合の場所を追える。

開始音を鳴らす順番にも理由がある。先に音を鳴らしてからマイクを起こすと、人は合図と同時に話し、先頭が欠ける。そこでnobetsuはマイクが本当に動いた後、Bluetooth機器の切替を0.25秒だけ待って開始音を鳴らす。停止時は逆に、認識の後始末より先に入力の門を閉じ、マイクのtapを外し、engineをresetし、インスタンス自体を捨てる。標準音声入力とマイクを奪い合わないためである。

6. 確定を待たない:楽観的に入力し、変わった末尾だけ直す

SpeechAnalyzerの未確定結果は、追記だけではない。後続の音を聞いて過去の語を修正する。たとえば同じ区間が次のように届く。

text
1回目  今日は音声にゅう
2回目  今日は音声入力を
3回目  今日は音声入力を試します。

毎回全文を貼れば重複する。毎回全文を消して打ち直せば、ちらつき、打鍵渋滞、誤削除が起きる。そこで前回と今回の最長共通接頭辞を求める。

text
前回: 今日は音声にゅう
今回: 今日は音声入力を
共通: 今日は音声

操作: 末尾「にゅう」だけ3文字削除 → 「入力を」だけ挿入

認識結果は毎秒4〜5回ほど届くため、反映は0.25秒に一度へ絞る。SwiftのCharacter単位で差分を数えるので、絵文字や結合文字をバイト数と取り違えて余分に消さない。一方、CGEventへ送るときはUTF-16へ変換し、一イベント16単位に分割する。長すぎるイベントを取りこぼすアプリがあるためだ。

連続する日本語の一部だけを精密に交換する機構を表現したAI生成イラスト

全文をやり直さず、安定した前半は触らない。変化した末尾だけを最小限に交換するから、未確定でも文字を先に見せられる。

この方式はデータベースの楽観的更新に近い。「いま見えている推定を先に出し、前提が変わった場所だけ直す」。確定を待つより速く、全置換より穏やかである。

7. 本当に難しかったのは認識ではなく「人の文章を壊さない」こと

差分計算だけなら短い。しかし対象は自分のテキスト領域ではなく、Slack、ブラウザ、エディタなど他アプリの入力欄である。利用者は音声入力中にもEnter、Shift+Enter、クリック、手入力をする。そこへ古い差分を当てると、人が書いた文字までBackspaceで消してしまう。

nobetsuは、次のように安全側へ倒す。

  • 手入力・クリックを検知したら基準を捨てる。 次の未確定全文が直前の文章で始まる場合だけ、続きを重複なく再開する。つながらなければ、その区間は諦める。
  • Enterは0.12秒預かる。 nobetsuが直前に投げた1〜2文字を先に到着させてからEnterを再送し、送信後の空欄に「。」だけ残る競合を防ぐ。
  • 送信済み文章は“画面にはない仮想接頭辞”として守る。 認識器が後から過去を書き換えても、送信済みの場所へBackspaceしない。
  • Shift+Enterは改行として区間を切らない。 チャットの送信と文章内改行を分ける。
  • 停止後の遅い確定結果は捨てる。 すでに見えている文章を二重入力しない。
  • 入力先から離れたら既定で停止する。 別アプリへ移った後の独り言が、同僚宛ての欄へ流れる事故を防ぐ。
流れる文字を守る複数の安全ゲートを表現したAI生成イラスト

速く入れるだけでは道具にならない。送信、人の割り込み、フォーカス移動、停止後の遅延結果を別々の門で止める。

フォーカス監視も通知任せではない。Electronアプリは入力欄をAccessibilityへ公開しないことがあり、通知はアプリごとに挙動が違う。0.4秒ごとに別キューから確認し、「文字入力できない場所」が2回続いたときだけ離脱と判定する。分からない状態は停止理由にしない。この実装は、認識精度のベンチマークには出ないが、日用品としての信頼を決める部分である。

8. 実測して選び、約3,000行まで削って公開した

エンジンは名前で選ばず、同じMacで測った。MacBook Air M4、macOS 26.5.2、日本語の自然発話80〜105秒で、3構成を比較した結果がこれである。

構成初回表示途中結果の平均/最大遅延確定の平均/最大遅延誤り
Dictation + frequentFinalization1.63秒0.16/0.38秒0.42/0.86秒500字中7箇所
Dictation1.33秒0.16/0.38秒0.32/0.52秒668字中5箇所
SpeechTranscriber11.79秒0.08/0.18秒3.78/8.34秒531字中5箇所

SpeechTranscriberは精度で大敗したわけではない。しかしこの環境では初回表示が11.79秒かかり、確定も最大8.34秒遅れた。「話しながら入力欄を見る」用途には、DictationTranscriberの方が合った。未確定を先に出す設計も、感覚ではなくこの差から決めた。

公開している本体はSwift 12ファイル、約2,965行。ビルドスクリプトはswiftcでコンパイルし、辞書を同梱し、署名して/Applications/nobetsu.appへ置く。Xcodeプロジェクトも外部依存もない。テストは、間違えると文章を壊し、しかも純粋関数として検証できる「辞書の置換」「差分計算」「送信済み接頭辞の保護」に絞った。

完成品は万能ではない。macOS 26とApple Siliconが必要で、UIも認識言語も日本語だけ。CGEventのUnicodeを独自解釈するアプリでは入力できない可能性があり、合成キーイベントを送るため権限も要る。それでも、狭い条件の中で欲しかった体験はできた。

新しいモデルを発明しなくても、OSの新しい能力と、現場で起きた小さな失敗を丁寧につなぐと、今までなかった道具になる。 nobetsuは販売商品ではなく、自分の「ここだけ直れば」を最後まで掘った結果である。役に立ちそうなら、コードも動画も設計理由もGitHubに置いてある。自由に試し、読み、必要なら自分向けに変えてほしい。[1]

参考文献・出典

  1. [1]pochang6/nobetsu(GitHub)。README、全ソース、実測用spike、デモ動画、MITライセンスを公開。
  2. [2]Superwhisper公式およびモデル解説。Hold–speak–release、100以上の言語、ローカル/クラウドモデルを案内。
  3. [3]Wispr Flow「Use Flow hands-free」。停止時の貼り付けとデスクトップ20分上限を明記。
  4. [4]Willow Voice「Dictating with Willow Voice」。キーを離した後、またはNo Hands Mode停止後に全文を挿入し、50言語対応と説明。
  5. [5]Aqua Voice for Macおよび公式FAQ。Realtime Modeと日本語を含む49言語を案内。
  6. [6]Beingpax/VoiceInk(GitHub)。ローカル音声認識、ショートカット、個人辞書を備えるオープンソースmacOSアプリ。
  7. [7]MacWhisper公式。リアルタイム音声入力と100以上の言語対応を案内。
  8. [8]TypeWhisper/typewhisper-mac(GitHub)。SpeechAnalyzerを含む複数エンジン、ストリーミングプレビュー、完了後の自動貼り付けを提供。
  9. [9]yasu-888/koetype(GitHub)。日本発の無料アプリ。ローカルWhisper/Geminiに対応し、READMEでは録音停止後に文字起こしして貼り付ける流れを説明。
  10. [10]ソースネクスト「いきなりAI 音声タイピング」。日本発の商用製品。オフライン、リアルタイム、ハンズフリーを案内。
  11. [11]Appleサポート「Macでメッセージや書類を音声入力する」。入力できる場所ならどこでも使え、Apple Siliconでは音声入力中もキーボードを併用でき、30秒間発話がないと自動停止すると説明。
  12. [12]Appleサポート「Macで日本語入力ソースを使用して日本語を入力する」。ライブ変換が、入力中のひらがなを漢字を含む適切な日本語へ自動変換すると説明。
  13. [13]Apple Developer, “Bring advanced speech-to-text to your app with SpeechAnalyzer” (WWDC25)。長時間・遠距離・オンデバイス、volatile/final結果、AssetInventoryを解説。
  14. [14]Apple Developer「DictationTranscriber」。システム音声入力と同系統のオンデバイスモデルを使うSpeechAnalyzerモジュール。
  15. [15]Apple Developer「keyboardSetUnicodeString」。キーボードイベントにUnicode文字列を設定し、通常の仮想キー変換を上書きするAPI。

関連記事

2026年4月4日

macOS音声入力が突然効かない問題を「構造」で直す: Dictation障害の実践ランブック

macOSの音声入力が無反応・ビープ音になる問題を、corespeechd/DictationIM/coreaudiodの構造から分解し、即効復旧・予防設定・長期移行まで実務手順で整理します。

テクノロジー続きを読む
2026年7月30日

Chromeは100%なのにGoogleスプレッドシートだけ巨大化する──Preferencesの「ゴーストズーム」をコマンドで直す【macOS】

macOS版Chromeの特定プロファイルで、Google SheetsやDocsだけUIが125%相当に巨大化し、Cmd+0やサイト別ズーム削除でも直らない症状を診断・修復する。devicePixelRatioの比較、Preferencesの読み取り専用確認、バックアップ付きの安全なPython修復、復元方法まで、コピー可能なコマンドで解説する。

テクノロジー続きを読む
2026年7月17日

Macが夜中に止まった犯人は、ChatGPT.appの14GBだった|Codexのメモリ暴走を突き止めて「自動で治る」ようにするまで【2026年7月】

macOS版ChatGPT.app(Codex)が夜間に14GBまで肥大し、16GBのMacBook Air全体が止まった。原因はアプリの既知バグと「Automationsの単一スレッド運用」の合わせ技。実測データで原因を特定し、スレッド回転・メモリ番犬・履歴退避の3層で完全自動化するまでの記録と手順をまとめる。

テクノロジー続きを読む
2026年6月1日

Brain to Productを公開しました:声で意図を渡し、AIとプロダクトをつくる本です

新刊「Brain to Product 声で意図を渡しプロダクトをつくる」を公開しました。音声入力とAIエージェントで、頭の中の違和感や制約を実装へ渡す働き方を紹介します。

テック続きを読む
2026年3月19日

古舘伊知郎さんはAIエージェントで世界を取れる(かも)――音声入力が武器になる本当の理由

整った短文よりも未圧縮の文脈が強い理由、音声入力が思考の圧縮を防ぐ可能性、そしてAI時代に企業が見落としがちな「トーキングエンジニア」の価値を論じます。

テクノロジー続きを読む