Wiz
Wiz

Reputation: 4875

AVCaptureSession and AVAudioSession recording video while background music playing only works once

After looking at this question: AVAudioSession AVAudioSessionCategoryPlayAndRecord glitch, i tried to take a stab at trying to get video recording with background music playing working correctly. I'm settling for the audio glitch when recording starts, and when it ends, and it works fine the first time the recording happens. But if I try to record again, the music will stop.

Any ideas why?

Here's a snippet of my code:

    captureSession = AVCaptureSession()
    captureSession?.automaticallyConfiguresApplicationAudioSession = false
    captureSession?.usesApplicationAudioSession = true

    guard let captureSession = self.captureSession else {
        print("Error making capture session")
        return;
    }

    captureSession.sessionPreset = AVCaptureSessionPresetHigh

    self.camera = self.defaultBackCamera()
    self.audioDeviceInput = try? AVCaptureDeviceInput(device: getAudioDevice())

    cameraInput = try AVCaptureDeviceInput(device: camera)
    captureSession.beginConfiguration()
    if captureSession.inputs.count > 0 {
        return
    }
    if captureSession.canAddInput(cameraInput) {
        captureSession.addInput(cameraInput)
        if captureSession.outputs.count == 0 {
            photoOutput = AVCapturePhotoOutput()
            if captureSession.canAddOutput(photoOutput!) {
                captureSession.addOutput(self.photoOutput!)
            }
    }
    captureSession.commitConfiguration()
    if !captureSession.isRunning {
        captureSession.startRunning()
        self.previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        self.previewLayer!.videoGravity = AVLayerVideoGravityResizeAspect
        self.previewLayer!.connection.videoOrientation = .portrait
        self.previewLayer!.frame = cameraView.layer.bounds
        self.cameraView.layer.addSublayer(self.previewLayer!)
        captureSession.beginConfiguration()
        videoFileOut = AVCaptureMovieFileOutput()
        if (captureSession.canAddOutput(videoFileOut)) {
            captureSession.addOutput(videoFileOut)
            if (videoFileOut?.connection(withMediaType: AVMediaTypeVideo).isVideoStabilizationSupported)! {
                videoFileOut?.connection(withMediaType: AVMediaTypeVideo).preferredVideoStabilizationMode = .cinematic
            }
        }
        captureSession.commitConfiguration()
    }

This is the code to start recording:

    let audioSession = AVAudioSession.sharedInstance()
    try! audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord,
                                                    with: [.mixWithOthers, .allowBluetoothA2DP, .allowAirPlay])
    try! audioSession.setActive(true)
    captureSession?.beginConfiguration()
    if (captureSession?.canAddInput(audioDeviceInput!))! {
        captureSession?.addInput(audioDeviceInput!)
    }
    captureSession?.commitConfiguration()

And to stop recording:

    let audioSession = AVAudioSession.sharedInstance()
    try! audioSession.setCategory(AVAudioSessionCategoryAmbient, with: [.mixWithOthers, .allowAirPlay])

    captureSession?.beginConfiguration()
    captureSession?.removeInput(audioDeviceInput)
    captureSession?.commitConfiguration()

Upvotes: 10

Views: 4283

Answers (3)

Micro
Micro

Reputation: 10891

Remember to call false with the .notifyOthersOnDeactivation flag when deactivating:

try AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)

Otherwise other apps playing music in the background will not know to turn their music back on when your session is done.

Upvotes: 0

nullforlife
nullforlife

Reputation: 1414

It seems to me this has to do with your AVAudioSession. You do not set the audioSession to inactive when you are stopping the recording. This results in an immediate route change when you change the AVAudioSession category when starting a new recording.

Try setting the AVAudioSession inactive when stopping the recording.

Also different AVAudioSession categories have different impact on AirPlay.

Fetched from

https://developer.apple.com/documentation/avfoundation/avaudiosession/audio_session_categories

"The audio session category AVAudioSessionCategoryPlayAndRecord supports only the mirrored variant of AirPlay" and

"The audio session playback-only categories (AVAudioSessionCategoryAmbient, AVAudioSessionCategorySoloAmbient and AVAudioSessionCategoryPlayback) support both the mirrored and non-mirrored variants of AirPlay. "

I recommend a little reading on AVAudioSession in the Apple docs since just controlling the AVAudioSession itself sometimes need to be really well thought-out.

https://developer.apple.com/documentation/avfoundation/avaudiosession

Upvotes: 3

baberone
baberone

Reputation: 124

I'm working on a project where I have to do almost the same: record video with background audio playing. (in Xamarin)

In my code I do the AudioSession setup in the onViewLoad.

I also do audioSession.SetActive(false) before setting the catogory to PlayAndRecord. Maybe you should try this when starting/stopping the recording.

Benoit

Upvotes: 3

Related Questions