AVAudioPlayer NOT playing through speaker after recording with AVAudioRecorder

可紊 提交于 2021-01-07 03:26:58

问题


I'm working on an app that does audio recording and playback of recorded audio. I'm using AVAudioSession to change the category to playAndRecord as well as passing it to defaultToSpeaker.

My problem is, if I launch the app, play an earlier recording, it plays through the bottom (louder) speaker as I want it to and expected BUT if I launch the app and start recording a new memo then play it back, no matter what I do, it will always use the quieter (phone call) speaker that's next to front face camera. I need it to play from the louder speaker (actually all speakers if possible).

NOTE: I'm running iOS 14.2.1, my phone is set to silent mode (usually) though I tried other settings as well. I'm testing on an iPhone 12. Ideally, I'm not really looking for a 3rd party SDK or library solution as I want the playback to be simple and done natively.

This is how I set the audioSession in my viewModel (that's initialized from a viewController):

private func setupAudioSession() {
    do {
        let session = AVAudioSession.sharedInstance()
        try session.setCategory(.playAndRecord, options: [.defaultToSpeaker, .allowBluetooth])
        try session.setActive(true)
        session.requestRecordPermission({ [weak self] allowed in
            guard let self = self else { return }
            if allowed == false {
                self.settingsAlert?()
            }
        })
    } catch {
        debugPrint("error setting up AVAudioSession")
    }
}

This is how I do recording:

func startRecording() {
    guard let audioFileDir = getAudioFilePath(songId: songModel!.id) else { return }
    let audioURLString = audioFileDir.absoluteString + ".m4a"
    guard let audioURL = URL(string: audioURLString) else { return }
    let recordingSettings: [String: Any] = [
        AVFormatIDKey: Int(kAudioFormatLinearPCM),
        AVLinearPCMIsNonInterleaved: false,
        AVSampleRateKey: 44_100.0,
        AVNumberOfChannelsKey: isStereoSupported ? 2 : 1,
        AVLinearPCMBitDepthKey: 16
    ]
    do {
        audioRecorder = try AVAudioRecorder(url: audioURL, settings: recordingSettings)
        audioUrl = audioURL
        audioRecorder?.delegate = self
        audioRecorder?.prepareToRecord()
        audioRecorder?.record()
    } catch {
        audioRecorder = nil
        debugPrint("Problem recording audio: \(error.localizedDescription)")
    }
}

I even included some code from WWDC 2020 for stereo recording and that's what isStereoSupported does.

And this is how I do playback

do {
    if let data = songDoc?.data?.audioData {
        audioPlayer = try AVAudioPlayer(data: data)
    } else if let url = audioUrl {
        audioPlayer = try AVAudioPlayer(contentsOf: url)
    }
    audioPlayer?.delegate = self
    audioPlayer?.play()
    isPlaying = true
} catch {
    audioPlayer = nil
    debugPrint("playback error: \(error.localizedDescription)")
}

Of course I have tried adding things like:

try session.overrideOutputAudioPort(AVAudioSession.PortOverride.speaker)

as well as setting the AVAudioSession each time I play or record. I've tried bunch of other similar things to fix this issue but nothing seems to work.


回答1:


You should set audio session mode to AVAudioSessionModeVideoRecording and set session category options to AVAudioSessionCategoryOptionDefaultToSpeaker

[session setMode:AVAudioSessionModeVideoRecording error:&e]



来源:https://stackoverflow.com/questions/65138879/avaudioplayer-not-playing-through-speaker-after-recording-with-avaudiorecorder

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!