iOS

iOS Programming 101: Record and Play Audio using AVFoundation Framework


Editor’s note: Some of you asked us to write a tutorial about audio recording. This week, we work with Yiqi Shi and Raymond from Purple Development to give you an introduction of AVFoundation framework. Yiqi and Raymond are independent iOS developers and have recently released Voice Memo Wifi that allows users to record voice memo and share it over WiFi.

iOS provides various framework to let you work with sound in your app. One of the frameworks that you can use to play and record audio file is the AV Foundation Framework. In this tutorial, I’ll walk you through the basics of the framework and show you how to manage audio playback, as well as, recording.

To provide you with a working example, I’ll build a simple audio app that allows users to record and play audio. Our primary focus is to demonstrate the AV Foundation framework so the user interface of the app is very simple.

The AV Foundation provides easy ways to deal with audio. In this tutorial, we mainly deal with these two classes:

  • AVAudioPlayer – think of it as an audio player for playing sound files. By using the player, you can play sounds of any duration and in any audio format available in iOS.
  • AVAudioRecorder – an audio recorder for recording audio

Starting with the Project Template

First of all, create a “Single View Application” and name it as “AudioDemo”. To free you from setting up the user interface and code skeleton, you can download the project template from here.

I’ve created a simple UI for you that it only contains three buttons including “Record”, “Stop” and “Play”. The buttons are also linked up with the code.

AudioDemo Project Template

AudioDemo Project Template

Adding AVFoundation Framework

By default, the AVFoundation framework is not bundled in any Xcode project. So you have to add it manually. In the Project Navigator, select the “AudioDemo” project. In the Content Area, select “AudioDemo” under Targets and click “Build Phases”. Expand “Link Binary with Libraries” and click the “+” button to add the “AVFoundation.framework”.

Adding AVFoundation Framework

Adding AVFoundation Framework

To use the AVAudioPlayer and AVAudioRecorder class, we need to import in ViewController.h.

Audio Recording using AVAudioRecorder

First, let’s take a look how we can use AVAudioRecorder to record audio. Add the AVAudioRecorderDelegate protocol and AVAudioPlayerDelegate in the ViewController.h. We’ll explain both delegates as we walk through the code.

Next, declare the instance variables for AVAudioRecorder and AVAudioPlayer in ViewController.m:

The AVAudioRecorder class provides an easy way to record sound in iOS. To use the recorder, you have to prepare a few things:

  • Specify a sound file URL.
  • Set up the audio session.
  • Configure the audio recorder’s initial state.

We’ll do the setup in the “viewDidLoad” method of ViewController.m. Simply edit the method with the following code:

Note: For demo purpose, we skip the error handling. In real app, don’t forget to include proper error handling.

In the above code, we first define the sound file URL for saving the recording. and then configure the audio session. iOS handles audio behaviour of an app by using audio sessions. Upon launch, your app automatically gets an audio session. You can grab such session by calling [AVAudioSession sharedInstance] and configure it. Here, we tell iOS that the app uses “AVAudioSessionCategoryPlayAndRecord” category which enables both audio input and output. We will not go into the details of audio session but you can check out the official document for further details.

The AVAudioRecorder uses a dictionary-based settings for its configuration. In line 21-25, we use the options keys to configure the audio data format, sample rate and number of channels. Lastly, we initiate the audio recorder by calling “prepareToRecord:” method.

Note: For other settings keys, you can refer to AV Foundation Audio Settings Constants.

Implementing Record Button

We’ve completed the audio preparation. Let’s move on to implement the action method of Record button. Before we dive into the code, let me explain how the “Record” button works. When user taps the “Record” button, the app will start recording and the button text will be changed to “Pause”. If user taps the “Pause” button, the app will pause the audio recording till the “Record” is tapped again. The audio recording will only be stopped when user taps the “Stop” button.

Edit the “recordPauseTapped:” method with the following code:

In the above code, we first check whether the audio player is playing. If audio player is playing, we simply stop it by using the “stop:” method. Line 7 of the above code determines if the app is in recording mode. If it’s not in recording mode, the app activates the audio sessions and starts the recording. For recording to work (or sound to play), your audio session must be active.

In general, you can use the following methods of AVAudioRecorder class to control the recording:

  • record – start/resume a recording
  • pause – pause a recording
  • stop – stop a recording

Implementing Stop Button

For the Stop button, we simply call up the “stop:” method to the recorder, followed by deactivating the audio session. Edit the “stopTapped:” method with the following code:

Implementing the AVAudioRecorderDelegate Protocol

You can make use of AVAudioRecorderDelegate protocol to handle audio interruptions (say, a phone call during audio recording) and the completion of recording. In the example, the ViewController is the delegate. The methods defined in AVAudioRecorderDelegate protocol are optional. Here, we’ll only implement the “audioRecorderDidFinishRecording:” method to handle the completion of recording. Add the following code to ViewController.m:

After finishing the recording, we simply change the “Pause” button back to “Record” button.

Playing Sound using AVAudioPlayer

