2016-12-12 8 views
3

Я использую распознавание живой речи с помощью новой рамки iOS10. Я использую AVCaptureSession, чтобы получить аудио.iOS10 Распознавание речи Звуковой эффект «Прослушивание»

У меня есть «прослушивающий» звуковой сигнал, чтобы уведомить пользователя, с которым он может начать говорить. Лучший способ поставить этот звук - на 1-й вызов captureOutput(:didOutputSampleBuffer..), но если я попытаюсь воспроизвести звук после начала сеанса, звук просто не будет воспроизводиться. И никакая ошибка не брошено .. он просто молча не играть ...

Что я пробовал:

  • Воспроизведение через звуковую систему (AudioServicesPlaySystemSound...())
  • Играть актив с AVPlayer
  • Также попробовал оба вышеупомянутых решения async/sync в главной очереди

Кажется, что независимо от того, что я делаю, невозможно вызвать воспроизведение любого звука после tr (не уверен, что конкретно это AVCaptureSession или SFSpeechAudioBufferRecognitionRequest/SFSpeechRecognitionTask ...)

Любые идеи? Apple even recommends playing a "listening" sound effect (и делать это сами с Siri), но я не мог найти ссылку/пример, показывающий, как на самом деле это ... (их пример «SpeakToMe» не играет звук)

  • Я могу играть звук перед запуском сеанса, и он работает (при запуске сеанса при завершении воспроизведения звука), но иногда это отставание в самом начале распознавания (в основном при использовании BT-наушников и переключении с другой категории AudioSession, для которой я не имеют события завершения ...) - из-за этого мне нужен способ воспроизвести звук, когда запись действительно начинается, а не до того, как она срабатывает и скрестит пальцы, она не будет откладывать ее ...

ответ

2

Ну, по-видимому, существует целая серия «правил», которые необходимо выполнить, чтобы успешно начать сеанс распознавания речи и воспроизвести эффект «прослушивания» только тогда, когда (после) произошло признание действительно.

  1. Установка сеанса & триггеринга должен быть вызван в основную очередь. Итак:

    DispatchQueue.main.async { 
        speechRequest = SFSpeechAudioBufferRecognitionRequest() 
        task = recognizer.recognitionTask(with: speechRequest, delegate: self) 
        capture = AVCaptureSession() 
        //..... 
        shouldHandleRecordingBegan = true 
        capture?.startRunning() 
    } 
    
  2. «слушать» эффект должен быть игрок с помощью AVPlayer, а не как звук системы.

  3. Самое безопасное место, чтобы знать, что мы определенно записи в делегата вызова AVCaptureAudioDataOutputSampleBufferDelegate, когда мы получаем наш первый sampleBuffer обратный вызов:

    func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) { 
    
        //only once per recognition session 
        if shouldHandleRecordingBegan { 
         shouldHandleRecordingBegan = false 
    
         player = AVPlayer(url: Bundle.main.url(forResource: "listening", withExtension: "aiff")!) 
         player.play()    
    
         DispatchQueue.main.async { 
          //call delegate/handler closure/post notification etc... 
         } 
        } 
    
        // append buffer to speech recognition 
        speechRequest?.appendAudioSampleBuffer(sampleBuffer) 
    } 
    
  4. Конец эффекта распознавания является чертовски проще:

    var ended = false 
    
    if task?.state == .running || task?.state == .starting { 
        task?.finish() // or task?.cancel() to cancel and not get results. 
        ended = true 
    } 
    
    if true == capture?.isRunning { 
        capture?.stopRunning() 
    } 
    
    if ended { 
        player = AVPlayer(url: Bundle.main.url(forResource: "done", withExtension: "aiff")!) 
        player.play() 
    }