音频会话中断结束后 AVAudioRecorder 不在后台录制
AVAudioRecorder not recording in background after audio session interruption ended
我正在我的应用程序中录制音频,包括前台和后台。我还处理 AVAudioSessionInterruptionNotification 以在中断开始时停止录制并在中断结束时重新开始。虽然在前台它按预期工作,但当应用程序在后台录制并且我接到电话时,它不会在通话结束后再次开始录制。我的代码如下:
- (void)p_handleAudioSessionInterruptionNotification:(NSNotification *)notification
{
NSUInteger interruptionType = [[[notification userInfo] objectForKey:AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
if (interruptionType == AVAudioSessionInterruptionTypeBegan) {
if (self.isRecording && !self.interruptedWhileRecording) {
[self.recorder stop];
self.interruptedWhileRecording = YES;
return;
}
}
if (interruptionType == AVAudioSessionInterruptionTypeEnded) {
if (self.interruptedWhileRecording) {
NSError *error = nil;
[[AVAudioSession sharedInstance] setActive:YES error:&error];
NSDictionary *settings = @{
AVEncoderAudioQualityKey: @(AVAudioQualityMax),
AVSampleRateKey: @8000,
AVFormatIDKey: @(kAudioFormatLinearPCM),
AVNumberOfChannelsKey: @1,
AVLinearPCMBitDepthKey: @16,
AVLinearPCMIsBigEndianKey: @NO,
AVLinearPCMIsFloatKey: @NO
};
_recorder = [[AVAudioRecorder alloc] initWithURL:fileURL settings:settings error:nil];
[self.recorder record];
self.interruptedWhileRecording = NO;
return;
}
}
}
请注意,fileURL 指向 NSDocumentDirectory 子目录中的新 caf 文件。后台模式音频已配置。我也试过 voip 和播放静音,都没有成功。
AVAudioSessionInterruptionTypeEnded 块中的 NSError 是一个 OSStatus 错误 560557684,我还没有找到解决方法。
如有任何帮助,我们将不胜感激。
我添加了以下内容
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
在配置 AVAudioSession 之前它起作用了。还是不知道会出现什么bug。
错误 560557684 是针对 AVAudioSessionErrorCodeCannotInterruptOthers
的。当您的后台应用程序试图激活不与其他音频会话混合的音频会话时,就会发生这种情况。后台应用无法启动不与前台应用的音频会话混合的音频会话,因为这会中断用户当前正在使用的应用的音频。
要解决此问题,请确保将会话类别设置为可混合的类别,例如 AVAudioSessionCategoryPlayback
。还要确保设置类别选项 AVAudioSessionCategoryOptionMixWithOthers
(必需)和 AVAudioSessionCategoryOptionDuckOthers
(可选)。例如:
// background audio *must* mix with other sessions (or setActive will fail)
NSError *sessionError = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback
withOptions:AVAudioSessionCategoryOptionMixWithOthers | AVAudioSessionCategoryOptionDuckOthers
error:&sessionError];
if (sessionError) {
NSLog(@"ERROR: setCategory %@", [sessionError localizedDescription]);
}
错误代码560557684实际上是32位整数中的4个ascii字符'!int'。错误代码列在 AVAudioSession.h 文件中(另请参阅 AVAudioSession):
@enum AVAudioSession error codes
@abstract These are the error codes returned from the AVAudioSession API.
...
@constant AVAudioSessionErrorCodeCannotInterruptOthers
The app's audio session is non-mixable and trying to go active while in the background.
This is allowed only when the app is the NowPlaying app.
typedef NS_ENUM(NSInteger, AVAudioSessionErrorCode)
{
...
AVAudioSessionErrorCodeCannotInterruptOthers = '!int', /* 0x21696E74, 560557684 */
...
当我的应用程序在后台运行时尝试使用 AVSpeechSynthesizer().speak()
时,我遇到了同样的错误。 @progmr 的回答为我解决了这个问题,尽管我也不得不打电话给 AVAudioSession.sharedInstance().setActive(true)
。
为了完整起见,这是我在 Swift 5.
中的代码
在application(_:didFinishLaunchingWithOptions:)
中:
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback,
options: [.mixWithOthers,
.duckOthers])
} catch let error as NSError {
print("Error setting up AVAudioSession : \(error.localizedDescription)")
}
然后在我的视图控制器中:
do {
try AVAudioSession.sharedInstance().setActive(true)
} catch let error as NSError {
print("Error : \(error.localizedDescription)")
}
let speechUtterance = AVSpeechUtterance(string: "Hello, World")
let speechSynth = AVSpeechSynthesizer()
speechSynth.speak(speechUtterance)
注意:当调用 setActive(true)
时,它会降低当时播放的任何其他音乐的音量。之后要调高音量,您需要调用 setActive(false)
- 对我来说,最好的时间是在相应的 AVSpeechSynthesizerDelegate
方法中通知我演讲结束后。
我正在我的应用程序中录制音频,包括前台和后台。我还处理 AVAudioSessionInterruptionNotification 以在中断开始时停止录制并在中断结束时重新开始。虽然在前台它按预期工作,但当应用程序在后台录制并且我接到电话时,它不会在通话结束后再次开始录制。我的代码如下:
- (void)p_handleAudioSessionInterruptionNotification:(NSNotification *)notification
{
NSUInteger interruptionType = [[[notification userInfo] objectForKey:AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
if (interruptionType == AVAudioSessionInterruptionTypeBegan) {
if (self.isRecording && !self.interruptedWhileRecording) {
[self.recorder stop];
self.interruptedWhileRecording = YES;
return;
}
}
if (interruptionType == AVAudioSessionInterruptionTypeEnded) {
if (self.interruptedWhileRecording) {
NSError *error = nil;
[[AVAudioSession sharedInstance] setActive:YES error:&error];
NSDictionary *settings = @{
AVEncoderAudioQualityKey: @(AVAudioQualityMax),
AVSampleRateKey: @8000,
AVFormatIDKey: @(kAudioFormatLinearPCM),
AVNumberOfChannelsKey: @1,
AVLinearPCMBitDepthKey: @16,
AVLinearPCMIsBigEndianKey: @NO,
AVLinearPCMIsFloatKey: @NO
};
_recorder = [[AVAudioRecorder alloc] initWithURL:fileURL settings:settings error:nil];
[self.recorder record];
self.interruptedWhileRecording = NO;
return;
}
}
}
请注意,fileURL 指向 NSDocumentDirectory 子目录中的新 caf 文件。后台模式音频已配置。我也试过 voip 和播放静音,都没有成功。
AVAudioSessionInterruptionTypeEnded 块中的 NSError 是一个 OSStatus 错误 560557684,我还没有找到解决方法。
如有任何帮助,我们将不胜感激。
我添加了以下内容
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
在配置 AVAudioSession 之前它起作用了。还是不知道会出现什么bug。
错误 560557684 是针对 AVAudioSessionErrorCodeCannotInterruptOthers
的。当您的后台应用程序试图激活不与其他音频会话混合的音频会话时,就会发生这种情况。后台应用无法启动不与前台应用的音频会话混合的音频会话,因为这会中断用户当前正在使用的应用的音频。
要解决此问题,请确保将会话类别设置为可混合的类别,例如 AVAudioSessionCategoryPlayback
。还要确保设置类别选项 AVAudioSessionCategoryOptionMixWithOthers
(必需)和 AVAudioSessionCategoryOptionDuckOthers
(可选)。例如:
// background audio *must* mix with other sessions (or setActive will fail)
NSError *sessionError = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback
withOptions:AVAudioSessionCategoryOptionMixWithOthers | AVAudioSessionCategoryOptionDuckOthers
error:&sessionError];
if (sessionError) {
NSLog(@"ERROR: setCategory %@", [sessionError localizedDescription]);
}
错误代码560557684实际上是32位整数中的4个ascii字符'!int'。错误代码列在 AVAudioSession.h 文件中(另请参阅 AVAudioSession):
@enum AVAudioSession error codes
@abstract These are the error codes returned from the AVAudioSession API.
...
@constant AVAudioSessionErrorCodeCannotInterruptOthers
The app's audio session is non-mixable and trying to go active while in the background.
This is allowed only when the app is the NowPlaying app.
typedef NS_ENUM(NSInteger, AVAudioSessionErrorCode)
{
...
AVAudioSessionErrorCodeCannotInterruptOthers = '!int', /* 0x21696E74, 560557684 */
...
当我的应用程序在后台运行时尝试使用 AVSpeechSynthesizer().speak()
时,我遇到了同样的错误。 @progmr 的回答为我解决了这个问题,尽管我也不得不打电话给 AVAudioSession.sharedInstance().setActive(true)
。
为了完整起见,这是我在 Swift 5.
在application(_:didFinishLaunchingWithOptions:)
中:
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback,
options: [.mixWithOthers,
.duckOthers])
} catch let error as NSError {
print("Error setting up AVAudioSession : \(error.localizedDescription)")
}
然后在我的视图控制器中:
do {
try AVAudioSession.sharedInstance().setActive(true)
} catch let error as NSError {
print("Error : \(error.localizedDescription)")
}
let speechUtterance = AVSpeechUtterance(string: "Hello, World")
let speechSynth = AVSpeechSynthesizer()
speechSynth.speak(speechUtterance)
注意:当调用 setActive(true)
时,它会降低当时播放的任何其他音乐的音量。之后要调高音量,您需要调用 setActive(false)
- 对我来说,最好的时间是在相应的 AVSpeechSynthesizerDelegate
方法中通知我演讲结束后。