iOS 相机:`AVCaptureAudioDataOutput` 即时激活音频会话,避免背景音乐卡顿

mro*_*avy 8 objective-c avfoundation ios avcapturesession swift

我使用 AVFoundation 创建了一个相机,它能够使用AVCaptureVideoDataOutput和录制视频和音频AVCaptureAudioDataOutput。我创建我的捕获会话,连接所有输入以及视频和音频数据输出,然后相机处于空闲状态。用户现在可以开始视频录制。

问题

问题在于,在我开始捕获会话 ( captureSession.startRunning()) 后,背景音乐立即断断续续。我认为这是因为一旦捕获会话开始运行,AVCaptureAudioDataOutput内部就会激活 AVAudioSession ( AVAudioSession.setActive(...)),我不希望它这样做。我希望它处于空闲状态(并且不提供任何音频输出缓冲区),直到我明确激活音频会话(一旦用户开始录制)。

这真的很烦人,因为相机是我们应用程序的开始屏幕,每次用户打开或关闭应用程序时,他的音乐都会断断续续。

我知道这在某种程度上是可能的,因为 Snapchat 就是这样工作的——你打开应用程序,背景音频继续流畅地播放。开始录制后,背景音乐会出现轻微的卡顿,但相机会顺利运行并在短暂的卡顿结束后开始录制。

我的代码:

func configureSession() {

    captureSession.beginConfiguration()

    // Video, Photo and Audio Inputs
    ...

    // Video Output
    ...

    // Audio Output
    audioOutput = AVCaptureAudioDataOutput()
    guard captureSession.canAddOutput(audioOutput!) else {
      throw CameraError.parameter(.unsupportedOutput(outputDescriptor: "audio-output"))
    }
    audioOutput!.setSampleBufferDelegate(self, queue: audioQueue)
    captureSession.addOutput(audioOutput!)

    try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playAndRecord,
                                                    options: [.mixWithOthers,
                                                              .allowBluetoothA2DP,
                                                              .defaultToSpeaker,
                                                              .allowAirPlay])

    captureSession.commitConfiguration()
}
Run Code Online (Sandbox Code Playgroud)

我试过的

延迟配置 AVAudioSession.sharedInstance()

我尝试首先AVAudioSession.sharedInstance使用 category进行配置AVAudioSession.Category.playback,然后在.playAndRecord我想开始录制音频时切换到。

这不起作用,并且在AVCaptureSessionRuntimeError使用错误代码启动相机后立即调用该事件-10851,这意味着kAudioUnitErr_InvalidPropertyValue. 我认为这意味着AVCaptureAudioDataOutput不允许从音频会话录制,但我现在不想这样做 - 它应该只是闲置。

延迟添加AVCaptureAudioDataOutput输出

我试图在开始时不添加音频输出 ( AVCaptureAudioDataOutput),并且仅在用户开始录制后“按需”添加它,而这对于背景音乐来说效果很好(开始时没有口吃,用户只有短暂的口吃开始录制,正是我想要的),它使预览冻结了很短的时间(因为捕获会话正在通过beginConfiguration+ 音频输出添加 +重新配置commitConfiguration

有谁知道如何实现我在这里尝试做的事情 - 或者 Snapchat 是如何做到的?任何帮助表示赞赏,谢谢!

mro*_*avy 1

终于想通了。我只是AVCaptureSession专门为音频输入/输出创建了一个单独的文件,我将其与主捕获会话的masterClock. 然后我可以即时启动/停止辅助捕获会话(在开始录制之前不久)