AVCaptureSession 和 AVAudioSession 在播放背景音乐时录制视频只能工作一次

Posted

技术标签:

【中文标题】AVCaptureSession 和 AVAudioSession 在播放背景音乐时录制视频只能工作一次【英文标题】:AVCaptureSession and AVAudioSession recording video while background music playing only works once 【发布时间】:2017-09-15 03:25:42 【问题描述】:

看了这个问题后:AVAudiosession AVAudioSessionCategoryPlayAndRecord glitch,我试图尝试让视频录制与背景音乐正常播放。我正在解决录制开始时和结束时出现的音频故障,并且在第一次录制时它工作正常。但是如果我再次尝试录制,音乐就会停止。

有什么想法吗?

这是我的代码的 sn-p:

    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()
    

这是开始录制的代码:

    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()

并停止录制:

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

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

【问题讨论】:

你有可以链接到的可运行代码sn-p吗? 你演奏的音乐怎么样?我使用了AVAudioEngine,您的代码可以正常使用。 【参考方案1】:

我正在做一个几乎相同的项目:录制视频并播放背景音频。 (在 Xamarin 中)

在我的代码中,我在 onViewLoad 中进行 AudioSession 设置。

在将类别设置为 PlayAndRecord 之前,我还会执行 audioSession.SetActive(false)。也许你应该在开始/停止录制时试试这个。

伯努瓦

【讨论】:

【参考方案2】:

在我看来,这与您的AVAudioSession 有关。停止录制时,不要将 audioSession 设置为非活动状态。当您在开始新录制时更改 AVAudioSession 类别时,这会导致立即更改路线。

尝试在停止录制时将AVAudioSession 设置为非活动状态。

另外,不同的AVAudioSession 类别对 AirPlay 的影响也不同。

取自

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

音频会话类别 AVAudioSessionCategoryPlayAndRecord 仅支持 AirPlay 的镜像变体”和

"仅音频会话播放类别(AVAudioSessionCategoryAmbient、AVAudioSessionCategorySoloAmbient 和 AVAudioSessionCategoryPlayback)支持 AirPlay 的镜像和非镜像变体。 "

我建议阅读一下 Apple 文档中的 AVAudioSession,因为有时需要经过深思熟虑才能控制 AVAudioSession 本身。

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

【讨论】:

【参考方案3】:

记得在停用时使用 .notifyOthersOnDeactivation 标志调用 false:

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

否则其他在后台播放音乐的应用程序将不知道在您的会话完成后重新打开他们的音乐。

【讨论】:

以上是关于AVCaptureSession 和 AVAudioSession 在播放背景音乐时录制视频只能工作一次的主要内容,如果未能解决你的问题,请参考以下文章

如何让 AVCaptureSession 和 AVPlayer 尊重 AVAudioSessionCategoryAmbient?

为啥使用 AVCaptureSession、AVAssetWriter 和 AVPlayer 录制和回放视频会卡顿?

如何在 AVCaptureSession 上设置音频采样率?

如何正确清理 AVCaptureSession 和 AVCaptureVideoPreviewLayer

使用 AVCaptureSession 录制视频

从同一个 AVCaptureSession 拍摄视频和照片时应用程序崩溃?