In Swift 3
- Add framework AVFoundation
- **In info.plist add key value
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) }