Finally, it comes to the implementation of the “Play” button for audio playback using AVAudioPlayer. In the ViewController.m, edit the “playTapped:” method using the following code:

The above code is very straightforward. Normally, there are a few things to configure an audio player:

  • Initialize the audio play and Assign a sound file to it. In the case, it’s the audio file of the recording (i.e. recorder.url).
  • Designate an audio player delegate object, which handles interruptions as well as the playback-completed event.
  • Call play: method to play the sound file.

Implementing the AVAudioPlayerDelegate Protocol

The delegate of an AVAudioPlayer object must adopt the AVAudioPlayerDelegate protocol. In this case, it’s the ViewController. The delegate allows you to handle interruptions, audio decoding errors and update the user interface when an audio has finished playing. All methods in AVAudioplayerDelegate protocol are optional, however. To demonstrate how it works, we’ll implement the “audioPlayerDidFinishPlaying:” method to display an alert prompt after the completion of audio playback. For usage of other methods, you can refer to the official documentation of AUAudioPlayerDelegate protocol.

Add the following code in ViewController.m:

Compile and Run Your App

You can test audio recording and playback using a physical device or software simulator. If you test the app using actual device (e.g. iPhone), the audio being recorded comes from the device connected by the built-in microphone or headset microphone. On the other hand, if you test the app by using the Simulator, the audio comes from the system’s default audio input device as set in the System Preference.

So go ahead to compile and run the app! Tap “Record” button to start recording. Say something, tap the “Stop” button and then select the “Play” button to listen the playback.

AudioDemo App

AudioDemo App

For your reference, you can download the complete source code from here. Feel free to leave me comment if you have any questions.

This post is contributed by Yiqi Shi and Raymond from Purple Development. Yiqi and Raymond are independent iOS developers and have recently released Voice Memo Wifi that allows users to record voice memo and share it over WiFi.

iOS
Adding Animated Effects to iOS App Using UIKit Dynamics
iOS
Building a Simple Share Extension in iOS 8 App
Tutorial
Managing SQLite Database with SwiftyDB
  • Reem

    ReemReem

    Author Reply

    Amazing tutorial
    thank you so mach


  • Damien

    DamienDamien

    Author Reply

    Great tutorial – very helpful!


  • 망각인간

    Awesome!
    Thanks for simon ng, Thanks for Raymond.
    Thanks to the always helpful.


  • kevin chen

    kevin chenkevin chen

    Author Reply

    Wonderfully, thanks!


  • pantgurra

    pantgurrapantgurra

    Author Reply

    I would like a tutorial how external sound, music, singing, talking etc can trigger an action, animation, image etc. Thanks for the great turorials btw, youre doing a great job!


  • Alex

    AlexAlex

    Author Reply

    That’s great! Would be possible to extend this with a voice recognition engine? E.g. I record 3 messages: 1) hello, 2) bread 3) night and then when I press a “recognize button” the app understands if what am I repeating is “hello” or “bread” or “night”? Mission impossible? 🙂


    • Simon Ng

      Simon NgSimon Ng

      Author Reply

      I am still waiting for Apple to open up Siri API for speech recognition. However, if you’re looking for speech recognition engine, you can take a look at OpenEars: http://www.politepix.com/openears/


  • VladislavKovalyov

    How can I save my recorded audio?


  • onmywy133

    onmywy133onmywy133

    Author Reply

    Why does playing sound not require Audio Session ?


  • Kamran

    KamranKamran

    Author Reply

    how to record more than one msges e.g 1.hello 2. hi 3, country… and how to store these msges in table list and then play selected msges from tablelist …please tell me…thnks in advance


  • Mitchell

    MitchellMitchell

    Author Reply

    I am using XCode 4.2, IOS 5, MacOS 10.6.8.
    Do you have source code for the above combination please?


    • tung

      tungtung

      Author Reply

      go to “Show the File inspector” check autolayout isn’t ticked.


  • Innovative

    InnovativeInnovative

    Author Reply

    How the user will be able to attach the additional recording to the beginning, overlay in the middle or append to the end of the original audio recording.?


  • Aneta Karbowiak

    Hi,
    Ive read your tutoria and its very usefull but I wanted to ask you something more. Ive a project with several collision detections and after each collision appears a number. I added a sound for every number. My problem is that the numbers appears correctly after each collision: 1,2,3,4.... but the sound doesnt follow the numbers. It does like this: four, four, one, three, three…
    Do you know why and how to fix it?


    • Aneta

      AnetaAneta

      Author Reply

      Never mind. I`ve already did it.


  • Thakur

    ThakurThakur

    Author Reply

    By looking at this tutorial Now I would Like to learn something different. Can you make an Audio apps Tutorial which shows Audio Name in Table View and play song with Play Pause Button. Can you Please make a tutorial something like that 🙂


    • sol

      solsol

      Author Reply

      YEAH PLEASE!


  • Slogan

    SloganSlogan

    Author Reply

    Is there a way to modify this code so that instead of recording audio using the microphone (hardware), the record button records sounds that the phone is making/outputting? I have programmed a few buttons to make noises, and I want to be able to record a sequence of those noises and play back that recording.


  • Innovative

    InnovativeInnovative

    Author Reply

    I am running this code in iOS 7, it is not working. May i know how to record and set framerate to some xxfps(eg:24fps).? Thanks in advance.


  • Евгений Михайлов

    Note: For demo purpose, we skip the error handling. In real app, don’t forget to include proper error handling.

    What do you mean by it?


    • velociround

      All parameters which receive an NSError pointer, such as [session setCategory:AVAudioSessionCategoryPlayAndRecord error:nil] have not been properly handling. If an error were to ever occur, you’d have no idea what happened and your application will not work properly (might even crash depending on what you’re trying to do).

      This is still not proper error handling and I don’t recommend using that either, but it will tell you on the console what happened:

      NSError *error;
      [session setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
      if (error) {
      NSLog(@”Erro! %@”, error.debugDescription);
      }


  • Claire

    ClaireClaire

    Author Reply

    Awesome tutorial! Thank you 🙂


  • tung ta

    tung tatung ta

    Author Reply

    thanks, nice tutorial!


  • nagendra

    nagendranagendra

    Author Reply

    thanks, nice tutorial.,.


  • Ваше Онтатиле Масвибилили

    How would i use metering(measuring the level of audio input)?


  • Jimm

    JimmJimm

    Author Reply

    Great intro into AVAudio! Thanks


  • హరి కృష్ణ

    I have a TableView Contains List of Urls and When i did selectRow In the next view AVPlayer should Play,Pause etc….

    my task is that song should be played When it is in Background or When it goes to AnotherView i.e. TableView. I have Some code Like This and i pasted in AppDelegate

    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
    [[AVAudioSession sharedInstance] setActive: YES error: nil];
    [[AVAudioSession sharedInstance] setDelegate:self];

    now its played in background. But it doesn’t play when we back to TableViewController from PlayerView

    Please help me my E-mail is [email protected]


  • harikrishna

    hi


  • Hasan

    HasanHasan

    Author Reply

    Very useful tutorial. Can you please please please do one using Swift language?
    Thanks a lot.


  • John D. Storey

    Thanks 🙂 This was a great tutorial! Keep ’em coming guys


  • Hasan

    HasanHasan

    Author Reply

    Hi, can you please the same tutorial using swift? I couldn’t find any helpful guideline. Thanks


  • harikrishna

    Shell we record the playing song in the Background


  • HelpPlease

    HelpPleaseHelpPlease

    Author Reply

    What would i need to do if i wanted to have two buttons to record separate recordings?
    I’m a beginner…


  • sdfsdf

    sdfsdfsdfsdf

    Author Reply

    u have put that code link, but its empty buttons there oin xcode project….
    check out dear…


  • Fortuna

    FortunaFortuna

    Author Reply

    How can I test the latency of the record audio?


  • alijnclarke

    Got this working perfectly, but i just wondered how i can set it up so that incoming text message notifications are not muted when recording?

    Currently the notification pops up but there is no sound 🙁

    (I know this is most likely a dead thread)


  • Lukasz Rutkowski

    To make the audio louder add this line to the Session setup part:
    [session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];


  • Vimal Raval

    can we test in simulator ?


  • Michael Mork

    I am getting a very uninformative and frustrating error:
    “fatal error: unexpectedly found nil while unwrapping an Optional value”
    when attempting to instantiate the AVAudioRecorder; I am not passing optional values.


  • Davut Temel

    i make a karaoke app. it is recording success (background mp3 and my voice mix) when headphone was not plugin. but headphone plugin and listen record, i cant hear background music (its too low). how can i do that? please help me.


  • Ram Gade

    Ram GadeRam Gade

    Author Reply

    How do i record audio using auxillary. cable on ipad.


  • Manish Patel

    Hi,
    I am using your code with iOS9. Now it is working fine if I record and stop and then play that file.
    But if i modify your code to play previously saved files then it is giving problem with playback in particular case:

    1. Start app and start record.
    2. Without stopping, close app from background
    3. Now start app again.
    4. Tap on Play button (I have modified code to enable playbutton always)
    5. It won’t play audio. Now if i stop recording from step 2 then it will play recording for next app run.

    So you have any solution for this?


    • Balu M

      Balu MBalu M

      Author Reply

      [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord

      withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker

      error:nil];


  • Balu M

    Balu MBalu M

    Author Reply

    >= IOS 9

    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord

    withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker

    error:nil];


  • Gill Steens

    Is it possible to save the recorded data and store it in core data?


  • JKrolling

    JKrollingJKrolling

    Author Reply

    would you make a tutorial about how how play music while capturing video ?


  • rak appdev

    rak appdevrak appdev

    Author Reply

    the link is broken. can anyone send the code to [email protected]


  • Bernard Tai

    Dear author,

    Even though the article is from 2013….any chance I can still access the file? It’s showing 404….


  • Vijay Kumar

    It’s working 🙂
    Thanks for sharing this tutorial


Shares