簡體   English   中英

音頻會話中斷結束后,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,我還沒有找到如何解決。

任何幫助將非常感激。

錯誤 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 之前,它起作用了。 還不知道會出現什么bug。

當我的應用程序在后台時嘗試使用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方法中結束時。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM