Chapters

Hide chapters

SwiftUI Cookbook

Live Edition · iOS 16.4 · Swift 5.8.1 · Xcode 14.3.1

Playing Audio & Video in the Background in SwiftUI
Written by Team Kodeco

There are many scenarios in which you might need to play audio or video in the background. For instance, an app that offers music or podcast streaming like or video playback would require this functionality so that users can continue to listen to the audio or watch videos even when the app is not currently active on the screen.

To enable this functionality in SwiftUI, you can use the AVPlayer class along with the AVPlayerViewController. Let’s create a simple player view that plays a video in the background:

import AVKit

struct PlayerView: UIViewControllerRepresentable {
  var videoURL = URL(string:"https://archive.org/download/ksnn_compilation_master_food_in_space/ksnn_compilation_master_food_in_space_512kb.mp4")!

  func makeUIViewController(context: Context) -> AVPlayerViewController {
    let controller = AVPlayerViewController()
    let player = AVPlayer(url: videoURL)
    controller.player = player
    controller.player?.play()
    controller.allowsPictureInPicturePlayback = true // enables PiP
    return controller
  }

  func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) {}
}

struct ContentView: View {
  var body: some View {
    PlayerView()
  }
}

Your preview should look like this:

You can set an AVPlayer to allow Picture in Picture playback.
You can set an AVPlayer to allow Picture in Picture playback.

This view is a SwiftUI wrapper for AVPlayerViewController. When you initialize this view with a URL, it creates an AVPlayerViewController that plays the video at the specified URL. The allowsPictureInPicturePlayback property is set to true, enabling the video to continue playing in Picture in Picture mode, which is a form of background video playback.

For audio playback, you will need to configure the app’s audio session to continue playing when the app enters the background. This can be done in your main App file by creating an AppDelegate adapter:

import SwiftUI
import AVKit

@main
struct SwiftUITestApp: App {
  @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
  
  var body: some Scene {
    WindowGroup {
      ContentView()
    }
  }
}

// AppDelegate
class AppDelegate: NSObject, UIApplicationDelegate {
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
    do {
      try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [.mixWithOthers, .allowAirPlay])
      print("Playback OK")
      try AVAudioSession.sharedInstance().setActive(true)
      print("Session is Active")
    } catch {
      print(error)
    }
    return true
  }
}

In this code, the audio session category is set to .playback, which is suitable for music playback apps. The mixWithOthers option is also set, allowing your app’s audio to mix with other audio sources, and the allowAirPlay option allows the audio to be streamed to AirPlay devices.

Add the Background Modes capability for your target in Xcode project settings.
Add the Background Modes capability for your target in Xcode project settings.

Note: To play media in the background, you must also configure your app’s Background Modes in the Capabilities section of the project settings. Enable the Audio, AirPlay, and Picture in Picture mode to allow audio and video to continue playing when the app is not in the foreground. Additionally, you’ll need to run this app on a physical device to test background playback.

As you can see, playing audio and video in the background is essential for certain types of apps and can greatly enhance the user experience. By utilizing the AVKit framework and configuring your app’s settings correctly, you can easily add this functionality to your SwiftUI apps.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.