あたも技術ブログ

セットジャパンコーポレーションの社員が運営しています。

【iOS 10】Speech Frameworkで音声認識

先月行われたWWDCiOS 10が発表され、DeveloperにはすでにiOS 10とXcode 8のベータ版が配布されています。

今回は、iOS 10で実装されたSpeech Frameworkを紹介します。

Speech Frameworkとは

iOS 10から対応するAppleが純正のAPIとして公開した音声認識Frameworkです。

今までiOS音声認識を使う場合、サードパーティ音声認識ライブラリを使う必要がありましたが、今後はSpeech Frameworkを利用することで、サードパーティに頼る必要がなくなります。

公式のサンプルコード

Using Speech Recognition with AVAudioEngineというサンプルコードがAppleから公開されています。

プロジェクトファイルを開くためにはXcode 8が必要になります。

developer.apple.com

使い方

音声認識を行うためには"SFSpeechRecognizer"というクラスを使うようです。

初期化の引数としてLocaleクラスを渡します。

 // 識別言語を日本語とする
private let speechRecognizer = SFSpeechRecognizer(locale: Locale(localeIdentifier: "ja_JP"))!

続いて、Delegateを設定します。

speechRecognizer.delegate = self

Delegateメソッドは以下のものが存在し、Recognizerのステータスが変化した場合に呼び出されるようです。

availableにRecognizerが使用可能か否かの値が入っています。

optional public func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool)

音声認識を使用する場合は権限の許可を得なければならないので、

SFSpeechRecognizerクラスのrequestAuthorizationメソッドで、権限を求めるアラートを表示します。

サンプルでは、許可されている場合に認識を開始するボタンを有効にする処理になっていました。

SFSpeechRecognizer.requestAuthorization { authStatus in
            // 音声アクセス許可を求める
            OperationQueue.main().addOperation {
                switch authStatus {
                    case .authorized:
                    //  許可
                    case .denied:
                    // 拒否
                    case .restricted:
                    //  設定などにより制限されている
                    case .notDetermined:
                    //  未認証
                }
            }
        }

音声入力を使う場合

認識リクエスト
// プロパティで宣言する
private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?

// 初期化
recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
guard let recognitionRequest = recognitionRequest else { fatalError("Unable to created a SFSpeechAudioBufferRecognitionRequest object") }
// 確定前の結果を取得する
recognitionRequest.shouldReportPartialResults = true
音声ファイルを使う場合
// プロパティなどで宣言
private var recognitionRequest: SFSpeechURLRecognitionRequest?

// 初期化
// URL
recognitionRequest = SFSpeechURLRecognitionRequest(url: URL(string: "http://xxxxxxxxxxxxxxxx")!)
// ローカルファイル
recognitionRequest = SFSpeechURLRecognitionRequest(url: URL(fileURLWithPath: localPath))

タスクの設定

タスクを設定し、値を受け取った場合の処理をBlockで渡します。

// プロパティなどで宣言
private var recognitionTask: SFSpeechRecognitionTask?
// タスクを設定
recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { result, error in    
    if let result = result {
        //  結果を取得できた場合の処理
    }
    
    if error != nil {
        // 取得エラー
    }
}

resultはSFSpeechRecognitionResultオブジェクトになっています。

// 認識したテキストの取得
result.bestTranscription.formattedString
// 終了検知
result.isFinal

音声ファイルを使用する場合は以上で終了です。

認識の開始

AVAudioEngineによりマイクからの音声入力を取得します。

// プロパティなどで宣言
private let audioEngine = AVAudioEngine()

// 初期化
audioEngine = AVAudioEngine()
guard let inputNode = audioEngine.inputNode else { fatalError("Audio engine has no input node") }
// 音声取得形式を設定
 let recordingFormat = inputNode.outputFormat(forBus: 0)
// 音声入力を受け取った際に、SFAudioBufferRecognitionRequestに受け取ったバッファを追加します。
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in
    self.recognitionRequest?.append(buffer)
}
// 音声の取得を開始します
audioEngine.prepare()
try audioEngine.start()

注意点

上記のコードで簡単に実装できるSpeech Frameworkですが、いくつか問題点があるようです。 調べて分かった問題点を幾つか紹介します。

・インターネット環境必須

・回数制限あり

・連続使用は1分まで

使ってみて

実際にiPhoneに向かって喋ってみましたが、かなり高い精度で認識してくれているようです。 50文字程度の文章を音読してみましたが、誤字などは無く、識別率100%となりました。