[英]Speech Recognition in swift
實際上,我在代碼中使用了語音識別,以根據識別出的語音找出聯系方式。 但是,它不斷將單詞添加到緩沖區中,我要刪除的是先前記錄的單詞或行。 就像我要搜索“史蒂夫·喬布斯”,然后是“比爾·蓋茨”一樣,它都被組合為“史蒂夫·喬布斯·比爾·蓋茨”。 以下是我的代碼。
import UIKit
import Speech
class SpeechRecognizer:NSObject,SFSpeechRecognizerDelegate{
static let shared:SpeechRecognizer? = {
return SpeechRecognizer()
}()
var isRunning = false
private var speechRecognizer:SFSpeechRecognizer!
private var audioEngine:AVAudioEngine!
private var recognitionRequest:SFSpeechAudioBufferRecognitionRequest!
private var recognitionTask:SFSpeechRecognitionTask!
public func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) {
if available {
print("recordign available")
} else {
print("Recording not available")
}
}
func stopRecording() {
if audioEngine == nil {
return
}
if audioEngine.isRunning {
audioEngine.inputNode.removeTap(onBus: 0)
audioEngine.stop()
recognitionTask?.cancel()
recognitionRequest?.endAudio()
print("Stopped")
isRunning = false
}
}
func start(result:@escaping(String)->()) {
getSpeechRegnizationPermission { (per) in
if per && !self.isRunning{
do {
try self.startRecording(rcResult: { (rcRes) in
result(rcRes)
})
} catch {
print(error)
}
} else if self.isRunning {
print("alrdy running")
} else {
print("no permission")
}
}
}
private func startRecording(rcResult:@escaping (String)->()) throws {
self.stopRecording()
isRunning = true
speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))!
audioEngine = AVAudioEngine()
recognitionTask = nil
recognitionRequest = nil
if let recognitionTask = recognitionTask {
recognitionTask.cancel()
self.recognitionTask = 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("Unable to create a SfSpeechAudioBufferRecognitionRequest object")}
recognitionRequest.shouldReportPartialResults = true
recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { result, error in var isFinal = false
if let result = result {
rcResult(result.bestTranscription.formattedString)
isFinal = result.isFinal
print("Final word is :",isFinal)
}
if error != nil || isFinal {
self.audioEngine.stop()
inputNode.removeTap(onBus: 0)
self.recognitionRequest = nil
self.recognitionTask = nil
}
}
let recordingFormat = inputNode.outputFormat(forBus: 0)
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in
self.recognitionRequest?.append(buffer)
}
audioEngine.prepare()
try audioEngine.start()
print("Im listening ")
}
private func getSpeechRegnizationPermission(status:@escaping (Bool)->()){
if SFSpeechRecognizer.authorizationStatus() == .authorized {
status(true)
return
}
SFSpeechRecognizer.requestAuthorization { (sta) in
switch sta {
case .authorized:
status(true)
case .denied:
status(false)
case .notDetermined:
SFSpeechRecognizer.requestAuthorization({ (st) in
if st == .authorized {
status(true)
} else {
status(false)
}
})
case .restricted:
status(false)
}
}
}
}
我建議先合並stopRecording
函數和此代碼塊, stopRecording
僅使用stopRecording
:
if error != nil || isFinal {
self.audioEngine.stop()
inputNode.removeTap(onBus: 0)
self.recognitionRequest = nil
self.recognitionTask = nil
}
這樣,您將剩下一種處置正在使用的資源的方法,而且您無需在startRecording
函數的第一行調用stopRecording
。 獲得結果后,將該結果傳遞到rcResult(result.bestTranscription.formattedString)
塊, stopRecording
在該位置調用stopRecording
。
另外,也不要使用recognitionTask?.finish()
recognitionTask?.cancel()
來調用recognitionTask?.cancel()
recognitionTask?.finish()
。
希望有幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.