質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • Swift

    7243questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • iOS

    3998questions

    iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

[iOS11][Swift]音声認識でエラーとなる

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 235

maeta

score 1

 前提・実現したいこと

現在、音声でのチャットアプリを作成しようとしており、
まずは音声周りを調査しております。
iOSのSFSpeechRecognizerを使用してサンプルを作成しているのですが
音声認識開始後無言のまま音声認識の停止を実行するとエラーとなっています。
GitHubにある、Sampleをクローンして実行するも同じエラーとなります。
またこのエラーが出ると、AVSpeechSynthesizerのspeakでも
エラーとなってしまいます。
どのようなことを行えばエラーが無くなるのでしょうか?

 SFSpeechRecognizerのエラー

2018-07-13 09:28:20.405082+0900 test[250:11545] [Utility] +[AFAggregator logDictationFailedWithError:] Error Domain=kAFAssistantErrorDomain Code=203 "Retry" UserInfo={NSLocalizedDescription=Retry, NSUnderlyingError=0x1c4450f80 {Error Domain=SiriSpeechErrorDomain Code=1 "(null)"}}

 AVSpeechSynthesizerのエラー

2018-07-13 09:28:57.917950+0900 test[250:11814] [TTS] Failure starting audio queue ≥˚˛ˇ
2018-07-13 09:28:59.942248+0900 test[250:11814] [TTS] _BeginSpeaking: couldn't begin playback

 該当のソースコード

import UIKit
import Speech

class ViewController: UIViewController {

    // "ja-JP"を指定すると日本語になります。
    private let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "ja-JP"))!
    private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?
    private var recognitionTask: SFSpeechRecognitionTask?
    private let audioEngine = AVAudioEngine()
    private var inputNode:AVAudioInputNode!

    @IBOutlet weak var textView: UITextView!
    @IBOutlet weak var recordButton: UIButton!
    // 音声読み上げ
    let talker = AVSpeechSynthesizer()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        recordButton.isEnabled = false
    }

    override func viewDidAppear(_ animated: Bool) {
        // 音声認識用デリゲートを設定
        speechRecognizer.delegate = self

        requestRecognizerAuthorization()

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    // 音声認識が許可されているかどうか確認
    private func requestRecognizerAuthorization() {
        // 認証処理
        SFSpeechRecognizer.requestAuthorization { authStatus in
            // メインスレッドで処理したい内容のため、OperationQueue.main.addOperationを使う
            // コールバックはメインスレッドで呼び出されないことがあります。 追加する
            // 操作をメインキューに送り、レコードボタンの状態を更新します。
            OperationQueue.main.addOperation {
                switch authStatus {
                case .authorized:
                    self.recordButton.isEnabled = true

                case .denied:
                    self.recordButton.isEnabled = false
                    self.recordButton.setTitle("ユーザーが音声認識へのアクセスを拒否しました", for: .disabled)

                case .restricted:
                    self.recordButton.isEnabled = false
                    self.recordButton.setTitle("このデバイスで音声認識が制限されています", for: .disabled)

                case .notDetermined:
                    self.recordButton.isEnabled = false
                    self.recordButton.setTitle("音声認識が承認されていません", for: .disabled)
                }
            }
        }
    }
    private func startRecording() throws {

        // 前のタスクが実行中の場合はキャンセルします。
        if let recognitionTask = recognitionTask {
            recognitionTask.cancel()
            self.audioEngine.stop()
            self.audioEngine.inputNode.removeTap(onBus: 0)
            self.recognitionTask = nil
            self.recognitionRequest = nil
        }

        let audioSession = AVAudioSession.sharedInstance()
        try audioSession.setCategory(AVAudioSessionCategoryRecord)
        try audioSession.setMode(AVAudioSessionModeMeasurement)
        try audioSession.setActive(true, with: .notifyOthersOnDeactivation)

        recognitionRequest = SFSpeechAudioBufferRecognitionRequest()

        let inputNode = audioEngine.inputNode
        guard let recognitionRequest = recognitionRequest else { fatalError("音声認識オブジェクトを作成できません") }

        // オーディオ録音が完了する前に結果が返されるようにリクエストを設定する
        // trueだと現在-1回目のリクエスト結果が返ってくる模様。falseだとボタンをオフにしたときに音声認識の結果が返ってくる設定。
        recognitionRequest.shouldReportPartialResults = true

        // 認識タスクは、音声認識セッションを表します。
        // それを取り消すことができるようにタスクへの参照を保持します。
        recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { result, error in
            var isFinal = false

            self.textView.text = ""

            if let result = result {
                self.textView.text = result.bestTranscription.formattedString
                isFinal = result.isFinal
            }

            // エラーがある、もしくは最後の認識結果だった場合の処理
            if error != nil || isFinal {
                self.audioEngine.stop()
                self.recognitionRequest?.endAudio()
                inputNode.removeTap(onBus: 0)

                self.recognitionRequest = nil
                self.recognitionTask = nil

                self.recordButton.isEnabled = true
                self.recordButton.setTitle("音声認識開始", for: [])

                if error == nil {
                    self.play(text: self.textView.text)
                }
            }
        }

        // マイクから取得した音声バッファをリクエストに渡す
        let recordingFormat = inputNode.outputFormat(forBus: 0)
        inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in
            self.recognitionRequest?.append(buffer)
            //append(buffer)
        }

        // startの前にリソースを確保しておく。
        audioEngine.prepare()
        try audioEngine.start()

        textView.text = "(音声認識状態になっています)"

    }
    @IBAction func recordButtonTapped() {

        if self.audioEngine.isRunning {
            // 認識終了
            self.audioEngine.stop()
            self.audioEngine.inputNode.removeTap(onBus: 0)
            self.recognitionRequest?.endAudio()

            self.recordButton.isEnabled = false
            self.recordButton.setTitle("音声認識停止中", for: .disabled)

        } else {
            try! self.startRecording()
            self.recordButton.setTitle("音声認識停止", for: [])
        }

    }
    @IBAction func speechButton() {
        play(text: "音声認識テスト")
    }

}

extension ViewController: SFSpeechRecognizerDelegate {

    // 音声認識の可否が変更したときに呼ばれるdelegate
    public func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) {
        if available {
            recordButton.isEnabled = true
            recordButton.setTitle("音声認識開始", for: [])
        } else {
            recordButton.isEnabled = false
            recordButton.setTitle("音声認識を実行できない状態です", for: .disabled)
        }
    }

}

extension ViewController: AVSpeechSynthesizerDelegate {

    private func play(text: String) {
        if talker.isSpeaking {
            talker.stopSpeaking(at: .immediate)
        }

        let utterance = AVSpeechUtterance(string: text)
        utterance.volume = 1

        utterance.voice = AVSpeechSynthesisVoice(language: "ja-JP")
        talker.speak(utterance)
    }
}

 XcodeとiOS

Xcode:Version 9.4.1
iOS:11.4

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

自己解決
どうもこのエラーですが、
iOSのキーボードに付いている、音声認識でも
同じエラーが出ます。
なので、一旦無視します。

解決方法は今の所ありません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Swift

    7243questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • iOS

    3998questions

    iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。