Claude
Skills
Sign in
Back

avkit

Included with Lifetime
$97 forever

Create media playback experiences using AVKit. Use when adding video players with AVPlayerViewController, enabling Picture-in-Picture, routing media with AirPlay, using SwiftUI VideoPlayer views, configuring transport controls, displaying subtitles and closed captions, or integrating AVFoundation playback with system UI.

Design

What this skill does


# AVKit

High-level media playback UI built on AVFoundation. Provides system-standard
video players, Picture-in-Picture, AirPlay routing, transport controls, and
subtitle/caption display. Targets Swift 6.3 / iOS 26+.

## Contents

- [Setup](#setup)
- [AVPlayerViewController](#avplayerviewcontroller)
- [SwiftUI VideoPlayer](#swiftui-videoplayer)
- [Picture-in-Picture](#picture-in-picture)
- [AirPlay](#airplay)
- [Transport Controls and Playback Speed](#transport-controls-and-playback-speed)
- [Subtitles and Closed Captions](#subtitles-and-closed-captions)
- [Common Mistakes](#common-mistakes)
- [Review Checklist](#review-checklist)
- [References](#references)

## Setup

### Audio Session Configuration

Playback apps need an audio session category and the matching background mode
when they support background audio, AirPlay, or PiP.

1. Enable Background Modes > Audio, AirPlay, and Picture in Picture (the
   `audio` value in `UIBackgroundModes`)
2. Set the audio session category to `.playback`
3. Defer `setActive(true)` until playback begins so you do not interrupt other
   audio prematurely

```swift
import AVFoundation

func configureAudioSessionForPlayback() {
    let session = AVAudioSession.sharedInstance()
    do {
        try session.setCategory(.playback, mode: .moviePlayback)
    } catch {
        print("Audio session category failed: \(error)")
    }
}

func activateAudioSessionWhenPlaybackBegins() {
    do {
        try AVAudioSession.sharedInstance().setActive(true)
    } catch {
        print("Audio session activation failed: \(error)")
    }
}
```

### Imports

```swift
import AVKit          // AVPlayerViewController, VideoPlayer, PiP
import AVFoundation   // AVPlayer, AVPlayerItem, AVAsset
```

## AVPlayerViewController

`AVPlayerViewController` is the standard UIKit player. It provides system
playback controls, PiP, AirPlay, subtitles, and frame analysis out of the box.
Do not subclass it.

### Basic Presentation (Full Screen)

```swift
import AVKit

func presentPlayer(from viewController: UIViewController, url: URL) {
    let player = AVPlayer(url: url)
    let playerVC = AVPlayerViewController()
    playerVC.player = player

    viewController.present(playerVC, animated: true) {
        player.play()
    }
}
```

### Inline (Embedded) Playback

Add `AVPlayerViewController` as a child view controller for inline playback.
Call `addChild`, add the view with constraints, then call `didMove(toParent:)`.

```swift
func embedPlayer(in parent: UIViewController, container: UIView, url: URL) {
    let playerVC = AVPlayerViewController()
    playerVC.player = AVPlayer(url: url)

    parent.addChild(playerVC)
    container.addSubview(playerVC.view)
    playerVC.view.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        playerVC.view.leadingAnchor.constraint(equalTo: container.leadingAnchor),
        playerVC.view.trailingAnchor.constraint(equalTo: container.trailingAnchor),
        playerVC.view.topAnchor.constraint(equalTo: container.topAnchor),
        playerVC.view.bottomAnchor.constraint(equalTo: container.bottomAnchor)
    ])
    playerVC.didMove(toParent: parent)
}
```

### Key Properties

```swift
playerVC.showsPlaybackControls = true                    // Show/hide system controls
playerVC.videoGravity = .resizeAspect                    // .resizeAspectFill to crop
playerVC.entersFullScreenWhenPlaybackBegins = false
playerVC.exitsFullScreenWhenPlaybackEnds = true
playerVC.updatesNowPlayingInfoCenter = true              // Auto-updates MPNowPlayingInfoCenter
```

Use `contentOverlayView` to add non-interactive views (watermarks, logos)
between the video and transport controls.

### Delegate

Adopt `AVPlayerViewControllerDelegate` to respond to full-screen transitions,
PiP lifecycle events, interstitial playback, and media selection changes.
Use the transition coordinator's `animate(alongsideTransition:completion:)` to
synchronize your UI with full-screen animations.

### Display Readiness

Observe `isReadyForDisplay` before showing the player to avoid a black flash:

```swift
let observation = playerVC.observe(\.isReadyForDisplay) { observed, _ in
    if observed.isReadyForDisplay {
        // Safe to show the player view
    }
}
```

## SwiftUI VideoPlayer

The `VideoPlayer` SwiftUI view wraps AVKit's playback UI.

### Basic Usage

```swift
import SwiftUI
import AVKit

struct PlayerView: View {
    @State private var player: AVPlayer?

    var body: some View {
        Group {
            if let player {
                VideoPlayer(player: player)
                    .frame(height: 300)
            } else {
                ProgressView()
            }
        }
        .task {
            let url = URL(string: "https://example.com/video.m3u8")!
            player = AVPlayer(url: url)
        }
    }
}
```

### Video Overlay

Add a SwiftUI overlay above the video content and below the system playback
controls. The overlay can be interactive, but it only receives events the system
controls do not handle.

```swift
VideoPlayer(player: player) {
    VStack {
        Spacer()
        HStack {
            Image("logo")
                .resizable()
                .frame(width: 40, height: 40)
                .padding()
            Spacer()
        }
    }
}
```

### UIKit Hosting for Advanced Control

`VideoPlayer` does not expose all `AVPlayerViewController` properties. For PiP
configuration, delegate callbacks, or playback speed control, wrap
`AVPlayerViewController` in a `UIViewControllerRepresentable`. See the full
pattern in [references/avkit-patterns.md](references/avkit-patterns.md).

## Picture-in-Picture

PiP lets users watch video in a floating window while using other apps.
`AVPlayerViewController` supports PiP automatically once the app is configured,
the device supports PiP, and the current `AVPlayerItem` is playable video
content in an `AVPlayer`-compatible format. Audio-only items, unsupported
containers/codecs, or items that are not ready to display video can make PiP
unavailable even when app and device setup are correct. For custom player UIs,
use `AVPictureInPictureController` directly.

### Prerequisites

1. Audio session category set to `.playback` (see [Setup](#setup))
2. Background Modes > Audio, AirPlay, and Picture in Picture enabled
3. Ready `AVPlayerItem` with playable video media, not audio-only content
4. Current playback context allows PiP; for custom players, observe `isPictureInPicturePossible`

### Standard Player PiP

PiP is enabled by default on `AVPlayerViewController`. Control automatic
activation and inline-to-PiP transitions:

```swift
let playerVC = AVPlayerViewController()
playerVC.player = player

// PiP enabled by default; set false to disable
playerVC.allowsPictureInPicturePlayback = true

// Auto-start PiP when app backgrounds (for inline/non-fullscreen players)
playerVC.canStartPictureInPictureAutomaticallyFromInline = true
```

### Restoring the UI When PiP Stops

When the user taps the restore button in PiP, implement the delegate method to
re-present your player. Call the completion handler with `true` to signal the
system to finish the restore animation.

```swift
func playerViewController(
    _ playerViewController: AVPlayerViewController,
    restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void
) {
    // Re-present or re-embed the player view controller
    present(playerViewController, animated: false) {
        completionHandler(true)
    }
}
```

### Custom Player PiP

For custom player UIs, use `AVPictureInPictureController` with an `AVPlayerLayer`
or sample buffer content source. Check device support before creating PiP UI,
then check the controller's `isPictureInPicturePossible` before starting PiP in
the current playback context. See [references/avkit-patterns.md](references/avkit-patterns.md)
for full custom player and sample buffer PiP patterns.

```swift
guard AVPictureInPictureControlle
Files: 3
Size: 40.8 KB
Complexity: 46/100
Category: Design

Related in Design