【发布时间】:2017-06-21 05:28:15
【问题描述】:
我正在制作一个支持视频播放和录制的应用。我总是希望允许背景音频混合,除了在视频播放期间(在播放期间,背景音频应该静音)。因此,我在更改播放状态的同时使用了以下两种方法。当我的 AVPlayer 开始加载时,我调用MuteBackgroundAudio,当我关闭包含它的视图控制器时,我调用ResumeBackgroundAudio。这按预期工作,离开播放后音频成功返回。
问题是,在至少这样做一次之后,每当我使用AVCaptureSession 录制任何内容时,都不会录制任何声音。我的会话配置如下:
AVCaptureDevice *audioDevice = [[AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio] firstObject];
AVCaptureDeviceInput *audioDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:&error];
if (error)
{
NSLog(@"%@", error);
}
if ([self.session canAddInput:audioDeviceInput])
{
[self.session addInput:audioDeviceInput];
}
[self.session setAutomaticallyConfiguresApplicationAudioSession:NO];
// ... videoDeviceInput
注意我没有设置usesApplicationAudioSession,所以默认为YES。
void MuteBackgroundAudio(void)
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
if ([[AVAudioSession sharedInstance] isOtherAudioPlaying] && !isMuted)
{
isMuted = YES;
NSError *error = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord
withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker
error:&error];
if (error)
{
NSLog(@"DEBUG - Set category error %ld, %@", (long)error.code, error.localizedDescription);
}
NSError *error2 = nil;
[[AVAudioSession sharedInstance] setActive:YES
withOptions:0
error:&error2];
if (error2)
{
NSLog(@"DEBUG - Set active error 2 %ld, %@", (long)error.code, error.localizedDescription);
}
}
});
}
void ResumeBackgroundAudio(void)
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
if (isMuted)
{
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *deactivationError = nil;
[audioSession setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&deactivationError];
if (deactivationError)
{
NSLog(@"DEBUG - Failed at deactivating audio session, retrying...");
ResumeBackgroundAudio();
return;
}
isMuted = NO;
NSLog(@"DEBUG - Audio session deactivated");
NSError *categoryError = nil;
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord
withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionMixWithOthers
error:&categoryError];
if (categoryError)
{
NSLog(@"DEBUG - Failed at setting category");
return;
}
NSLog(@"DEBUG - Audio session category set to mix with others");
NSError *activationError = nil;
[audioSession setActive:YES error:&activationError];
if (activationError)
{
NSLog(@"DEBUG - Failed at activating audio session");
return;
}
NSLog(@"DEBUG - Audio session activated");
}
});
}
调试
我注意到,在调用ResumeBackgroundAudio 后,audioSession 总是需要两次尝试才能成功停用。由于AVAudioSession.h 中的这条评论,我的 AVPlayer 似乎没有及时被释放或停止:
请注意,此方法将在链接的应用程序中抛出异常或 在 iOS 8 之后,如果会话在运行时设置为非活动状态,或者 暂停的 I/O(例如音频队列、播放器、录音机、转换器、远程 I/O 等)。
没有声音被记录的事实让我相信audioSession实际上并没有被激活,但我的日志显示它确实被激活了(总是在递归的第二次迭代中)。
我从this post得到了使用递归来解决这个问题的想法。
为了澄清,导致问题的流程如下:
- 在播放 Spotify 的情况下打开应用
- 开始播放应用中的任何内容
- Spotify 静音,开始播放 (
MuteBackgroundAudio) - 播放结束,Spotify 再次开始播放 (
ResumeBackgroundAudio) - 开始录制
- 停止录制,因为没有音频而生气
【问题讨论】:
-
我遇到了这个确切的问题。无论在什么情况下,只有我的音频第一次无法正常工作,我需要删除并重新添加音频输入/输出才能获得任何东西。
标签: ios objective-c avfoundation avaudiosession