Does anyone know where I can find info on how to record audio in a Swift application? I've been looking at some of the audio playback examples but I can't seem to be able to find anything on implementing the audio recording. Thanks
First you need to import the AVFoundation framework into your view controller. You will need to add three properties to your view controller: a button for the user to tap to start or stop recording, an audio session to manage recording, and an audio recorder to handle the actual reading and saving of data.
In Swift 3
Key = Privacy - Microphone Usage Description and Value = For using microphone
(the apps will crash if you don't provide the value - description why you are asking for the permission)**
Import AVFoundation & AVAudioRecorderDelegate, AVAudioPlayerDelegate
import AVFoundation class RecordVC: UIViewController , AVAudioRecorderDelegate, AVAudioPlayerDelegate
Create button for record audio & play audio , and label for display recording timing & give outlets and action as start_recording , play_recording & declare some variables which we will use later
@IBOutlet var recordingTimeLabel: UILabel! @IBOutlet var record_btn_ref: UIButton! @IBOutlet var play_btn_ref: UIButton! var audioRecorder: AVAudioRecorder! var audioPlayer : AVAudioPlayer! var meterTimer:Timer! var isAudioRecordingGranted: Bool! var isRecording = false var isPlaying = false
In viewDidLoad check record permission
override func viewDidLoad() { super.viewDidLoad() check_record_permission() } func check_record_permission() { switch AVAudioSession.sharedInstance().recordPermission() { case AVAudioSessionRecordPermission.granted: isAudioRecordingGranted = true break case AVAudioSessionRecordPermission.denied: isAudioRecordingGranted = false break case AVAudioSessionRecordPermission.undetermined: AVAudioSession.sharedInstance().requestRecordPermission({ (allowed) in if allowed { self.isAudioRecordingGranted = true } else { self.isAudioRecordingGranted = false } }) break default: break } }
generate path where you want to save that recording as myRecording.m4a
func getDocumentsDirectory() -> URL { let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) let documentsDirectory = paths[0] return documentsDirectory } func getFileUrl() -> URL { let filename = "myRecording.m4a" let filePath = getDocumentsDirectory().appendingPathComponent(filename) return filePath }
Setup the recorder
func setup_recorder() { if isAudioRecordingGranted { let session = AVAudioSession.sharedInstance() do { try session.setCategory(AVAudioSessionCategoryPlayAndRecord, with: .defaultToSpeaker) try session.setActive(true) let settings = [ AVFormatIDKey: Int(kAudioFormatMPEG4AAC), AVSampleRateKey: 44100, AVNumberOfChannelsKey: 2, AVEncoderAudioQualityKey:AVAudioQuality.high.rawValue ] audioRecorder = try AVAudioRecorder(url: getFileUrl(), settings: settings) audioRecorder.delegate = self audioRecorder.isMeteringEnabled = true audioRecorder.prepareToRecord() } catch let error { display_alert(msg_title: "Error", msg_desc: error.localizedDescription, action_title: "OK") } } else { display_alert(msg_title: "Error", msg_desc: "Don't have access to use your microphone.", action_title: "OK") } }
Start recording when button start_recording press & display seconds using updateAudioMeter, & if recording is start then finish the recording
@IBAction func start_recording(_ sender: UIButton) { if(isRecording) { finishAudioRecording(success: true) record_btn_ref.setTitle("Record", for: .normal) play_btn_ref.isEnabled = true isRecording = false } else { setup_recorder() audioRecorder.record() meterTimer = Timer.scheduledTimer(timeInterval: 0.1, target:self, selector:#selector(self.updateAudioMeter(timer:)), userInfo:nil, repeats:true) record_btn_ref.setTitle("Stop", for: .normal) play_btn_ref.isEnabled = false isRecording = true } } func updateAudioMeter(timer: Timer) { if audioRecorder.isRecording { let hr = Int((audioRecorder.currentTime / 60) / 60) let min = Int(audioRecorder.currentTime / 60) let sec = Int(audioRecorder.currentTime.truncatingRemainder(dividingBy: 60)) let totalTimeString = String(format: "%02d:%02d:%02d", hr, min, sec) recordingTimeLabel.text = totalTimeString audioRecorder.updateMeters() } } func finishAudioRecording(success: Bool) { if success { audioRecorder.stop() audioRecorder = nil meterTimer.invalidate() print("recorded successfully.") } else { display_alert(msg_title: "Error", msg_desc: "Recording failed.", action_title: "OK") } }
Play the recording
func prepare_play() { do { audioPlayer = try AVAudioPlayer(contentsOf: getFileUrl()) audioPlayer.delegate = self audioPlayer.prepareToPlay() } catch{ print("Error") } } @IBAction func play_recording(_ sender: Any) { if(isPlaying) { audioPlayer.stop() record_btn_ref.isEnabled = true play_btn_ref.setTitle("Play", for: .normal) isPlaying = false } else { if FileManager.default.fileExists(atPath: getFileUrl().path) { record_btn_ref.isEnabled = false play_btn_ref.setTitle("pause", for: .normal) prepare_play() audioPlayer.play() isPlaying = true } else { display_alert(msg_title: "Error", msg_desc: "Audio file is missing.", action_title: "OK") } } }
When recording is finish enable the play button & when play is finish enable the record button
func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) { if !flag { finishAudioRecording(success: false) } play_btn_ref.isEnabled = true } func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { record_btn_ref.isEnabled = true }
Generalize function for display alert
func display_alert(msg_title : String , msg_desc : String ,action_title : String) { let ac = UIAlertController(title: msg_title, message: msg_desc, preferredStyle: .alert) ac.addAction(UIAlertAction(title: action_title, style: .default) { (result : UIAlertAction) -> Void in _ = self.navigationController?.popViewController(animated: true) }) present(ac, animated: true) }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With