AvAudioEngine 可以播放和录音吗?

Posted

技术标签:

【中文标题】AvAudioEngine 可以播放和录音吗?【英文标题】:AvAudioEngine playing and recording possible? 【发布时间】:2020-08-21 18:32:14 【问题描述】:

我正在尝试使用 AVAudioEngine 播放按钮声音。但不幸的是声音文件只播放了一次。

想法是,用户点击按钮,播放声音并开始录制。用户再次点击按钮后,应播放第二个声音,指示录制会话已结束。

到目前为止,第一个声音出现,录音开始。 不幸的是,不会播放第二个声音(结束声音)。

我发现,当我使用与录音功能相同的 AudioEngine 时,根本不会播放声音。

由于我对 AVFoundation 框架完全陌生,我不确定这里的问题是什么。

提前致谢。

    var StartSoundEngineScene1 = AVAudioEngine()
    var StartSoundNodeScene1 = AVAudioPlayerNode()

    func SetupAudio(AudioEngine: AVAudioEngine, SoundNode: AVAudioPlayerNode, FileURL: URL) 
        
        guard let AudioFile = try? AVAudioFile(forReading: FileURL) else return 
        let Audiosession = AVAudioSession.sharedInstance()

        AudioEngine.attach(SoundNode)
        AudioEngine.connect(SoundNode, to: AudioEngine.mainMixerNode, format: AudioFile.processingFormat)
        AudioEngine.prepare()
        
    

   override func viewDidLoad() 
        super.viewDidLoad()
        
        SetupAudio(AudioEngine: StartSoundEngineScene1, SoundNode: StartSoundNodeScene1, FileURL: StartRecSound)




    func ButtonSound (AudioEngine: AVAudioEngine, SoundNode: AVAudioPlayerNode, FileURL: URL)
        
        try? AudioEngine.start()
        
        guard let audioFile = try? AVAudioFile(forReading: FileURL) else return 
        
        SoundNode.scheduleFile(audioFile, at: nil, completionHandler: nil)
        SoundNode.volume = 0.16
        SoundNode.play()
                
    

func StartRecording()
        
ButtonSound(AudioEngine: StartSoundEngineScene1, SoundNode: StartSoundNodeScene1, FileURL: StartRecSound)

Timer.scheduledTimer(withTimeInterval: 0.7, repeats: false)  timer in

          if audioEngine.isRunning 
                audioEngine.stop()
                recognitionRequest?.endAudio()
            
           else 
              print("Rercording Started")
                  
              if let recognitionTask = self.recognitionTask 
                  recognitionTask.cancel()
                  self.recognitionTask = nil
              
              
              self.recordedMessage = ""
              
              let audioSession = AVAudioSession.sharedInstance()
              do 
                try audioSession.setCategory(AVAudioSession.Category.record)
                try audioSession.setMode(AVAudioSession.Mode.measurement)
              catch 
                  print(error)
              
                        
              recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
              
              guard let recognitionRequest = self.recognitionRequest else 
                  fatalError("Unable to create a speech audio buffer")
              
              
              recognitionRequest.shouldReportPartialResults = true
              recognitionRequest.requiresOnDeviceRecognition = true
                  
              recognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest, resultHandler:  (result, error) in
                  
                  var isFinal = false
                  if let result = result 
                      let sentence = result.bestTranscription.formattedString
                      self.recordedMessage = sentence
                      print (self.recordedMessage)
                      isFinal = result.isFinal
                  
                  
                  if error != nil || isFinal 
                      self.audioEngine.stop()
                      self.audioEngine.inputNode.removeTap(onBus: 0)
                      self.recognitionRequest = nil
                      self.recognitionTask = nil
                      self.RecordBtn.isEnabled = true
                  
                  
              )
              
              let recordingFormat = audioEngine.inputNode.outputFormat(forBus: 0)
              audioEngine.inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat)  (buffer, when) in
                  self.recognitionRequest?.append(buffer)
              
              
              audioEngine.prepare()
                
              do
                  try audioEngine.start()
              catch 
                  print(error)
              
          
      


    
    func StopRecording()
         if audioEngine.isRunning
             audioEngine.stop()
ButtonSound(AudioEngine: StartSoundEngineScene1, SoundNode: StartSoundNodeScene1, FileURL: StopRecSound)
             recognitionRequest?.endAudio()
             audioEngine.inputNode.removeTap(onBus: 0)
             
         

【问题讨论】:

【参考方案1】:

您将 AVAudioSessionCategory 设置为记录。

try audioSession.setCategory(AVAudioSession.Category.record)

如果你想同时播放和录制,你应该设置这个类别playAndRecord

并且...如果您在播放或录制过程中更改 AVAudioSession,AVAudioEngine 的配置将被更改,然后它会触发 AVAudioEngineConfigurationChange 通知。

【讨论】:

以上是关于AvAudioEngine 可以播放和录音吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 WatchOS 上使用 AVAudioEngine 录制时阻止播放

使用 AVAudioEngine 离线渲染音频文件

从 AVAudioNodeTap 向 AVAudioFile 写入缓冲区(从 AVAudioEngine 保存录音)

AVAudioEngine 实时音频播放问题

AVAudioEngine inputNode installTap 重启录音时崩溃

录音和播放同时进行