I am trying to record audio from a record button inside Keyboards View and then play it back to the user with the play button but neither its recording nor it is playing the audio.
Xcode Version: 13.2.1
Here is the error: Screenshot of Error when the record button is tapped
Below is my code for recording and playing the audio:
class AudioRecoder: NSObject, AVAudioRecorderDelegate, AVAudioPlayerDelegate {
var recordingSession: AVAudioSession!
var audioRecorder: AVAudioRecorder!
var audioPlayer = AVAudioPlayer()
func askPermission() {
recordingSession = AVAudioSession.sharedInstance()
do {
try recordingSession.setCategory(.playAndRecord, mode: .default)
try recordingSession.setActive(true)
recordingSession.requestRecordPermission() { [unowned self] allowed in
DispatchQueue.main.async {
if allowed {
print("user has allowed")
} else {
print("user has not allowed")
}
}
}
} catch {
// failed to record!
print("failed to record!")
}
}
func playSound() throws {
let url = getDocumentsDirectory().appendingPathComponent("recording.m4a")
audioPlayer = try AVAudioPlayer(contentsOf: url)
audioPlayer.prepareToPlay()
audioPlayer.play()
}
func startRecording() {
let audioFilename = getDocumentsDirectory().appendingPathComponent("recording.m4a")
let settings = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 12000,
AVNumberOfChannelsKey: 1,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
]
do {
audioRecorder = try AVAudioRecorder(url: audioFilename, settings: settings)
audioRecorder.delegate = self
audioRecorder.record()
//recordButton.setTitle("Tap to Stop", for: .normal)
} catch {
finishRecording(success: false)
}
}
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return paths[0]
}
func finishRecording(success: Bool) {
audioRecorder.stop()
audioRecorder = nil
if success {
//recordButton.setTitle("Tap to Re-record", for: .normal)
} else {
//recordButton.setTitle("Tap to Record", for: .normal)
// recording failed :(
}
}
func recordTapped() {
if audioRecorder == nil {
startRecording()
} else {
finishRecording(success: true)
}
}
func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
if !flag {
finishRecording(success: false)
}
}}
Your code is working correctly actually. I just put your code into an example project and it worked fine.
Make sure you added Microphone Usage Description to Info.plist and I would suggest putting some logs in the code to understand your issue. For example:
Also you can download the container and check in the Documents directory whether it is actually saving the audio file.