Communitygithub.com

Compétences AVKit pour iOS

Créez des expériences de lecture multimédia avec AVKit. Utilisez cette compétence pour ajouter des lecteurs vidéo avec AVPlayerViewController, activer le Picture-in-Picture, router le contenu avec AirPlay, utiliser les vues SwiftUI VideoPlayer, configurer les contrôles de transport, afficher les sous-titres et le légendage, ou intégrer la lecture AVFoundation avec l'interface système.

Qu'est-ce que Compétences AVKit pour iOS ?

Cette compétence fournit des directives complètes pour implémenter des expériences de lecture multimédia de haut niveau sur iOS en utilisant le framework AVKit. Elle est conçue pour les développeurs qui créent des applications iOS natives avec UIKit ou SwiftUI, et qui ont besoin d'une intégration robuste de la lecture vidéo avec les contrôles système standard, le Picture-in-Picture (PiP), le routage AirPlay et la gestion des sous-titres. La compétence couvre la configuration essentielle de la session audio, l'utilisation de `AVPlayerViewController` pour la lecture plein écran et intégrée, la vue `VideoPlayer` SwiftUI pour les interfaces déclaratives modernes, et les techniques avancées de PiP et AirPlay. Elle inclut également des sections détaillées sur la configuration des vitesses de lecture personnalisées, le comportement de saut, l'intégration avec le centre d'informations 'Now Playing', et la gestion des pistes de sous-titres et de légendes. Des exemples de code Swift concrets sont fournis pour chaque cas d'utilisation, ainsi que des conseils sur les erreurs courantes à éviter (comme le sous-classement de `AVPlayerViewController` ou l'oubli de la configuration de PiP) et une checklist de revue pour assurer une implémentation correcte. La compétence s'applique à toute application iOS 26+ utilisant Swift 6.3.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/JordanCoin/ios-skills-collection/tree/HEAD/skills/dpearson2699--avkit

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

AVKit

Interface de lecture multimédia haut niveau basée sur AVFoundation. Fournit des lecteurs vidéo standard du système, le Picture-in-Picture, le routage AirPlay, les contrôles de transport et l'affichage des sous-titres/légendes. Cible Swift 6.3 / iOS 26+.

Sommaire

Configuration

Configuration de la session audio

Configurez la session audio et les modes d'arrière-plan avant toute lecture. Sans cela, le PiP et l'audio en arrière-plan échouent silencieusement.

  1. Ajoutez le mode d'arrière-plan audio à UIBackgroundModes dans Info.plist
  2. Définissez la catégorie de la session audio sur .playback
import AVFoundation

func configureAudioSession() {
    let session = AVAudioSession.sharedInstance()
    do {
        try session.setCategory(.playback, mode: .moviePlayback)
        try session.setActive(true)
    } catch {
        print("La configuration de la session audio a échoué : \(error)")
    }
}

Imports

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

AVPlayerViewController

AVPlayerViewController est le lecteur standard UIKit. Il fournit les contrôles de lecture système, le PiP, AirPlay, les sous-titres et l'analyse d'image prêts à l'emploi. Ne le sous-classez pas.

Présentation de base (plein écran)

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()
    }
}

Lecture intégrée (inline)

Ajoutez AVPlayerViewController comme contrôleur enfant pour une lecture intégrée. Appelez addChild, ajoutez la vue avec des contraintes, puis appelez didMove(toParent:).

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)
}

Propriétés clés

playerVC.showsPlaybackControls = true                    // Afficher/masquer les contrôles système
playerVC.videoGravity = .resizeAspect                    // .resizeAspectFill pour recadrer
playerVC.entersFullScreenWhenPlaybackBegins = false
playerVC.exitsFullScreenWhenPlaybackEnds = true
playerVC.updatesNowPlayingInfoCenter = true              // Met à jour automatiquement MPNowPlayingInfoCenter

Utilisez contentOverlayView pour ajouter des vues non interactives (filigranes, logos) entre la vidéo et les contrôles de transport.

Délégué

Adoptez AVPlayerViewControllerDelegate pour répondre aux transitions plein écran, aux événements du cycle de vie PiP, à la lecture interstitielle et aux changements de sélection de média. Utilisez le coordinateur de transition animate(alongsideTransition:completion:) pour synchroniser votre interface utilisateur avec les animations plein écran.

État d'affichage prêt

Observez isReadyForDisplay avant d'afficher le lecteur pour éviter un flash noir :

let observation = playerVC.observe(\.isReadyForDisplay) { observed, _ in
    if observed.isReadyForDisplay {
        // Sécurisé pour afficher la vue du lecteur
    }
}

SwiftUI VideoPlayer

