同様の質問がすでに出されていることは知っていますが、提案された解決策は役に立ちませんでした。
私のアプリでは、ユーザーの音声を認識し、音声合成も行う必要があります。問題は、アプリが認識しようとしているときにランダムにクラッシュすることです (特にテキスト読み上げの後ですが、他の場合: 2 回目の認識の試行時など)。
いくつかの明らかな変数 (一部はプライベート) と 2 つの主要な機能を持つ特別なクラス Speecher があります:startRecord
とkillRecord
.
func startRecord() {
session = AVAudioSession.sharedInstance()
do {
try session.setCategory(AVAudioSession.Category.playAndRecord, mode: .spokenAudio, options: [.defaultToSpeaker, .mixWithOthers])
} catch {
print("audio session \(error)")
return
}
audioEngine = AVAudioEngine()
inputNode = audioEngine.inputNode
inputNode.removeTap(onBus: 0)
let recordingFormat = inputNode.inputFormat(forBus: 0)
recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
guard let recognitionRequest = recognitionRequest else { fatalError("Unable to create a SFSpeechAudioBufferRecognitionRequest object") }
recognitionRequest.shouldReportPartialResults = true
if #available(iOS 13, *) {
recognitionRequest.requiresOnDeviceRecognition = true
}
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, _ in
self.recognitionRequest.append(buffer)
}
audioEngine.prepare()
do {
try audioEngine.start()
} catch {
return print("audio engine start error \(error)")
}
guard let myRecognizer = SFSpeechRecognizer() else {
print("recognizer error")
return
}
if !myRecognizer.isAvailable {
print("Recognizer is not available right now error")
return
}
recognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest, resultHandler: { result, error in
if let result = result {
let bestString = result.bestTranscription.formattedString
print(bestString)
self.speecherDelegate?.sendSpeechString(str: bestString)
} else if let error = error {
print("result error \(error)")
}
})
}
次の関数は、テキスト読み上げを使用しようとする前、または認識セッションをキャンセル/停止する前に呼び出されます。
func killRecord() {
if recognitionRequest != nil {
recognitionRequest.endAudio()
}
if audioEngine != nil {
audioEngine.stop()
if audioEngine.inputNode != nil {
audioEngine.inputNode.removeTap(onBus: 0)
}
}
if recognitionTask != nil {
recognitionTask?.cancel()
}
if session != nil {
do {
try session.setCategory(AVAudioSession.Category.playback, mode: .spokenAudio, options: [.allowBluetooth, .allowBluetoothA2DP, .defaultToSpeaker, .mixWithOthers])
try session.setActive(false, options: .notifyOthersOnDeactivation)
} catch {
print("switch audiosession error not nil \(error)")
return
}
} else {
session = AVAudioSession.sharedInstance()
do {
try session.setCategory(AVAudioSession.Category.playback, mode: .spokenAudio, options: [.allowBluetooth, .allowBluetoothA2DP, .defaultToSpeaker, .mixWithOthers])
try session.setActive(false, options: .notifyOthersOnDeactivation)
} catch {
print("switch audiosession error \(error)")
return
}
}
}
私がよく得ているのはlldbエラーです。次のようになります。
コード内の問題文字列は のようですがinputNode = audioEngine.inputNode
、解決方法がわかりません。私はすでにaudioEngine.inputNode.removeTap(onBus: 0)
直前に試しましinputNode = audioEngine.inputNode
たが、役に立ちませんでした。