Hi! I am trying to build an app for band kids to record practice sessions to cloudKit on one viewController & display sessions on a UITableview with the option to play the audio & email the session to a teacher. None of my audio is saving when I try it on my iPhone or displaying, here is the code I have, I have iCloud set up from Capabilities & a container checked. Thank you!
ViewController for recording sessions:
import UIKit
import CoreData
import AVFoundation
class NewPracticeSessionViewController: UIViewController, AVAudioRecorderDelegate, AVAudioPlayerDelegate, UITextFieldDelegate {
var audioRecorder: AVAudioRecorder?
var audioPlayer: AVAudioPlayer?
var recordingSession: AVAudioSession!
@IBOutlet weak var startRecording: UIButton!
@IBOutlet weak var endRecording: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
func setupView() {
let format = DateFormatter()
format.dateFormat = "MM-dd-yyyy"
let currentFileName = "recording-\(format.string(from: NSDate() as Date)).caf"
print(currentFileName)
recordingSession = AVAudioSession.sharedInstance()
do {
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
print("Error on setting up the recorder: \(error.localizedDescription)")
}
startRecording.isEnabled = false
endRecording.isEnabled = true
}
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return paths[0]
}
func loadRecordingUI(){
startRecording.isEnabled = true
startRecording.setTitle("Recording", for: .normal)
startRecording.addTarget(self, action: #selector(setter: startRecording), for: .touchUpInside)
view.addSubview(startRecording)
}
func beginRecording() {
if audioPlayer != nil && ((audioPlayer?.isPlaying) != nil) {
audioPlayer?.stop()
}
if audioRecorder == nil {
let audioFileName =
getDocumentsDirectory().appendingPathComponent("recording.m4a")
print("Recording saved at: "+audioFileName.absoluteString)
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?.isMeteringEnabled = true
audioRecorder?.record()
startRecording.setTitle("Now Recording", for: .normal)
} catch {
finishRecording(success: false)
}
} else {
finishRecording(success: true)
}
}
func finishRecording(success: Bool) {
audioRecorder?.stop()
audioRecorder = nil
if success {
print("Recording successful completed")
} else {
print("Recording Failed")
}
self.performSegue(withIdentifier: "Already Completed", sender: self)
}
@IBAction func startRecording(_ sender: UIButton) {
beginRecording()
}
@IBAction func endRecording(_ sender: UIButton) {
finishRecording(success: true)
func saveTrack(asset: AVURLAsset) {
let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A)
let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
exporter?.outputURL = fileURL
exporter?.exportAsynchronously(completionHandler: {
print(exporter?.status)
print(exporter?.estimatedOutputFileLength)
print(exporter?.maxDuration)
print("Finished Saving File")
})
}
}
UITableView where the saved audio files are displayed, played and emailed:
import UIKit
import AVFoundation
import CloudKit
import CoreData
class ExistingPracticeSessionsTableViewController: UITableViewController, URLSessionDelegate {
var receivedAudio: URL?
var practiceRecordings = [String]()
var player: AVAudioPlayer?
var audioUrl: String = ""
var arrayRecordings = [URL]()
var fileName = "audio_file.m4a"
override func viewDidLoad() {
super.viewDidLoad()
tableView.reloadData()
listRecordings()}
func listRecordings() {
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
do {
let urls = try FileManager.default.contentsOfDirectory(at: documentsDirectory, includingPropertiesForKeys: nil, options: FileManager.DirectoryEnumerationOptions.skipsHiddenFiles)
self.arrayRecordings = urls.filter({ (name: URL) -> Bool in
return name.lastPathComponent.hasSuffix("m4a")
})
} catch let error as NSError {
print(error.localizedDescription)
} catch {
print("Something went wrong listing recordings")
}
}
func playSound(url: URL) {
print("playing\(url)")
do {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
try AVAudioSession.sharedInstance().setActive(true)
self.player = try AVAudioPlayer(contentsOf: url)
player?.play()
} catch let error {
print(error.localizedDescription)
}
}
func getCacheDirectory() -> URL {
let fm = FileManager.default
let docsurl = try! fm.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
return docsurl
}
func getFileURL() -> URL {
let path = getCacheDirectory()
let filePath = path.appendingPathComponent("\(fileName)")
return filePath
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return practiceRecordings.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "Cell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath)
cell.textLabel?.text = practiceRecordings[indexPath.row]
listRecordings()
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
print(practiceRecordings[indexPath.row])
}
Post
Replies
Boosts
Views
Activity
Hello! I am writing an app that let band students record their practice sessions and be able to play them back. I'm not the most experienced developer, but working towards getting there. When trying to play back what I recorded after selecting the cell, I get this error The operation couldn’t be completed. (OSStatus error 2003334207.) in the console. Thank you in advance for help! Here is my code:
import AVFoundation
import UIKit
class ViewController: UIViewController, AVAudioRecorderDelegate, UITableViewDelegate, UITableViewDataSource {
var recordingSession: AVAudioSession!
var audioRecorder: AVAudioRecorder!
var audioPlayer: AVAudioPlayer!
var numberOfRecorders: Int = 0
@IBOutlet weak var myTableView: UITableView!
@IBOutlet weak var startRecordingButton: UIButton!
@IBAction func startRecording(_ sender: UIButton) {
//Check if we have an active recorder
if audioRecorder == nil {
numberOfRecorders += 1
let fileName = getDirectory().appendingPathComponent("\(numberOfRecorders).m4a")
let settings = [AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 1200,
AVNumberOfChannelsKey: 1,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue]
//Start Recording
do {
audioRecorder = try AVAudioRecorder(url: fileName, settings: settings)
audioRecorder.delegate = self
audioRecorder.record()
startRecordingButton.setTitle("Stop Recording", for: .normal)
} catch {
displayAlert(title: "Oop", message: "Recording Failed")
}
} else {
//Stopping audio recording
audioRecorder.stop()
audioRecorder = nil
UserDefaults.standard.set(numberOfRecorders, forKey: "myNumber")
myTableView.reloadData()
startRecordingButton.setTitle("Start Recording", for: .normal)
}
}
override func viewDidLoad() {
super.viewDidLoad()
recordingSession = AVAudioSession.sharedInstance()
if let number: Int = UserDefaults.standard.object(forKey: "myNumber") as? Int {
numberOfRecorders = number
}
AVAudioSession.sharedInstance().requestRecordPermission() {
[weak self] isGranted in
guard let strongSelf = self else {return}
guard isGranted else {
let settingURL = URL(string: UIApplication.openSettingsURLString)!
UIApplication.shared.open(settingURL, options: [:], completionHandler: nil)
return
}
}
}
//Function that gets path to directory
func getDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentDirectory = paths[0]
return documentDirectory
}
//Function that displays an alert
func displayAlert(title: String, message: String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "dismiss", style: .default, handler: nil))
present(alert, animated: true, completion: nil)
}
//MARK: - Tableview Setup
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return numberOfRecorders
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = String(indexPath.row + 1)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let path = getDirectory().appendingPathComponent("\(indexPath.row + 1).m4a")
do {
// Set up the AVAudioSession configuration
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default)
try AVAudioSession.sharedInstance().setActive(true)
// Keep an instance of AVAudioPlayer at the UIViewController level
self.audioPlayer = try AVAudioPlayer(contentsOf: getDirectory())
audioPlayer.play()
} catch let error {
print(error.localizedDescription)
}
}
}