2017-02-01 1 views
2

내가 자습서 다음 구현하고의 침묵 후. 자습서에서는 녹음을 시작하고 중지하는 버튼을 사용하여 음성을 텍스트로 안내합니다.녹음을 정지 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 


} 

응용 프로그램이 멋지게 작동합니다. 하지만 audioEngine을 X 초 동안 멈추도록 구현하고 싶습니다.

답변

2

음성 입력을 얻을 때마다 지정된 간격으로 타이머를 사용하고 무효화 할 수 있습니다.

항상 사용자를 무효화하고 사용자가 말하는 동안 새 타이머를 만드는 타이머를 만듭니다.

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 내 업데이트 된 답변보기 - 이는 사실이 아닙니다. 난 오직 하나의 타이머를 사용하고 항상 타이머를 무효화합니다. – Ram

+0

@Ram 당신이 타이머를 호출해야하는 곳을 말해 줄 수 있습니까? –

관련 문제