iOS 摄像头:`AVCaptureAudioDataOutput` 即时激活音频会话,避免背景音乐断断续续
iOS Camera: `AVCaptureAudioDataOutput` activate audio session on the fly, avoid background music stutter
我使用 AVFoundation 创建了一个相机,它能够使用 AVCaptureVideoDataOutput
和 AVCaptureAudioDataOutput
录制视频和音频。我创建我的捕获会话,附加所有输入以及视频和音频数据输出,然后相机闲置。用户现在可以开始视频录制了。
问题
问题在于,在我开始捕获会话 (captureSession.startRunning()
) 后,背景音乐立即断断续续。我认为这是因为一旦捕获会话开始 运行,AVCaptureAudioDataOutput
就会在内部激活 AVAudioSession (AVAudioSession.setActive(...)
),我不希望它这样做。我希望它闲置(并且不提供任何音频输出缓冲区),直到我明确激活音频会话(一旦用户开始录制)。
这真的很烦人,因为相机是我们应用程序的开始屏幕,每次用户打开或关闭应用程序时,他的音乐都会断断续续。
我知道这在某种程度上是可能的,因为 Snapchat 就是这样工作的——你打开应用程序,背景音频会继续流畅地播放。开始录制后,背景音乐会有一点卡顿,但卡顿结束后,Camera 会平稳运行并开始录制。
我的代码:
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()
}
我试过的
延迟配置 AVAudioSession.sharedInstance()
我尝试先将 AVAudioSession.sharedInstance
配置为类别 AVAudioSession.Category.playback
,然后在我想开始录制音频时切换到 .playAndRecord
。
这没有用,AVCaptureSessionRuntimeError
事件在启动相机后立即被调用,错误代码为 -10851
,这意味着 kAudioUnitErr_InvalidPropertyValue
。我认为这意味着 AVCaptureAudioDataOutput
不允许从音频会话中录制,但我现在不想这样做 - 它应该只是闲置。
延迟添加 AVCaptureAudioDataOutput
输出
我尝试在开始时不添加音频输出 (AVCaptureAudioDataOutput
),只有在用户开始录制后才“按需”添加它,虽然这对背景音乐来说效果很好(没有开始时口吃,一旦用户开始录制,只有短暂的口吃,正是我想要的),它使预览冻结了很短的时间(因为捕获会话正在通过 beginConfiguration
+ 音频输出添加 + commitConfiguration
)
有谁知道如何实现我在这里尝试做的事情 - 或者 Snapchat 是如何做到的?感谢任何帮助,谢谢!
.mixWithOthers
看起来是避免打扰的正确做法,但默认 AVCaptureSession
将为您配置 AVAudioSession
,因此请设置
captureSession.automaticallyConfiguresApplicationAudioSession = false
阻止它替换您的设置。
属性 的文档告诉我们 AVCaptureSession
不仅仅是设置 .playAndRecord
类别,这一事实对于您的用例可能很重要:
the receiver ensures the application's audio session is set to the PlayAndRecord category, and picks an appropriate microphone and polar pattern to match the video camera being used
终于想通了。我只是专门为音频 input/output 创建了一个单独的 AVCaptureSession
,我将其与主捕获会话的 masterClock
同步。然后我可以 start/stop 即时进行二次捕获会话(在开始录制前不久)
我使用 AVFoundation 创建了一个相机,它能够使用 AVCaptureVideoDataOutput
和 AVCaptureAudioDataOutput
录制视频和音频。我创建我的捕获会话,附加所有输入以及视频和音频数据输出,然后相机闲置。用户现在可以开始视频录制了。
问题
问题在于,在我开始捕获会话 (captureSession.startRunning()
) 后,背景音乐立即断断续续。我认为这是因为一旦捕获会话开始 运行,AVCaptureAudioDataOutput
就会在内部激活 AVAudioSession (AVAudioSession.setActive(...)
),我不希望它这样做。我希望它闲置(并且不提供任何音频输出缓冲区),直到我明确激活音频会话(一旦用户开始录制)。
这真的很烦人,因为相机是我们应用程序的开始屏幕,每次用户打开或关闭应用程序时,他的音乐都会断断续续。
我知道这在某种程度上是可能的,因为 Snapchat 就是这样工作的——你打开应用程序,背景音频会继续流畅地播放。开始录制后,背景音乐会有一点卡顿,但卡顿结束后,Camera 会平稳运行并开始录制。
我的代码:
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()
}
我试过的
延迟配置 AVAudioSession.sharedInstance()
我尝试先将 AVAudioSession.sharedInstance
配置为类别 AVAudioSession.Category.playback
,然后在我想开始录制音频时切换到 .playAndRecord
。
这没有用,AVCaptureSessionRuntimeError
事件在启动相机后立即被调用,错误代码为 -10851
,这意味着 kAudioUnitErr_InvalidPropertyValue
。我认为这意味着 AVCaptureAudioDataOutput
不允许从音频会话中录制,但我现在不想这样做 - 它应该只是闲置。
延迟添加 AVCaptureAudioDataOutput
输出
我尝试在开始时不添加音频输出 (AVCaptureAudioDataOutput
),只有在用户开始录制后才“按需”添加它,虽然这对背景音乐来说效果很好(没有开始时口吃,一旦用户开始录制,只有短暂的口吃,正是我想要的),它使预览冻结了很短的时间(因为捕获会话正在通过 beginConfiguration
+ 音频输出添加 + commitConfiguration
)
有谁知道如何实现我在这里尝试做的事情 - 或者 Snapchat 是如何做到的?感谢任何帮助,谢谢!
.mixWithOthers
看起来是避免打扰的正确做法,但默认 AVCaptureSession
将为您配置 AVAudioSession
,因此请设置
captureSession.automaticallyConfiguresApplicationAudioSession = false
阻止它替换您的设置。
属性 的文档告诉我们 AVCaptureSession
不仅仅是设置 .playAndRecord
类别,这一事实对于您的用例可能很重要:
the receiver ensures the application's audio session is set to the PlayAndRecord category, and picks an appropriate microphone and polar pattern to match the video camera being used
终于想通了。我只是专门为音频 input/output 创建了一个单独的 AVCaptureSession
,我将其与主捕获会话的 masterClock
同步。然后我可以 start/stop 即时进行二次捕获会话(在开始录制前不久)