Audio Recording in watchOS Tutorial

Learn how to record audio right in your own watchOS apps! By Soheil Azarpour.

Leave a rating/review
Save for later
Share
You are currently viewing page 2 of 3 of this article. Click here to view the first page.

Background Audio Playback

In watchOS, very much like in iOS, you can specify that your app should use background audio. This lets the system prepare to take over and continue playing the audio file if a user dismisses your media player.

To declare support for background audio, you’ll update the Info.plist for the Watch app. Open TurboMemoWatch\Info.plist, select the Information Property List entry and tap the + button:

Change the value of the new key to UIBackgroundModes. Make sure its type is Array and then expand the key and add a new value named audio. Xcode will most likely change the values to more readable versions:

Adding this key lets the Watch app continue running for the purpose of playing audio. If the key is not present, playback ends when the user stops interacting with your app.

Recording Audio

One of the most exciting features of watchOS is its access to the microphone. Being able to add a voice memo to Turbo Memo on the Apple Watch is definitely something users will appreciate — so let’s do it!

When you start recording, it’s the Watch app that does the recording and has access to the microphone. Prior to watchOS 4, the WatchKit extension had to provide a shared container using App Groups to which both could read and write, allowing the Watch app to write the audio and the WatchKit extension to grab it.

Even though the WatchKit extension code was bundled and copied to the Apple Watch along with the Watch app itself, from the system’s standpoint, they were still two separate processes that were sandboxed within their own containers. In other words, the Watch app and the WatchKit extension didn’t share the same sandbox!

New in watchOS 4, thanks to Unified Process Runtime, both the Watch app and the WatchKit extension run in the same process so they both have access to the same sandbox.

Note: The good news is that if you’re dropping support for watchOS versions prior to watchOS 4, you can simplify your code by removing the code related to communication between App Groups and your app’s container. The bad news is that if you want to have a backward-compatible watchOS app, you need to enable App Groups. To learn more about App Groups, check out the “Sharing Data with Your Containing App” section of Apple’s App Extension Programming Guide: apple.co/1I5YBtZ

The starter project includes a menu item called + Voice that’s accessible in the app’s main interface by force-touching the screen:

In code, it’s hooked up to addVoiceMemoMenuItemTapped() in InterfaceController.swift, and currently does … (surprise) nothing.

It’s time to tune up this code and do some recording.

Open InterfaceController.swift, find the empty implementation of addVoiceMemoMenuItemTapped() and update it as follows:

// 1
let outputURL = MemoFileNameHelper.newOutputURL()
// 2
let preset = WKAudioRecorderPreset.narrowBandSpeech
// 3
let options: [String : Any] =
  [WKAudioRecorderControllerOptionsMaximumDurationKey: 30]
// 4
presentAudioRecorderController(
  withOutputURL: outputURL,
  preset: preset,
  options: options) { 
    [weak self] (didSave: Bool, error: Error?) in
    
    // 5
    guard didSave else { return }
    self?.processRecordedAudio(at: outputURL)
}

This is the action method you’ll call when a user wants to add a new voice memo. Here’s what you’re doing:

  1. Create a new URL by calling MemoFileNameHelper.newOutputURL() which is a convenient helper module. All it does is that it generates a unique file name based on the current date and time, appends .m4a as the file extension to it, and creates a URL based on user’s documentDirectory on the current device — it’s a shared code between the iPhone and the Watch app. This is basically where you’ll save the audio file.
  2. Configure presets for the recorder. See below for more information on the presets you can use.
  3. Create an options dictionary to specify the maximum duration of the recording session. Here, it’s 30 seconds.
  4. Present the system-provided audio recording controller.
  5. In the completion block, if the audio file is successfully saved, you pass it on to a helper method, processRecordedAudio(at:) which will then broadcast it to the iPhone app and update your data source for the interface table.

When you present an audio recording controller, there are a number of things you can specify. First, the preset you select determines the sample and bit rates at which the audio will record:

  • NarrowBandSpeech: As its name implies, this is a good preset for voice memos and voice messages. It has a sample rate of 8 kHz, and it records at a bit rate of 24 kbps with an AAC codec and 128 kbps with an LPCM codec.
  • WideBandSpeech: This preset has a higher sample rate of 16 kHz, and it records at a bit rate of 32 kbps with an AAC codec and 256 kbps with an LPCM codec.
  • HighQualityAudio: This preset has the highest sample rate at 44.1 kHz, and it records at a bit rate of 96 kbps with an AAC codec and 705.6 kbps with an LPCM codec.

You can also specify various recording options:

  • WKAudioRecorderControllerOptionsMaximumDurationKey: You can set the maximum duration of recorded audio clips by passing in a TimeInterval value in seconds. There’s no maximum recording time if you don’t set a value for this key.
  • WKAudioRecorderControllerOptionsAlwaysShowActionTitleKey: You can use this key to pass either true or false to modify the behavior for showing the action button. If you specify false, the audio recorder controller shows the button only after the user has recorded some audio. By default, the action button is always visible.
  • WKAudioRecorderControllerOptionsActionTitleKey: You can use this key to pass in a String to customize the display title of the button that the user taps to accept a recording. By default, the button’s title is Save.
  • WKAudioRecorderControllerOptionsAutorecordKey: By passing a Boolean value for this key, you can change the automatic recording behavior of the audio recorder controller. If you set it to true, once the controller is presented, it automatically starts recording; otherwise, the user has to tap on the record button to start recording. The default value is true.

That’s it! Build and run. Bring up the contextual menu using the force touch gesture and tap on the + Voice button. The app will present you with an audio recording controller. Tap the Save button, and you’ll have recorded your first voice memo on an Apple Watch, using your own code!

If you try recording on a real device, the very first time you present the system-provided audio recording controller, watchOS will ask for the user’s permission.

Very much like in iOS, the user should grant access to the microphone on the Watch. However, unlike iOS, you don’t explicitly ask for user’s permission as there’s no API for that. Instead, the watchOS uses the NSMicrophoneUsageDescription key in the iPhone’s app to present the appropriate UI and ask the user for their permission. If user doesn’t grant access, the audio recorder will still work, but it will only record silence!

Note: At the time of writing this tutorial, the watchOS simulator doesn’t present the dialog asking for the user’s permission. The iPhone simulator, on the other hand, does present the permission dialog.