2017-02-01 13 views
2

後、私は次のチュートリアル実装しています:私はAVAudioEngineを使用して、音声を録音し、音声をテキストに実装するSFSpeechRecognizerを使用していますSpeech To Text記録を停止X秒の沈黙

を。このチュートリアルでは、録音を開始および停止するボタンを使用して音声をテキストに誘導します。

私は、アプリケーションが許可を得たときにviewDidAppearで記録を開始しています。しかし、私は数秒間の沈黙の後に録音を止める方法を見つけることができません。以下は私のコードです:

import UIKit 
import Speech 

public class ViewController: UIViewController, SFSpeechRecognizerDelegate { 
// MARK: Properties 

private let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))! 

private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest? 

private var recognitionTask: SFSpeechRecognitionTask? 

private let audioEngine = AVAudioEngine() 

@IBOutlet var textView : UILabel! 

@IBOutlet var recordButton : UIButton! 


public override func viewDidLoad() { 
    super.viewDidLoad() 

    recordButton.isEnabled = false 
} 

override public func viewDidAppear(_ animated: Bool) { 
    speechRecognizer.delegate = self 

    SFSpeechRecognizer.requestAuthorization { authStatus in 
     /* 
     The callback may not be called on the main thread. Add an 
     operation to the main queue to update the record button's state. 
     */ 
     OperationQueue.main.addOperation { 
      switch authStatus { 
      case .authorized: 
       self.recordButton.isEnabled = true 
       try! self.startRecording() 
       self.recordButton.setTitle("Stop recording", for: []) 


      case .denied: 
       self.recordButton.isEnabled = false 
       self.recordButton.setTitle("User denied access to speech recognition", for: .disabled) 

      case .restricted: 
       self.recordButton.isEnabled = false 
       self.recordButton.setTitle("Speech recognition restricted on this device", for: .disabled) 

      case .notDetermined: 
       self.recordButton.isEnabled = false 
       self.recordButton.setTitle("Speech recognition not yet authorized", for: .disabled) 
      } 
     } 
    } 
} 

@IBAction func recordButtonTapped() { 
    if audioEngine.isRunning { 
     audioEngine.stop() 
     recognitionRequest?.endAudio() 
     recordButton.isEnabled = false 
     recordButton.setTitle("Start Recording", for: []) 
    } else { 
     try! startRecording() 
     recordButton.setTitle("Stop recording", for: []) 
    } 
} 

private func startRecording() throws { 

    // Cancel the previous task if it's running. 
    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() 

    guard let inputNode = audioEngine.inputNode else { fatalError("Audio engine has no input node") } 
    guard let recognitionRequest = recognitionRequest else { fatalError("Unable to created a SFSpeechAudioBufferRecognitionRequest object") } 

    // Configure request so that results are returned before audio recording is finished 
    recognitionRequest.shouldReportPartialResults = true 

    // A recognition task represents a speech recognition session. 
    // We keep a reference to the task so that it can be cancelled. 
    recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { result, error in 
     var isFinal = false 

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

     if error != nil || isFinal { 
      self.audioEngine.stop() 
      inputNode.removeTap(onBus: 0) 

      self.recognitionRequest = nil 
      self.recognitionTask = nil 

      self.recordButton.isEnabled = true 
     } 
    } 

    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() 

    textView.text = "(Go ahead, I'm listening)" 
} 

// MARK: SFSpeechRecognizerDelegate 

public func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) { 
    if available { 
     recordButton.isEnabled = true 
     recordButton.setTitle("Start Recording", for: []) 
    } else { 
     recordButton.isEnabled = false 
     recordButton.setTitle("Recognition not available", for: .disabled) 
    } 
} 

// MARK: Interface Builder actions 


} 

アプリケーションは素晴らしいです。しかし、私は無音のX秒でaudioEngineを停止するように実装したい。

答えて

2

音声入力を取得するたびに、指定した間隔のタイマーを使用して無効にすることがあります。

常に自分自身を無効にし、ユーザーが話している間に新しいタイマーを作成するタイマーを1つ作成します。ユーザーが時間を話すことは終わりに達し停止し、

例終えるとき:

class text { 
var timer:Timer? 
    func startRecording() { createTimer(4) } 

    func whileRecording() { createTimer(1) } 

    func createTimer(_ interval:Double) { 
     timer?.invalidate() 
     timer = Timer.scheduledTimer(withTimeInterval: interval, repeats: false) { (_) in 
      if self.audioEngine.isRunning { 
       self.stopRecording() 
      } 
     } 
    } 

} 
+0

を私はタイマーを無効にするたびに、それは再度使用することはできませんので、これは答えではありません。 5秒間待つためのタイマーを開始したとします。しかし、ユーザーが何かを話すとき、私はそのタイマーが再び始まり、5秒待つことを望む。したがって、前のタイマーを無効にすると、再び使用することはできません。そして、ユーザーが100回(最悪の場合の想像力)話すなら、私はタイマー100回を作成し、それらの99を無効にして、毎回次のものを待たなければなりません。だから実用的な解決策ではありません。 –

+0

@RockBalbao私の更新された回答を見てください - これは真実ではありません。私は1つのタイマーしか使用せず、常にそのタイマーを無効にします。 – Ram

+0

@Ramタイマーをどこに呼び出すべきか教えてください。 –

関連する問題