-
Prise en charge de la lecture vidéo immersive dans les apps visionOS
Découvrez comment lire des vidéos immersives dans les apps visionOS. Nous aborderons les différents modes de rendu immersif ainsi que les frameworks qui les prennent en charge, et nous vous expliquerons comment effectuer le rendu de vidéos immersives dans votre app. Pour tirer le meilleur parti de cette vidéo, nous vous recommandons de commencer par regarder « Explorer les expériences vidéo pour visionOS » de la WWDC25.
Chapitres
- 0:00 - Introduction
- 1:24 - Profils vidéo pris en charge dans visionOS 26
- 3:09 - Lecture vidéo immersive dans Aperçu rapide
- 4:25 - Lecture vidéo immersive avec AVKit
- 9:11 - Détection de l’atténuation du confort
- 9:51 - Lecture personnalisée dans RealityKit
- 11:48 - Mode d’immersion progressive dans RealityKit
- 16:32 - Rendu de vidéos spatiales avec RealityKit
- 21:16 - Détection de l’atténuation du confort dans RealityKit
- 22:57 - Intégration de contenu RealityKit avec SwiftUI
Ressources
- HTTP Live Streaming Examples
- Playing immersive media with RealityKit
- Playing immersive media with AVKit
- RealityKit
- AVFoundation
- AVKit
Vidéos connexes
WWDC25
- Découvrir des expériences vidéo pour visionOS
- En savoir plus sur Apple Projected Media Profile
- En savoir plus sur les technologies Apple Immersive Video
- Nouveautés pour le web spatial
WWDC24
WWDC23
-
Rechercher dans cette vidéo…
-
-
5:03 - AVExperienceController - AutomaticTransitionToImmersive
struct ExpandedConfiguration { enum AutomaticTransitionToImmersive { case `default` case none } } -
5:50 - Disable Automatic Transitions to immersive
import AVKit let controller = AVPlayerViewController() let experienceController = controller.experienceController experienceController.allowedExperiences = .recommended(including: [.expanded, .immersive]) experienceController.configuration.expanded.automaticTransitionToImmersive = .none await experienceController.transition(to: .expanded) -
6:26 - AVExperienceController - Immersive
enum Experience { case immersive } struct Configuration { struct Placement { static var unspecified: Placement static func over(scene: UIScene) -> Placement } } -
6:53 - Transition to immersive
import AVKit let controller = AVPlayerViewController() let experienceController = controller.experienceController experienceController.allowedExperiences = .recommended(including: [.immersive]) let myScene = getMyPreferredWindowUIScene() experienceController.configuration.placement = .over(scene: myScene) await experienceController.transition(to: .immersive) -
8:13 - AVExperienceController.Delegate
func experienceController(_ controller: AVExperienceController, didChangeAvailableExperiences availableExperiences: AVExperienceController.Experiences) func experienceController(_ controller: AVExperienceController, prepareForTransitionUsing context: AVExperienceController.TransitionContext) async func experienceController(_ controller: AVExperienceController, didChangeTransitionContext context: AVExperienceController.TransitionContext) -
12:52 - PortalVideoView
@main struct ImmersiveVideoApp: App { var body: some Scene { WindowGroup { PortalVideoView() } } } -
13:03 - Portal Rendering
import AVFoundation import RealityKit import SwiftUI struct PortalVideoView: View { var body: some View { RealityView { content in guard let url = URL(string: "https://cdn.example.com/My180.m3u8") else { return } let player = AVPlayer(playerItem: AVPlayerItem(url: url)) let videoEntity = Entity() var videoPlayerComponent = VideoPlayerComponent(avPlayer: player) videoPlayerComponent.desiredImmersiveViewingMode = .portal videoEntity.components.set(videoPlayerComponent) videoEntity.scale *= 0.4 content.add(videoEntity) } } } -
13:57 - Progressive Immersion Rendering
import AVFoundation import RealityKit import SwiftUI struct ProgressiveVideoView: View { var body: some View { RealityView { content in guard let url = URL(string: "https://cdn.example.com/My180.m3u8") else { return } let player = AVPlayer(playerItem: AVPlayerItem(url: url)) let videoEntity = Entity() var videoPlayerComponent = VideoPlayerComponent(avPlayer: player) videoPlayerComponent.desiredImmersiveViewingMode = .progressive videoEntity.components.set(videoPlayerComponent) content.add(videoEntity) } } } -
14:20 - ProgressiveVideoView
import AVFoundation import RealityKit import SwiftUI @main struct ImmersiveVideoApp: App { var body: some Scene { ImmersiveSpace { ProgressiveVideoView() } .immersionStyle(selection: .constant(.progressive(0.1...1, initialAmount: 1.0)), in: .progressive) } } -
17:22 - SpatialVideoMode
if let vpc = components.get[VideoPlayerComponent.self] { vpc.desiredSpatialVideoMode = .spatial } -
18:32 - Spatial Video Portal Rendering
import AVFoundation import RealityKit import SwiftUI struct PortalSpatialVideoView: View { var body: some View { RealityView { content in let url = Bundle.main.url(forResource: "MySpatialVideo", withExtension: "mov")! let player = AVPlayer(url: url) let videoEntity = Entity() var videoPlayerComponent = VideoPlayerComponent(avPlayer: player) videoPlayerComponent.desiredViewingMode = .stereo videoPlayerComponent.desiredSpatialVideoMode = .spatial videoPlayerComponent.desiredImmersiveViewingMode = .portal videoEntity.components.set(videoPlayerComponent) videoEntity.scale *= 0.4 content.add(videoEntity) } } } -
19:02 - Spatial Video Immersive Rendering
import AVFoundation import RealityKit import SwiftUI struct PortalSpatialVideoView: View { var body: some View { RealityView { content in let url = Bundle.main.url(forResource: "MySpatialVideo", withExtension: "mov")! let player = AVPlayer(url: url) let videoEntity = Entity() var videoPlayerComponent = VideoPlayerComponent(avPlayer: player) videoPlayerComponent.desiredViewingMode = .stereo videoPlayerComponent.desiredSpatialVideoMode = .spatial videoPlayerComponent.desiredImmersiveViewingMode = .full videoEntity.position = [0, 1.5, -1] videoEntity.components.set(videoPlayerComponent) content.add(videoEntity) } } } -
19:46 - ImmersiveSpatialVideoView
import AVFoundation import RealityKit import SwiftUI @main struct SpatialVideoApp: App { var body: some Scene { ImmersiveSpace { ContentSimpleView() } .immersionStyle(selection: .constant(.mixed), in: .mixed) .immersiveEnvironmentBehavior(.coexist) } } -
21:40 - Comfort Mitigation Event
switch event.comfortMitigation { case .reduceImmersion: // Default behavior break case .play: // No action break case .pause: // Show custom pause dialog break }
-
-
- 0:00 - Introduction
Cette vidéo présente les nouvelles API d’AVKit et Quick Look pour la lecture immersive de vidéos, et explique en détail comment personnaliser les expériences de lecture immersive avec RealityKit.
- 1:24 - Profils vidéo pris en charge dans visionOS 26
visionOS 26 propose de nouveaux formats vidéo, notamment l’APMP pour les contenus à 180°, 360° et grand angle, ainsi qu’Apple Immersive Video pour une expérience immersive optimale. Vous pouvez utiliser Quick Look, AVKit ou RealityKit pour la lecture dans l’app.
- 3:09 - Lecture vidéo immersive dans Aperçu rapide
Quick Look dans visionOS 26 propose deux API : PreviewApplication pour la présentation multimédia hors processus et QLPreviewController pour les aperçus multimédias dans les apps. Les deux API ont été mises à jour pour prendre en charge les photos et vidéos spatiales, Apple Immersive Video et Apple Projected Media Profile. Les apps qui utilisent déjà les API Quick Look prendront automatiquement en charge ces nouveaux profils multimédias immersifs.
- 4:25 - Lecture vidéo immersive avec AVKit
AVKit présente « AVExperienceController », qui offre deux expériences principales : Expanded et Immersive. Vous pouvez désormais configurer l’expérience Expanded pour une lecture immersive, avec une option permettant de désactiver les transitions automatiques. Cela permet un « traitement portail » du contenu immersif lorsqu’il est détecté. Vous pouvez explicitement passer à l’expérience immersive à l’aide de la nouvelle API Immersive Experience, qui fournit une API de configuration permettant de définir l’emplacement de la lecture vidéo immersive. « AVExperienceController » gère les animations et les transitions entre les expériences. Le protocole délégué du contrôleur est essentiel pour surveiller les changements d’état de transition et de présentation, ce qui garantit que vos apps s’adaptent correctement aux différents types de contenu et aux interactions des utilisateurs.
- 9:11 - Détection de l’atténuation du confort
visionOS 26 intègre une fonctionnalité de détection de l’inconfort pour les vidéos immersives dans Quick Look et AVKit. Le système réduit automatiquement le niveau d’immersion lors de la lecture de contenus Apple Projected Media Profile comportant beaucoup de mouvements afin d’éviter toute gêne pour le spectateur. Cette fonctionnalité peut être personnalisée dans l’app Réglages.
- 9:51 - Lecture personnalisée dans RealityKit
RealityKit est l’outil essentiel pour créer des expériences vidéo immersives personnalisées sous visionOS, particulièrement pour les jeux et les apps ayant des interfaces innovantes. visionOS 26 intègre le VideoPlayerComponent de RealityKit qui permet la lecture native de vidéos immersives, y compris les formats 180°, 360° et grand-angle, ainsi que la vidéo spatiale et le format Apple Immersive Video, tout comme l’app Photos. Ce composant s’occupe automatiquement de la gestion des mises à jour et des animations des maillages, ce qui en fait la solution parfaite pour développer des expériences vidéo immersives dynamiques.
- 11:48 - Mode d’immersion progressive dans RealityKit
Dans visionOS 26, « VideoPlayerComponent » prend en charge trois modes immersifs pour Apple Projected Media Profile et Apple Immersive Video : portail, progressif et complet. Le mode Portal présente la vidéo dans un portail. Le mode Progressive, nouveau dans visionOS 26, permet aux utilisateurs d’ajuster l’immersion à l’aide de la Digital Crown et est préférable pour plus de confort et de flexibilité. Il équivaut à une immersion totale à 100 %. Pour configurer la lecture, définissez le paramètre « desiredImmersiveViewingMode ». Pour le mode Progressive, utilisez un « ImmersiveSpace » avec un « ImmersionStyle » progressif et faites correspondre le mode au style. Les évènements du mode de visualisation immersive indiquent quand basculer la visibilité de l’interface utilisateur pendant les transitions.
- 16:32 - Rendu de vidéos spatiales avec RealityKit
RealityKit prend désormais en charge les vidéos spatiales en mode natif, ce qui permet un rendu immersif avec un style spatial complet. Vous pouvez configurer le style spatial à l’aide de la propriété « desiredSpatialVideoMode » dans « VideoPlayerComponent ». Définir cette propriété sur « .spatial » active le style spatial, ce qui permet le rendu dans les modes d’affichage immersif « .portal » ou « .full ». Le mode « .full » est toujours utilisé pour les vidéos spatiales immersives, qui s’affichent dans une taille fixe en fonction du champ de vision du contenu. Le mode par défaut, « .screen », rend les vidéos spatiales en stéréo traditionnelle sur un maillage d’écran. Vous pouvez vous abonner à l’évènement « SpatialVideoModeDidChange » pour surveiller les mises à jour de la propriété « spatialVideoMode ». Pour créer un portail vidéo spatial, définissez « desiredSpatialVideoMode » sur « .spatial » et « desiredImmersiveViewingMode » sur « .portal ». Pour un rendu vidéo spatial immersif, utilisez le mode « .full » avec un style d’immersion mixte et l’option « coexist » pour « immersiveEnvironmentBehavior ».
- 21:16 - Détection de l’atténuation du confort dans RealityKit
RealityKit détecte automatiquement les mouvements rapides dans les vidéos Apple Projected Media Profile et applique des mesures d’atténuation pour améliorer le confort. Votre app est informée de ces ajustements via l’évènement « VideoComfortMitigationDidOccur ». Le rendu progressif est nécessaire pour la mesure d’atténuation « reducedImmersion », mais pas pour le rendu de portail, car celui-ci est déjà confortable pour la plupart des contenus. L’évènement « ContentTypeDidChange » vous permet de vous adapter aux différents types de vidéos, à leur mode d’affichage spécifique et aux exigences en matière d’atténuation.
- 22:57 - Intégration de contenu RealityKit avec SwiftUI
Lors de l’intégration du composant VideoPlayerComponent de RealityKit à SwiftUI, assurez-vous que les axes X et Y de l’entité vidéo sont mis à l’échelle de manière uniforme afin de conserver le rapport d’aspect, en particulier en mode portail. Utilisez « GeometryReader3D » pour mettre à l’échelle la vidéo en fonction de la taille de la fenêtre disponible afin d’éviter tout rognage. L’interface utilisateur personnalisée sur le même plan que le maillage vidéo présente un comportement de tri non défini. Pour résoudre les problèmes de tri avec l’interface utilisateur personnalisée sur le même plan, ajoutez un « ModelSortGroupComponent » avec une catégorie « planarUIPlacement ».