Monday, November 9, 2026
HomeiOS DevelopmentConfigure AVAudioSession correctly to combine audio with different app Digital camera Swift...

Configure AVAudioSession correctly to combine audio with different app Digital camera Swift iOS

[ad_1]

My use case is kind of like SnapChat : I launch my app the digicam is show, I can file movies and show/play the video consequence proper after the file.

Then I am attempting to combine different app audio (like Spotify) once I’m recording with the AVAudioSession properties and play the consequence with the blended sound.

First drawback is once I play a Spotify music and open my app, the music is immediately killed by the digicam opening. But when I’m going again to Spotify, play music once more, and return on my app it is working wonderful and I can file accurately with .mixWithOther.

Second drawback once I play the video proper after the file, regardless of my config typically there isn’t any sound or typically there’s a battle between video sound and background.

Right here is my logic :

  • Setup the digicam machine
  • Init audio session class
  • Configure inputs / outputs session
  • Begin session
  • Report a video
  • Cease file and clear audio
  • Cease present session
  • Play the video
    var sessionQueue = DispatchQueue.international()
    var session: AVCaptureSession?
    let photoOutput = AVCapturePhotoOutput()
    let videoOutput = AVCaptureMovieFileOutput()
    var audioDevice: AVCaptureDevice?
    var audioInput: AVCaptureDeviceInput?
    var cameraInput: AVCaptureDeviceInput?
    let audioSession = AVAudioSession.sharedInstance()
    var currentCamera: AVCaptureDevice?

non-public func setupCamera() {        
        currentCamera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, place: cameraPosition)
        if(currentCamera != nil) {
            let sizeCamera = CMVideoFormatDescriptionGetPresentationDimensions(currentCamera!.activeFormat.formatDescription, usePixelAspectRatio: true, useCleanAperture: true);

            aspectRatio = sizeCamera.width / sizeCamera.top
            let minZoom = currentCamera!.minAvailableVideoZoomFactor
            let maxZoom = currentCamera!.maxAvailableVideoZoomFactor
            let minExposure = currentCamera!.minExposureTargetBias
            let maxExposure = currentCamera!.maxExposureTargetBias
            
            initSession()
        }
        else if(initializationCompletion != nil) {
            initializationCompletion!(false)
        }
    }
    
    
    func initSession() {
        print("init digicam session")
        do {
            
            attempt audioSession.setCategory(AVAudioSession.Class.playAndRecord,
                                         choices: [.mixWithOthers,
                                                   .allowBluetoothA2DP,
                                                   .defaultToSpeaker,
                                                   .allowAirPlay
                                                  ])
            attempt audioSession.setActive(true)
            
            cameraInput = attempt AVCaptureDeviceInput(machine: currentCamera!)
            audioDevice = AVCaptureDevice.default(for: AVMediaType.audio)
            audioInput = attempt AVCaptureDeviceInput(machine: audioDevice!)
            
            
            // Assign as soon as or after a stopSession() to deal with the swap digicam case
            if(session == nil) {
                session = AVCaptureSession()
            }
            session!.beginConfiguration()
            session!.automaticallyConfiguresApplicationAudioSession = false
            
            if session!.canAddInput(cameraInput!) {
                session!.addInput(cameraInput!)
            }
            if session!.canAddOutput(photoOutput) {
                session!.addOutput(photoOutput)
            }
            if session!.canAddOutput(videoOutput) {
                session!.addOutput(videoOutput)
            }
            if session!.canAddInput(audioInput!) {
                session!.addInput(audioInput!)
            }
            
            session!.sessionPreset = .hd1920x1080;
            session!.commitConfiguration()
            
            previewLayer.session = session
            
            if(session != nil) {
                self.session!.startRunning()
                self.initializationCompletion!(true)
            }
        }
        catch {
            
        }
    }
    
    
    public func startRecord(completion: ((Bool?)-> Void)? = nil) {
        guard let captureSession = self.session, captureSession.isRunning else {
            print(CameraControllerError.captureSessionIsMissing)
            return
        }

        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        let fileUrl = paths[0].appendingPathComponent("temp.mp4")
        attempt? FileManager.default.removeItem(at: fileUrl)
        DispatchQueue.important.async {
            self.videoOutput.startRecording(to: fileUrl, recordingDelegate: self)
            completion!(true)
        }
    }
    
    
    func stopRecording(completion: ((String?)-> Void)? = nil) {
        guard let captureSession = self.session, captureSession.isRunning else {
            print(CameraControllerError.captureSessionIsMissing)
            return
        }
        // Reset the audio session to default to play the video recorded 
        do {
            attempt audioSession.setActive(false)
            attempt audioSession.setCategory(.ambient)
            attempt audioSession.setActive(true)
        }
        catch {
        }
        DispatchQueue.important.async {
            self.videoOutput.stopRecording()
            self.videoRecordCompletionBlock = completion
            stopSession()
        }
    }
    
    
    func startSession(completion: ((Bool?)->Void)? = nil) {
        print("working the digicam session")
        initializationCompletion = completion
        sessionQueue.async {
            self.setupCamera()
        }
    }
    
    func stopSession(completion: ((Bool?)->Void)? = nil) {
        if(self.session != nil) {
            sessionQueue.async {
                let inputs = self.session!.inputs
                for oldInput:AVCaptureInput in inputs {
                    self.session!.removeInput(oldInput)
                }
                let outputs = self.session!.outputs
                for oldOutput:AVCaptureOutput in outputs {
                    self.session!.removeOutput(oldOutput)
                }
                do {
                    attempt self.audioSession.setCategory(AVAudioSession.Class.playback)
                    attempt self.audioSession.setActive(true)
                } catch {
                    print("error reset audio session")
                }
                
                self.session!.stopRunning()
                if(completion != nil) {
                    completion!(true)
                }
                //previewLayer.removeFromSuperlayer()
            }
        }
    }

I need to open my app with out killing different audio app, file video correctly, show and play the video with out sound conflicts.

The place my logic or implementation is flawed and tips on how to enhance this ?

[ad_2]

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments