AVFoundationでカメラ撮影機能を実装した流れで、以前から気になっていたSpeechフレームワークによる音声認識機能にも挑戦してみました。
1. マイクの権限だけ取得すればよいと思っていた
最初、音声を扱う機能なのでマイクの利用許可さえ得られれば動くと思い込んでいました。
SFSpeechRecognizer.requestAuthorization { status in
}
マイクの権限リクエストを実装したにもかかわらず、実際にはエラーで認識処理が動きませんでした。調べてみると、音声認識機能自体にもSFSpeechRecognizer.requestAuthorizationという別の権限リクエストが必要で、マイクの権限と音声認識の権限は別物として扱われていることが分かりました。両方の許可を得て初めて機能が使えるようになりました。
2. 常にオンデバイスで認識できると思っていた
プライバシーの観点から、認識処理はすべて端末内で完結するものだと思い込んでいました。
recognitionRequest.requiresOnDeviceRecognition = true
このプロパティを見つけて初めて、デフォルトではサーバーを利用した認識が行われる場合があり、オンデバイス認識を使いたい場合は明示的に指定する必要があると分かりました。またオンデバイス認識は対応言語やiOSバージョンに制約があることも合わせて理解しました。
3. 認識結果がどんどん書き換わる仕様に混乱した
音声認識の結果をそのままテキスト表示していたところ、確定していないはずの文言が話している最中に何度も書き換わる現象に戸惑いました。
気づいたこと:
isFinal が true になるまでは暫定結果
認識結果には「暫定結果」と「確定結果」があり、isFinalがtrueになるまでは認識精度が上がるたびに内容が更新され続ける仕様だと分かりました。リアルタイム表示自体はこの暫定結果を使い、最終的な保存処理などはisFinalのタイミングで行うよう実装を分ける必要がありました。
4. 認識セッションを終了する処理を書き忘れていた
動作確認を続けていると、しばらく使った後にアプリがマイクを使用し続けたままになっている現象に気づきました。
audioEngine.stop()
recognitionRequest.endAudio()
音声入力を終える際に、オーディオエンジンの停止と認識リクエストの終了処理を明示的に呼び出す必要があることが分かりました。この終了処理を書き忘れていたことで、マイクのリソースが解放されないままになっていたことが原因でした。
まとめ
- マイクの権限と音声認識自体の権限は別物で、両方の許可が必要
- オンデバイス認識はデフォルトではなく、明示的に指定する必要がある(対応言語・バージョンにも制約あり)
- 認識結果には暫定結果と確定結果があり、
isFinalで区別して扱う必要がある - 使用後は
audioEngine.stop()とrecognitionRequest.endAudio()を呼び、リソースを明示的に解放する必要がある
権限まわりの細かさと、リアルタイム性ゆえの状態管理の複雑さの両方を意識する必要がある実装だと実感しました。
本記事は生成AI(Claude)を活用して執筆・編集しています。内容は実体験に基づき、執筆者本人が確認・監修しています。


コメント