我正在应用程序中同时在前台和后台录制音频。我还处理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,我没有找到如何解决。
任何帮助将不胜感激。
错误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 */
...
我添加了以下内容
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
在配置AVAudioSession之前,它可以正常工作。仍然不知道可能会出现什么错误。
当我的应用程序在后台使用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 in instruction(_:) : \(error.localizedDescription)")
}
let speechUtterance = AVSpeechUtterance(string: "Hello, World")
let speechSynth = AVSpeechSynthesizer()
speechSynth.speak(speechUtterance)
注意:当调用setActive(true)
时,它会减小当时播放的其他任何东西的音量。要在之后将音量调高,您需要致电setActive(false)
-对我来说,这是最好的时间,一旦我被告知相应的AVSpeechSynthesizerDelegate
方法中的语音已结束。