In this article we are going to learn about recording sound using Swift 4. Not only recording but also playing the recorded file.
Here we are using AVAudioRecorder for recording audio and AVAudioPlayer for playing the sound.
It's an easy to record using AVAudioRecorder. We will explain step by step how to record an audio.
For testing this we need a device, because simulator don't has microphone.
Before getting into code we need to add Microphone usage description in Info.plist.
Open Info.plist and add 'Privacy - Microphone Usage Description' key, othersiwe app will creash.
Next open ViewController.swift file and import the following AVFoundation framework:
Next add the following properties to the view controller:
Record button is to start or stop the recording, play button is to play the recorded sound, isRecoding is an Bool to know the state, audio Recorder is to handle the actual reading and saving of data and finally player to handle the actual playing or stopping the audio.
Add the following code inside viewDidLoad() method:
Add the following methods for setting up the UI:
Here we added button using auto layout constraints programmatically.
Build and Run, next allow the Microphone for recording. Then the screen looks like below:
Add the following method to record an audio:
Here we created AVAudioSession and creating audio recording. Add the following method for getting the path to save or retrieve the audio.
Next step is to conform to AVAudioRecorderDelegate protocol as follow:
Next add the following code inside record() method:
Just needs to call either startRecording() or finishRecording() depending on the isRecording state.
Next add the following code inside record() method:
Before you're done, there's one more thing to be aware of: iOS might stop your recording for some reason out of your control, such as if a phone call comes in. We use the delegate of the audio recorder, so if this situation crops up you'll be sent a audioRecorderDidFinishRecording() message that you can pass on to finishRecording() like this:
That's it recording an audio successfully completed.
Conform to the AVAudioPlayerDelegate protocol as follow:
Next call the following method inside play() method as follow:
Add the AVAudioPlayerDelegate delegate method audioPlayerDidFinishPlaying() as follow to know whether audio finished playing or interrupted by an reason.
Great we are done, it's time to run and test.
Download sample project with example :
Here we are using AVAudioRecorder for recording audio and AVAudioPlayer for playing the sound.
It's an easy to record using AVAudioRecorder. We will explain step by step how to record an audio.
For testing this we need a device, because simulator don't has microphone.
Getting Started:
Firstly create a new Xcode project and name it as 'VoiceRecorder' and save.Before getting into code we need to add Microphone usage description in Info.plist.
Open Info.plist and add 'Privacy - Microphone Usage Description' key, othersiwe app will creash.
Next open ViewController.swift file and import the following AVFoundation framework:
import AVFoundation
Next add the following properties to the view controller:
var recordButton = UIButton() var playButton = UIButton() var isRecording = false var audioRecorder: AVAudioRecorder? var player : AVAudioPlayer?
Record button is to start or stop the recording, play button is to play the recorded sound, isRecoding is an Bool to know the state, audio Recorder is to handle the actual reading and saving of data and finally player to handle the actual playing or stopping the audio.
Microphone Permission:
Next step is we need to ask the user's permission for accessing the microphone in order to stop malicious apps doing malicious things. If the user grant permission we will add the record and play button UI.Add the following code inside viewDidLoad() method:
view.backgroundColor = UIColor.black // Asking user permission for accessing Microphone AVAudioSession.sharedInstance().requestRecordPermission () { [unowned self] allowed in if allowed { // Microphone allowed, do what you like! self.setUpUI() } else { // User denied microphone. Tell them off! } }
Add the following methods for setting up the UI:
// Adding play button and record buuton as subviews func setUpUI() { recordButton.translatesAutoresizingMaskIntoConstraints = false playButton.translatesAutoresizingMaskIntoConstraints = false view.addSubview(recordButton) view.addSubview(playButton) // Adding constraints to Record button recordButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true recordButton.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true let recordButtonHeightConstraint = recordButton.heightAnchor.constraint(equalToConstant: 50) recordButtonHeightConstraint.isActive = true recordButton.widthAnchor.constraint(equalTo: recordButton.heightAnchor, multiplier: 1.0).isActive = true recordButton.setImage(#imageLiteral(resourceName: "record"), for: .normal) recordButton.layer.cornerRadius = recordButtonHeightConstraint.constant/2 recordButton.layer.borderColor = UIColor.white.cgColor recordButton.layer.borderWidth = 5.0 recordButton.imageEdgeInsets = UIEdgeInsetsMake(-20, -20, -20, -20) recordButton.addTarget(self, action: #selector(record(sender:)), for: .touchUpInside) // Adding constraints to Play button playButton.heightAnchor.constraint(equalToConstant: 60).isActive = true playButton.widthAnchor.constraint(equalTo: playButton.heightAnchor, multiplier: 1.0).isActive = true playButton.trailingAnchor.constraint(equalTo: recordButton.leadingAnchor, constant: -16).isActive = true playButton.centerYAnchor.constraint(equalTo: recordButton.centerYAnchor).isActive = true playButton.setImage(#imageLiteral(resourceName: "play"), for: .normal) playButton.addTarget(self, action: #selector(play(sender:)), for: .touchUpInside) } @objc func record(sender: UIButton) { } @objc func play(sender: UIButton) { }
Here we added button using auto layout constraints programmatically.
Build and Run, next allow the Microphone for recording. Then the screen looks like below:
Start recording:
All buttons setting up done, next step is to start recording.Add the following method to record an audio:
func startRecording() { //1. create the session let session = AVAudioSession.sharedInstance() do { // 2. configure the session for recording and playback try session.setCategory(AVAudioSessionCategoryPlayAndRecord, with: .defaultToSpeaker) try session.setActive(true) // 3. set up a high-quality recording session let settings = [ AVFormatIDKey: Int(kAudioFormatMPEG4AAC), AVSampleRateKey: 44100, AVNumberOfChannelsKey: 2, AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue ] // 4. create the audio recording, and assign ourselves as the delegate audioRecorder = try AVAudioRecorder(url: getAudioFileUrl(), settings: settings) audioRecorder?.delegate = self audioRecorder?.record() //5. Changing record icon to stop icon isRecording = true recordButton.setImage(#imageLiteral(resourceName: "stop"), for: .normal) recordButton.imageEdgeInsets = UIEdgeInsetsMake(5, 5, 5, 5) playButton.isEnabled = false } catch let error { // failed to record! } }
Here we created AVAudioSession and creating audio recording. Add the following method for getting the path to save or retrieve the audio.
// Path for saving/retreiving the audio file func getAudioFileUrl() -> URL{ let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) let docsDirect = paths[0] let audioUrl = docsDirect.appendingPathComponent("recording.m4a") return audioUrl }
Next step is to conform to AVAudioRecorderDelegate protocol as follow:
class ViewController: UIViewController, AVAudioRecorderDelegate {
Next add the following code inside record() method:
Stop Recording:
Add the following method to stop recording an audio.// Stop recording func finishRecording() { audioRecorder?.stop() isRecording = false recordButton.imageEdgeInsets = UIEdgeInsetsMake(-20, -20, -20, -20) recordButton.setImage(#imageLiteral(resourceName: "record"), for: .normal) }
Just needs to call either startRecording() or finishRecording() depending on the isRecording state.
Next add the following code inside record() method:
if isRecording { finishRecording() }else { startRecording() }
Before you're done, there's one more thing to be aware of: iOS might stop your recording for some reason out of your control, such as if a phone call comes in. We use the delegate of the audio recorder, so if this situation crops up you'll be sent a audioRecorderDidFinishRecording() message that you can pass on to finishRecording() like this:
func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) { if flag { finishRecording() }else { // Recording interrupted by other reasons like call coming, reached time limit. } playButton.isEnabled = true }
That's it recording an audio successfully completed.
Play Audio:
For playing sound we are using AVAudioPlayer, so add the following method:func playSound(){ let url = getAudioFileUrl() do { // AVAudioPlayer setting up with the saved file URL let sound = try AVAudioPlayer(contentsOf: url) self.player = sound // Here conforming to AVAudioPlayerDelegate sound.delegate = self sound.prepareToPlay() sound.play() recordButton.isEnabled = false } catch { print("error loading file") // couldn't load file :( } }
Conform to the AVAudioPlayerDelegate protocol as follow:
class ViewController: UIViewController, AVAudioRecorderDelegate, AVAudioPlayerDelegate {
Next call the following method inside play() method as follow:
@objc func play(sender: UIButton) { playSound() }
Add the AVAudioPlayerDelegate delegate method audioPlayerDidFinishPlaying() as follow to know whether audio finished playing or interrupted by an reason.
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { if flag { }else { // Playing interrupted by other reasons like call coming, the sound has not finished playing. } recordButton.isEnabled = true }
Great we are done, it's time to run and test.
Download sample project with example :