Avkit

作者 dpearson26998d90fd121a26無授權條款1.1K 個星標收錄於 2026年10月8日更新於 2026年10月8日儲存庫2 個月前更新

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.

AI 產生的概覽

指導以 Swift 建構 AVKit 媒體播放介面,涵蓋播放器、子母畫面、AirPlay、字幕與播放控制。

功能
此技能提供使用 Apple AVKit 框架在 Swift 中建立媒體播放體驗的參考指引與程式碼模式。內容涵蓋 AVPlayerViewController 的呈現與內嵌、SwiftUI VideoPlayer、子母畫面的設定與還原處理、AirPlay 路由、播放速度與傳輸控制,以及字幕與隱藏式字幕的選擇。它也列出常見錯誤與審查清單,並在隨附的參考檔案中提供進階模式。
適用情境
適用於為 Apple 平台應用程式加入影片播放介面時,例如呈現播放器、內嵌播放、啟用子母畫面或 AirPlay,或處理字幕與隱藏式字幕。也適合在審查現有 AVKit 播放器程式碼、排查常見問題時使用。
執行需求
需要 Apple 平台開發環境,使用 Swift、AVKit 與 AVFoundation;目標為 Swift 6.3 / iOS 26+。未隨附指令碼,僅為說明文件加一份參考檔案。

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

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, PiPimport 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 controlsplayerVC.videoGravity = .resizeAspect                    // .resizeAspectFill to cropplayerVC.entersFullScreenWhenPlaybackBegins = falseplayerVC.exitsFullScreenWhenPlaybackEnds = trueplayerVC.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 SwiftUIimport 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 [blocked].

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)
  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 disableplayerVC.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 [blocked] for full custom player and sample buffer PiP patterns.

swift
guard AVPictureInPictureController.isPictureInPictureSupported() else { return }let pipController = AVPictureInPictureController(playerLayer: playerLayer)pipController.delegate = selfpipController.canStartPictureInPictureAutomaticallyFromInline = true
// Call this from the user's PiP button action, never automatically.if pipController.isPictureInPicturePossible {    pipController.startPictureInPicture()}

Linear Playback During Ads

Interstitial breaks can come from the media stream/manifest, which AVFoundation exposes through AVPlayerItem.interstitialTimeRanges, or from an app-owned AVPlayerInterstitialEventController schedule. Do not assign interstitialTimeRanges directly on iOS. Use requiresLinearPlayback only to prevent seeking during required ad or legal segments:

swift
// During an adplayerVC.requiresLinearPlayback = true
// After the ad completesplayerVC.requiresLinearPlayback = false

AirPlay

AVPlayerViewController supports AirPlay automatically when app configuration, media, routes, and device support allow external playback. No additional code is required when using the standard player. The system displays the AirPlay button in the transport controls when AirPlay-capable devices are available.

AVRoutePickerView

Add a standalone AirPlay route picker button outside the player UI:

swift
import AVKit
func addRoutePicker(to containerView: UIView) {    let routePicker = AVRoutePickerView(frame: CGRect(x: 0, y: 0, width: 44, height: 44))    routePicker.activeTintColor = .systemBlue    routePicker.prioritizesVideoDevices = true  // Show video-capable routes first    containerView.addSubview(routePicker)}

External Playback

AVPlayer allows external playback by default. Leave it enabled for AirPlay, or set it explicitly when code elsewhere may disable it:

swift
player.allowsExternalPlayback = true

Set usesExternalPlaybackWhileExternalScreenIsActive only when you want the player to automatically switch to external playback while an external screen mode is active.

Transport Controls and Playback Speed

Custom Playback Speeds

Provide user-selectable playback speeds in the player UI:

swift
let playerVC = AVPlayerViewController()playerVC.speeds = [    AVPlaybackSpeed(rate: 0.5, localizedName: "Half Speed"),    AVPlaybackSpeed(rate: 1.0, localizedName: "Normal"),    AVPlaybackSpeed(rate: 1.5, localizedName: "1.5x"),    AVPlaybackSpeed(rate: 2.0, localizedName: "Double Speed")]

Use AVPlaybackSpeed.systemDefaultSpeeds to restore the default speed options.

Skipping and Seeking

On iOS, use the standard transport controls and AVPlayer.seek(...) for custom app controls. AVPlayerViewController skipping behavior APIs such as isSkipForwardEnabled, isSkipBackwardEnabled, and skippingBehavior are tvOS-focused; keep them out of iOS player implementations.

Now Playing Integration

AVPlayerViewController updates MPNowPlayingInfoCenter automatically by default. Disable this if you manage Now Playing info manually:

swift
playerVC.updatesNowPlayingInfoCenter = false

Subtitles and Closed Captions

AVKit handles subtitle and closed caption display automatically when the media contains appropriate text tracks. Users control subtitle preferences in Settings > Accessibility > Subtitles & Captioning.

Programmatic Selection

swift
let asset = player.currentItem?.asset
if let group = try await asset?.loadMediaSelectionGroup(for: .legible),   let english = group.options.first(where: { option in       option.locale?.language.languageCode?.identifier == "en"   }) {    player.currentItem?.select(english, in: group)}

allowedSubtitleOptionLanguages, requiresFullSubtitles, and the AVPlayerViewControllerDelegate media-selection callback are tvOS-only. For iOS, load the asset's .legible media selection group and select an option on the AVPlayerItem when the app needs a default.

Providing Subtitle Tracks in HLS

Subtitles and closed captions are embedded in HLS manifests. AVKit reads them from AVMediaSelectionGroup on the AVAsset. For local files, use media that already includes legible subtitle or closed-caption tracks, or author those tracks into the playable asset before presenting it with AVKit.

Common Mistakes

DON'T: Subclass AVPlayerViewController

Apple explicitly states this is unsupported. It may cause undefined behavior or crash on future OS versions.

swift
// WRONGclass MyPlayerVC: AVPlayerViewController { } // Unsupported
// CORRECT: Use composition with delegationlet playerVC = AVPlayerViewController()playerVC.delegate = coordinator

DON'T: Skip audio session configuration for PiP

PiP and background playback depend on the playback audio session category and the Audio, AirPlay, and Picture in Picture background mode.

swift
// WRONG: Default audio sessionlet playerVC = AVPlayerViewController()playerVC.player = player // PiP won't work
// CORRECT: Configure the category, then activate when playback startstry AVAudioSession.sharedInstance().setCategory(.playback, mode: .moviePlayback)try AVAudioSession.sharedInstance().setActive(true)let playerVC = AVPlayerViewController()playerVC.player = player

DON'T: Forget the PiP restore delegate or its completion handler

Without restoreUserInterfaceForPictureInPictureStopWithCompletionHandler, the system cannot return the user to your player. Failing to call completionHandler(true) leaves the system in an inconsistent state.

swift
// WRONG: No delegate method or missing completionHandler call// User taps restore in PiP -> nothing happens or animation hangs
// CORRECTfunc playerViewController(    _ playerViewController: AVPlayerViewController,    restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) {    present(playerViewController, animated: false) {        completionHandler(true)    }}

DON'T: Create AVPlayer in a SwiftUI view's init

Creating the player eagerly causes performance issues. SwiftUI may recreate the view multiple times.

swift
// WRONG: Created on every view initstruct PlayerView: View {    let player = AVPlayer(url: videoURL) // Re-created on every view evaluation
    var body: some View { VideoPlayer(player: player) }}
// CORRECT: Use @State and defer creationstruct PlayerView: View {    @State private var player: AVPlayer?
    var body: some View {        VideoPlayer(player: player)            .task { player = AVPlayer(url: videoURL) }    }}

Review Checklist

  • Audio session category set to .playback with mode: .moviePlayback
  • Audio session activation deferred until playback begins
  • Audio, AirPlay, and Picture in Picture background mode added to UIBackgroundModes
  • AVPlayerViewController is not subclassed
  • PiP tested with supported video media, not only app/device setup
  • PiP restore delegate method implemented and calls completionHandler(true)
  • Custom PiP checks both device support and current isPictureInPicturePossible
  • Custom PiP starts only from explicit user interaction
  • AVPlayer deferred to .task in SwiftUI (not created eagerly)
  • canStartPictureInPictureAutomaticallyFromInline set for inline players
  • requiresLinearPlayback toggled only during required ad/legal segments
  • tvOS-only skipping APIs are not used for iOS transport controls
  • External playback is not disabled accidentally when AirPlay is required
  • Subtitle selection tested with actual media tracks
  • Video gravity set appropriately (.resizeAspect vs .resizeAspectFill)
  • isReadyForDisplay observed before showing the player view
  • Error handling for network-streamed content (HLS failures, timeouts)

References

來源與署名

來源:dpearson2699/swift-ios-skills位於skills/avkit提交8d90fd1

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架

更多來自 dpearson2699/swift-ios-skills 的技能

Widgetkit

dpearson2699

指導實作、審查與改進 iOS、iPadOS、watchOS 與 CarPlay 上的 WidgetKit 小工具與控制項。

Software Development1.1K2 個月前更新

Weatherkit

dpearson2699

指導 iOS 開發者使用 WeatherService 取得 WeatherKit 預報、警報與署名資訊。

Software Development1.1K2 個月前更新

Vision Framework

dpearson2699

Implement computer vision features including text recognition (OCR), face detection, barcode scanning, image segmentation, object tracking, and document scanning in iOS apps. Covers both the modern Swift-native Vision API (iOS 18+) and legacy VNRequest patterns, VisionKit DataScannerViewController for live camera scanning, and CoreMLRequest/VNCoreMLRequest for custom model inference. Use when adding OCR, barcode scanning, face detection, or custom Core ML model inference with Vision.

待分類1.1K2 個月前更新

Tipkit

dpearson2699

Implement and review Apple TipKit feature-discovery UI for iOS 17+ apps. Use when adding or auditing in-app tips, contextual help, coach marks, Tip, TipView, popoverTip, rules, events, actions, display frequency, testing overrides, reusable tip identifiers, or iOS 18+ TipGroup and CloudKit tip sync; avoid for generic SwiftUI navigation or layout outside tip presentation.

待分類1.1K2 個月前更新

Tabletopkit

dpearson2699

指導使用 TabletopKit 在 visionOS 上打造多人空間桌遊,涵蓋棋具、座位、動作與 RealityKit 算繪。

Software Development1.1K2 個月前更新

Swiftui Webkit

dpearson2699

指導在 iOS 26 及更新版本的 SwiftUI App 中使用 WebKit for SwiftUI 嵌入與控制網頁內容。

Software Development1.1K2 個月前更新