La vue SwiftUI VideoPlayer encapsule l'interface de lecture d'AVKit.

Utilisation de base

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)
        }
    }
}

Superposition vidéo

Ajoutez une superposition SwiftUI non interactive sur le contenu vidéo.

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

Hébergement UIKit pour un contrôle avancé

VideoPlayer n'expose pas toutes les propriétés de AVPlayerViewController. Pour la configuration PiP, les callbacks délégués ou le contrôle de la vitesse de lecture, encapsulez AVPlayerViewController dans un UIViewControllerRepresentable. Voir le modèle complet dans references/avkit-patterns.md.

Picture-in-Picture

Le PiP permet aux utilisateurs de regarder une vidéo dans une fenêtre flottante tout en utilisant d'autres applications. AVPlayerViewController prend en charge le PiP automatiquement une fois la session audio configurée. Pour les interfaces utilisateur personnalisées, utilisez directement AVPictureInPictureController.

Prérequis

  1. Catégorie de session audio définie sur .playback (voir Configuration)
  2. Mode d'arrière-plan audio dans UIBackgroundModes

PiP du lecteur standard

Le PiP est activé par défaut sur AVPlayerViewController. Contrôlez l'activation automatique et les transitions inline-vers-PiP :

let playerVC = AVPlayerViewController()
playerVC.player = player

// PiP activé par défaut ; définir false pour désactiver
playerVC.allowsPictureInPicturePlayback = true

// Démarrer automatiquement le PiP lorsque l'application passe en arrière-plan (pour les lecteurs inline/non plein écran)
playerVC.canStartPictureInPictureAutomaticallyFromInline = true

Restaurer l'interface utilisateur lorsque le PiP s'arrête

Lorsque l'utilisateur appuie sur le bouton de restauration dans PiP, implémentez la méthode déléguée pour représenter votre lecteur. Appelez le gestionnaire d'achèvement avec true pour signaler au système de terminer l'animation de restauration.

func playerViewController(
    _ playerViewController: AVPlayerViewController,
    restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void
) {
    // Ré-afficher ou ré-intégrer le contrôleur de vue du lecteur
    present(playerViewController, animated: false) {
        completionHandler(true)
    }
}

PiP du lecteur personnalisé

Pour les interfaces utilisateur personnalisées, utilisez AVPictureInPictureController avec un AVPlayerLayer ou une source de contenu basée sur un échantillon tampon. Vérifiez d'abord isPictureInPictureSupported(). Voir references/avkit-patterns.md pour les modèles complets de lecteur personnalisé et de PiP basé sur un échantillon tampon.

guard AVPictureInPictureController.isPictureInPictureSupported() else { return }
let pipController = AVPictureInPictureController(playerLayer: playerLayer)
pipController.delegate = self
pipController.canStartPictureInPictureAutomaticallyFromInline = true

Lecture linéaire pendant les publicités

Empêchez la recherche pendant les publicités ou les avis légaux en basculant requiresLinearPlayback :

// Pendant une publicité
playerVC.requiresLinearPlayback = true

// Une fois la publicité terminée
playerVC.requiresLinearPlayback = false

AirPlay

AVPlayerViewController prend en charge AirPlay automatiquement. Aucun code supplémentaire n'est nécessaire lors de l'utilisation du lecteur standard. Le système affiche le bouton AirPlay dans les contrôles de transport lorsque des appareils compatibles AirPlay sont disponibles.

AVRoutePickerView

Ajoutez un bouton de sélecteur d'itinéraire AirPlay autonome en dehors de l'interface du lecteur :

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  // Afficher d'abord les itinéraires vidéo compatibles
    containerView.addSubview(routePicker)
}

Activation de la lecture externe

Assurez-vous que AVPlayer permet la lecture externe (activée par défaut) :

player.allowsExternalPlayback = true
player.usesExternalPlaybackWhileExternalScreenIsActive = true

Contrôles de transport et vitesse de lecture

Vitesses de lecture personnalisées

Fournissez des vitesses de lecture sélectionnables par l'utilisateur dans l'interface du lecteur :

let playerVC = AVPlayerViewController()
playerVC.speeds = [
    AVPlaybackSpeed(rate: 0.5, localizedName: "Demi-vitesse"),
    AVPlaybackSpeed(rate: 1.0, localizedName: "Normale"),
    AVPlaybackSpeed(rate: 1.5, localizedName: "1.5x"),
    AVPlaybackSpeed(rate: 2.0, localizedName: "Double vitesse")
]

Utilisez AVPlaybackSpeed.systemDefaultSpeeds pour restaurer les options de vitesse par défaut.

Comportement de saut

Configurez les commandes de saut avant/arrière :

playerVC.isSkipForwardEnabled = true
playerVC.isSkipBackwardEnabled = true

Intégration Now Playing

AVPlayerViewController met à jour MPNowPlayingInfoCenter automatiquement par défaut. Désactivez cette option si vous gérez manuellement les informations Now Playing :

playerVC.updatesNowPlayingInfoCenter = false

Sous-titres et légendes

AVKit gère automatiquement l'affichage des sous-titres et des légendes lorsque le média contient des pistes de texte appropriées. Les utilisateurs contrôlent les préférences de sous-titres dans Réglages > Accessibilité > Sous-titres et légendage.

Restreindre les langues des sous-titres

// Afficher uniquement les options de sous-titres en anglais et en espagnol
playerVC.allowedSubtitleOptionLanguages = ["en", "es"]

Exiger les sous-titres

Forcer l'affichage permanent des sous-titres (l'utilisateur ne peut pas les désactiver) :

playerVC.requiresFullSubtitles = true

Sélection de média (délégué)

Réagissez au changement de sélection de piste de sous-titres ou audio par l'utilisateur :

func playerViewController(
    _ playerViewController: AVPlayerViewController,
    didSelect mediaSelectionOption: AVMediaSelectionOption?,
    in mediaSelectionGroup: AVMediaSelectionGroup
) {
    if let option = mediaSelectionOption {
        print("Sélectionné : \(option.displayName)")
    }
}

Fournir des pistes de sous-titres dans HLS

Les sous-titres et légendes sont intégrés dans les manifests HLS. AVKit les lit à partir de AVMediaSelectionGroup sur l'AVAsset. Pour les fichiers locaux, utilisez AVMutableComposition pour ajouter des pistes AVMediaCharacteristic.legible.

Erreurs courantes

NE PAS : Sous-classer AVPlayerViewController

Apple déclare explicitement que cela n'est pas pris en charge. Cela peut provoquer un comportement indéfini ou un crash sur les futures versions du système d'exploitation.

// FAUX
class MyPlayerVC: AVPlayerViewController { } // Non pris en charge

// CORRECT : Utiliser la composition avec délégation
let playerVC = AVPlayerViewController()
playerVC.delegate = coordinator

NE PAS : Ignorer la configuration de la session audio pour PiP

Le PiP échoue silencieusement si la session audio n'est pas définie sur .playback. L'audio en arrière-plan cesse également de fonctionner.

// FAUX : Session audio par défaut
let playerVC = AVPlayerViewController()
playerVC.player = player // PiP ne fonctionnera pas

// CORRECT : Configurer d'abord la session audio
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .moviePlayback)
try AVAudioSession.sharedInstance().setActive(true)
let playerVC = AVPlayerViewController()
playerVC.player = player

NE PAS : Oublier le délégué de restauration PiP ou son gestionnaire d'achèvement

Sans restoreUserInterfaceForPictureInPictureStopWithCompletionHandler, le système ne peut pas ramener l'utilisateur à votre lecteur. Ne pas appeler completionHandler(true) laisse le système dans un état incohérent.

// FAUX : Pas de méthode déléguée ou appel manquant à completionHandler
// L'utilisateur appuie sur restaurer dans PiP -> rien ne se passe ou l'animation se bloque

// CORRECT
func playerViewController(
    _ playerViewController: AVPlayerViewController,
    restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void
) {
    present(playerViewController, animated: false) {
        completionHandler(true)
    }
}

NE PAS : Créer AVPlayer dans l'initialiseur d'une vue SwiftUI

Créer le lecteur avec empressement provoque des problèmes de performances. SwiftUI peut recréer la vue plusieurs fois.

// FAUX : Créé à chaque initialisation de vue
struct PlayerView: View {
    let player = AVPlayer(url: videoURL) // Recréé à chaque évaluation de vue

    var body: some View { VideoPlayer(player: player) }
}

// CORRECT : Utiliser @State et différer la création
struct PlayerView: View {
    @State private var player: AVPlayer?

    var body: some View {
        VideoPlayer(player: player)
            .task { player = AVPlayer(url: videoURL) }
    }
}

Checklist de revue

  • Catégorie de session audio définie sur .playback avec mode: .moviePlayback
  • Mode d'arrière-plan audio ajouté à UIBackgroundModes dans Info.plist
  • AVPlayerViewController n'est pas sous-classé
  • Méthode déléguée de restauration PiP implémentée et appelle completionHandler(true)
  • AVPlayer différé avec .task dans SwiftUI (pas créé avec empressement)
  • canStartPictureInPictureAutomaticallyFromInline défini pour les lecteurs intégrés
  • requiresLinearPlayback basculé uniquement pendant les segments publicitaires/légaux requis
  • allowsExternalPlayback activé sur AVPlayer pour la prise en charge AirPlay
  • Restrictions de langue des sous-titres testées avec des pistes média réelles
  • Gravité vidéo définie de manière appropriée (.resizeAspect vs .resizeAspectFill)
  • isReadyForDisplay observé avant d'afficher la vue du lecteur
  • Gestion des erreurs pour le contenu diffusé en réseau (échecs HLS, timeouts)

Références

Individual skills in this repo

This repo contains 11 individual skills — each has its own dedicated page.

JordanCoin/ios-skills-collection

Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries. Use when the user asks about GitHub issues, pull requests, workflows, or wants to interact with GitHub repositories from the command line — including tasks like check CI status, create PR, list issues, or query the GitHub API.

JordanCoin/ios-skills-collection

Integrate and optimize Core ML models in iOS apps for on-device machine learning inference. Covers model loading (.mlmodelc, .mlpackage), predictions with auto-generated classes and MLFeatureProvider, compute unit configuration (CPU, GPU, Neural Engine), MLTensor, VNCoreMLRequest, MLComputePlan, multi-model pipelines, and deployment strategies. Use when loading Core ML models, making predictions, configuring compute units, or profiling model performance.

JordanCoin/ios-skills-collection

Implement, review, or improve maps and location features in iOS/macOS apps using MapKit and CoreLocation. Use when working with Map views, annotations, markers, polylines, user location tracking, geocoding, reverse geocoding, search/autocomplete, directions and routes, geofencing, region monitoring, CLLocationUpdate async streams, or location authorization flows. Also use when working with maps, coordinates, addresses, places, directions, distance calculations, or location-based features in Swift apps.

JordanCoin/ios-skills-collection

Display and manipulate PDF documents using PDFKit. Use when embedding PDFView to show PDF files, creating or modifying PDFDocument instances, adding annotations (highlights, notes, signatures), extracting text with PDFSelection, navigating pages, generating thumbnails, filling PDF forms, or wrapping PDFView in SwiftUI.

JordanCoin/ios-skills-collection

Implement, review, or improve in-app tips and onboarding using Apple's TipKit framework. Use when adding feature discovery tooltips, onboarding flows, contextual tips, first-run experiences, coach marks, or working with Tip protocol, TipView, popoverTip, tip rules, tip events, or feature education UI.

JordanCoin/ios-skills-collection

When the user wants to optimize their Google Play Store listing — title, short description, full description, keywords, ratings, or Play Store-specific features. Use when the user mentions "Google Play", "Android", "Play Store", "Play Console", "short description", "full description indexed", "Google Play ASO", or wants Google Play-specific keyword, creative, or ratings strategy. For iOS App Store optimization, see aso-audit and metadata-optimization.

JordanCoin/ios-skills-collection

When the user wants to implement, optimize, or use App Clips for app discovery and conversion. Use when the user mentions "App Clip", "app clip code", "mini app", "instant app", "App Clip card", "App Clip link", "no download required", "instant experience", or wants to understand how App Clips appear in App Store search. For general App Store discoverability, see aso-audit. For marketing campaigns, see ua-campaign.

JordanCoin/ios-skills-collection

When the user wants to plan a launch strategy for a new app or major update. Also use when the user mentions "app launch", "launch plan", "launch checklist", "pre-launch", "launch day", or "how to launch my app". For ongoing ASO after launch, see aso-audit. For paid acquisition during launch, see ua-campaign.

JordanCoin/ios-skills-collection

When the user wants to analyze their own app's actual performance data from App Store Connect — real downloads, revenue, IAP, subscriptions, trials, or country breakdowns synced via Appeeky Connect. Use when the user asks about "my downloads", "my revenue", "how is my app performing", "ASC data", "sales and trends", "my subscription numbers", "App Store Connect metrics", or wants to compare periods or top markets. For third-party app estimates, see app-analytics. For subscription analytics depth, see monetization-strategy.

JordanCoin/ios-skills-collection

When the user wants a full ASO health audit, review their App Store listing quality, or diagnose why their app isn't ranking. Also use when the user mentions "ASO audit", "ASO score", "why am I not ranking", "listing review", or "optimize my app store page". For keyword-specific research, see keyword-research. For metadata writing, see metadata-optimization.

JordanCoin/ios-skills-collection

Always use when working on any iOS, macOS, Swift, SwiftUI, Xcode, or Apple platform project. Routes to the correct specialized skills based on development phase and task context. This collection contains 210 skills from 28 authors covering the full iOS lifecycle.

Skills associés