Skip to content

Audio Recording Fails to Resume System Audio After Incoming Call Interruption in Background #886

@willonboy

Description

@willonboy

Describe the bug
Problem Description: When I use broadcast to record the screen and system audio (while also capturing mic audio), if a call comes in, regardless of whether I answer the phone or not, the recording of system audio will be interrupted. Afterward, without restarting the app, it will always be unable to record system audio. I investigated the cause, and the issue lies in the method public func capture(appAudio inputBuffer: AVAudioPCMBuffer) in MixerEngineObserver.swift. In this method, the condition engine.isRunning is not met, resulting in the system audio not being mixed and sent. I tried to fix it:

  1. I added pause and start methods to MixerEngineObserver for pausing and starting the audio engine. The specific code is as follows:
extension MixerEngineObserver {
    public func pause() {
        let appNode = _state.read {
            $0.appNode
        }
        guard let engine = appNode.engine else {
            log("Engine is not running engine == nil", .warning)
            return
        }
        try? engine.pause()
        appNode.pause()
    }
    public func start() {
        let appNode = _state.read {
            $0.appNode
        }
        guard let engine = appNode.engine else {
            log("Engine is not running engine == nil", .warning)
            return
        }
        do {
            try engine.start()
        } catch {
            log("Engine start failed \(error)", .error)
        }
        appNode.play()
    }
}
  1. When constructing AudioManager, I added a listener for AVAudioSession.interruptionNotification. When receiving the event, I use the methods added to MixerEngineObserver. The specific code is as follows:
init() {
#if os(iOS) || os(visionOS) || os(tvOS)
        let engineObservers: [any AudioEngineObserver] = [audioSession, mixer]
#else
        let engineObservers: [any AudioEngineObserver] = [mixer]
#endif
    _state = StateSync(State(engineObservers: engineObservers))
    _admDelegateAdapter.audioManager = self
    RTC.audioDeviceModule.observer = _admDelegateAdapter
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleAudioSessionInterruption),
            name: AVAudioSession.interruptionNotification,
            object: AVAudioSession.sharedInstance()
        )
    }
    @objc
    private func handleAudioSessionInterruption(_ notification: Notification) {
        guard
            let info = notification.userInfo,
            let typeValue = info[AVAudioSessionInterruptionTypeKey] as? UInt,
            let type = AVAudioSession.InterruptionType(rawValue: typeValue)
        else { return }
        switch type {
        case .began:
            log("AudioSession interruption began", .info)
            try? AVAudioSession.sharedInstance().setActive(false)
            mixer.pause()
        case .ended:
            let optionsValue =
                info[AVAudioSessionInterruptionOptionKey] as? UInt ?? 0
            let options = AVAudioSession.InterruptionOptions(rawValue: optionsValue)
            if options.contains(.shouldResume) {
                log("AudioSession interruption ended, resuming", .info)
                try? AVAudioSession.sharedInstance().setActive(true)
                mixer.start()
            }
        @unknown default:
            break
        }
    }

Fix Results:

  1. Now, when a call comes in, the recording of system audio will be interrupted, but if the user brings my app to the foreground, the recording of system audio can be restarted.

Issues with the Fix:

  1. The problem is that the user must bring my app to the foreground to resume; if not, it still won't record system audio. The issue is that AVAudioEngine cannot be restarted in the background.

I hope to automatically resume recording system audio even without the user bringing the app to the foreground. Can this be done without using AVAudioEngine for mixing? Thanks!

SDK Version
2.10.1

iOS/macOS Version
iOS17, 18, 26

Xcode Version
Xcode 16+, Xcode 26

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions