问题
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