-
Integre a reprodução de vídeo imersivo em apps para visionOS
Saiba como reproduzir vídeos imersivos em apps para visionOS. Abordaremos vários modos de renderização imersiva, analisaremos os frameworks que possibilitam isso e explicaremos como renderizar vídeos imersivos em seu app. Para aproveitar ao máximo este vídeo, recomendamos primeiro assistir à sessão "Explore experiências de vídeo para o visionOS” da WWDC25.
Capítulos
- 0:00 - Introdução
- 1:24 - Perfis de vídeo compatíveis no visionOS 26
- 3:09 - Reprodução de vídeo imersivo na Visualização Rápida
- 4:25 - Reprodução de vídeo imersivo com o AVKit
- 9:11 - Detecção de situações de desconforto
- 9:51 - Reprodução personalizada no RealityKit
- 11:48 - Modo de imersão progressiva no RealityKit
- 16:32 - Renderização de vídeo espacial com o RealityKit
- 21:16 - Detecção de situações de desconforto no RealityKit
- 22:57 - Integração de conteúdo do RealityKit com o SwiftUI
Recursos
- HTTP Live Streaming Examples
- Playing immersive media with RealityKit
- Playing immersive media with AVKit
- RealityKit
- AVFoundation
- AVKit
Vídeos relacionados
WWDC25
- Explore experiências de vídeo para o visionOS
- Novidades dos recursos espaciais para a web
- Saiba mais sobre as tecnologias Apple Immersive Video
- Saiba mais sobre o Apple Projected Media Profile (APMP)
WWDC24
WWDC23
-
Buscar neste vídeo...
-
-
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 - Introdução
Esse vídeo aborda as novas APIs no AVKit e na Visualização Rápida para reprodução de vídeo imersiva, além de detalhar como personalizar as experiências de reprodução imersivas com o RealityKit.
- 1:24 - Perfis de vídeo compatíveis no visionOS 26
O visionOS 26 apresenta novos perfis de vídeo, como o APMP para vídeos em 180, 360 e com campo de visão amplo, além do Apple Immersive Video para uma experiência imersiva definitiva. Você pode utilizar a Visualização Rápida, o AVKit ou o RealityKit para reprodução no app.
- 3:09 - Reprodução de vídeo imersivo na Visualização Rápida
A Visualização Rápida no visionOS 26 oferece duas APIs: PreviewApplication para apresentação de mídia fora do processo e QLPreviewController para pré-visualizações de mídia no app. Ambas as APIs são atualizadas para serem compatíveis com fotos espaciais, vídeos, Apple Immersive Video e Apple Projected Media Profile. Os apps que já usam as APIs da Visualização Rápida oferecerão suporte automaticamente a esses novos perfis de mídia imersiva.
- 4:25 - Reprodução de vídeo imersivo com o AVKit
O AVKit apresenta o "AVExperienceController", proporcionando duas experiências principais: Expandida e Imersiva. Agora, você pode configurar a experiência Expandida para reprodução imersiva, com a opção de desativar as transições automáticas. Isso permite um "tratamento de portal" de conteúdo imersivo quando detectado. Você pode fazer a transição explicitamente para a experiência Imersiva usando a nova API da experiência Imersiva, que fornece uma API de configuração para definir o ponto da reprodução de vídeo imersiva. "AVExperienceController" administra as animações e transições entre experiências. O Protocolo Delegado do controlador é essencial para monitorar as alterações de estado de apresentação e transição, garantindo que seus apps se adaptem adequadamente a diferentes tipos de conteúdo e interações do usuário.
- 9:11 - Detecção de situações de desconforto
O visionOS 26 introduz a detecção de mitigação de conforto para vídeos imersivos na Visualização Rápida e no AVKit. O sistema reduz automaticamente os níveis de imersão durante a reprodução de conteúdo do Apple Projected Media Profile com muito movimento para evitar desconforto visual, com opções de personalização disponíveis no app Ajustes.
- 9:51 - Reprodução personalizada no RealityKit
O RealityKit é o framework ideal para reprodução de vídeo imersiva personalizada no visionOS, especialmente para jogos e apps com interfaces de usuário exclusivas. No visionOS 26, o VideoPlayerComponent do RealityKit é compatível com reprodução nativa de vídeos imersivos, incluindo os formatos 180, 360 e com campo de visão amplo, e também com a renderização de vídeo espacial e o Apple Immersive Video, assim como o app Fotos. Esse componente trata automaticamente das atualizações de malha e animações, o que o torna ideal para criar experiências de vídeo imersivas e dinâmicas.
- 11:48 - Modo de imersão progressiva no RealityKit
No visionOS 26, o "VideoPlayerComponent" permite três modos imersivos no Apple Projected Media Profile e no Apple Immersive Video: portal, progressivo e total. O modo portal apresenta o vídeo em um portal. O modo progressivo, novo no visionOS 26, permite ajustar a imersão usando a Digital Crown e é preferido para conforto e flexibilidade. Ele é equivalente à imersão total em 100%. Para configurar a reprodução, defina o "desiredImmersiveViewingMode". Para o modo progressivo, use um "ImmersiveSpace" com um "ImmersionStyle" progressivo e combine o modo com o estilo. Eventos do modo de visualização imersiva sinalizam quando alternar a visibilidade da interface do usuário durante as transições.
- 16:32 - Renderização de vídeo espacial com o RealityKit
O RealityKit agora é compatível nativamente com vídeos espaciais, permitindo renderização imersiva com estilização espacial completa. Você pode configurar o estilo espacial usando a propriedade "desiredSpatialVideoMode" no "VideoPlayerComponent". Ajustar essa propriedade como ".spatial" ativa o estilo espacial, permitindo a renderização nos ImmersiveViewingModes ".portal" ou ".full". O modo ".full" sempre é usado para vídeos espaciais imersivos, que são renderizados em um tamanho fixo com base no campo de visão do conteúdo. O modo padrão, ".screen", renderiza vídeos espaciais em estéreo tradicional em uma malha de tela. Você pode assinar o evento "SpatialVideoModeDidChange" para monitorar as atualizações na propriedade "spatialVideoMode". Para criar um portal de vídeo espacial, defina "desiredSpatialVideoMode" como ".spatial" e "desiredImmersiveViewingMode" como ".portal". Para renderização de vídeo espacial imersivo, use o modo ".full" com um estilo de imersão misto e a opção "coexist" para "immersiveEnvironmentBehavior".
- 21:16 - Detecção de situações de desconforto no RealityKit
O RealityKit detecta automaticamente movimentos intensos nos vídeos do Apple Projected Media Profile e aplica mitigação de desconforto. Seu app é notificado sobre esses ajustes por meio do evento "VideoComfortMitigationDidOccur'. A renderização progressiva é necessária para a mitigação de "reducedImmersion", e a renderização de portal não precisa disso, pois já proporciona conforto para a maioria dos conteúdos. O evento "ContentTypeDidChange" ajuda você a se adaptar a diferentes tipos de vídeo e a seus requisitos específicos de mitigação e modo de visualização.
- 22:57 - Integração de conteúdo do RealityKit com o SwiftUI
Ao integrar o VideoPlayerComponent do RealityKit ao SwiftUI, garanta o dimensionamento uniforme dos eixos X e Y da entidade de vídeo para manter a proporção, especialmente no modo portal. Use "GeometryReader3D" para dimensionar o vídeo com base no tamanho da janela disponível para evitar recortes. A interface do usuário personalizada no mesmo plano da malha de vídeo tem comportamento de classificação indefinido. Para resolver problemas de classificação com a interface do usuário personalizada no mesmo plano, adicione um "ModelSortGroupComponent" com uma categoria "planarUIPlacement".