AVCaptureSession + AVAudioEngine + AVPlayer=来自接收器和扬声器而不是扬声器的低音频

Posted

技术标签:

【中文标题】AVCaptureSession + AVAudioEngine + AVPlayer=来自接收器和扬声器而不是扬声器的低音频【英文标题】:AVCaptureSession + AVAudioEngine + AVPlayer=Low audio coming out of both receiver and speaker instead of the loud speaker 【发布时间】:2021-10-01 10:06:34 【问题描述】:

我设置了一个 AVCaptureSession 和 AVAudiEngine 来录制视频和音频。我正在使用 AVPlayer 播放结果,除了存在音频问题外,它工作正常。

这个问题只出现在我的 iPhone 上,iPad 工作正常(可能是因为它没有接收器)。问题是当我像这样设置我的 AVAudiosession 时:

do 
        try AVAudioSession.sharedInstance().setCategory(.playAndRecord, options: [.defaultToSpeaker])
        try AVAudioSession.sharedInstance().setActive(true, options: .notifyOthersOnDeactivation)
     catch 
        NSLog(logPrefix + "Could not set the category.")
    

音频来自接收器和扬声器,几乎听不见。如果我省略这些选项,音频就会从接收器中出来(如预期的那样)。如果我包含一种模式(voiceChat 或 videoChat),iPad 不喜欢它(采样率不同步)。

你知道让它在扬声器上大声播放的技巧吗?

【问题讨论】:

不要让频率相互抵消。 【参考方案1】:

虽然很奇怪,但对我有用的解决方案涉及两个关键步骤:

    创建一个 AVAudioEngine 并在其输入节点上设置语音处理。 加载 AVPlayer 时,覆盖输出端口。

代码:

let audioSession = AVAudioSession.sharedInstance()
try audioSession.setCategory(.playAndRecord,
                    mode: .videoChat,
                    options: [.defaultToSpeaker,
                              .allowAirPlay,
                              .allowBluetooth])
try audioSession.setActive(true)

let engine = AVAudioEngine()
try engine.inputNode.setVoiceProcessingEnabled(true)

let playerItem = AVPlayerItem(url: ...)
let player = AVPlayer(playerItem: playerItem)
var observer: NSKeyValueObservation? = nil

observer = playerItem.observe(\.status, options:  [.new, .old], changeHandler:  (playerItem, change) in
       if playerItem.status == .readyToPlay 
             try? audioSession.overrideOutputAudioPort(.speaker)
       

player.play()

【讨论】:

以上是关于AVCaptureSession + AVAudioEngine + AVPlayer=来自接收器和扬声器而不是扬声器的低音频的主要内容,如果未能解决你的问题,请参考以下文章

使用 AVCaptureSession 录制视频

使用 AVAsset/AVCaptureSession 裁剪视频

只有背景音乐的 AVCaptureSession

CoreML 使用 AVCaptureSession 返回不同的值

通话时 AVCaptureSession 的“空白”音频

func setupSession() session = AVCaptureSession() session.sessionPreset = AVCaptureSessionPresetPhot