WWDC Quick Look 💓 By SwiftGGTeam
Create a great spatial playback experience

Create a great spatial playback experience

元の動画を見る

ハイライト

visionOS の動画再生は既存の AVFoundation + AVKit コードをそのまま活用します。AVPlayerViewController は RealityKit レンダリングで空間没入体験を実現し、3D 動画、空間オーディオ、自動環境調光に対応。開発者は visionOS SDK でビルドし、プレイヤーをウィンドウいっぱいに表示するだけで済みます。

主要内容

既存コードがそのまま使える

iOS で AVPlayerViewController を使って動画を再生していますか?visionOS ではほとんどコードを変える必要がありません。

00:42)AVFoundation がストリーミング、解析、デコード、同期などの低レベル処理を担当します。AVKit の AVPlayerViewController は visionOS で RealityKit レンダリングに強化され、動画がユーザー周囲の空間にシームレスに溶け込み、オーディオも空間位置に応答します。

互換性のある iOS App(iOS SDK でビルド)は iOS 互換の再生体験を得られます。完全な空間強化体験には、Xcode プロジェクトを visionOS SDK でビルドする必要があります。

3 行のコードで空間シネマを起動

02:23)使い方は iOS/tvOS とまったく同じです:

import AVFoundation
import AVKit

let playerViewController = AVPlayerViewController()
playerViewController.player = AVPlayer(url: videoURL)
present(playerViewController, animated: true)

キーポイント:

  • player item を作成する前に view controller に player を設定し、メディア読み込み前に表示方法を把握してパフォーマンスを向上
  • AVPlayerViewController をウィンドウいっぱいに表示して最適な没入体験を実現
  • SwiftUI では UIViewControllerRepresentable でラップ

空間再生体験

03:27)App 起動後、ユーザー目の前に大きなスクリーンが現れ、部屋が自動的に暗くなり映画鑑賞の雰囲気を演出します。移動してもスクリーンはその位置に留まり、オーディオはスクリーンに固定されます。スクリーンを見て指をピンチすると、動画の前方に再生コントロールが浮かび上がります。Digital Crown で音量を調整するか、没入型環境(シアター環境など)を開きます。

再生コントロールの詳細

04:48)visionOS の再生コントロールには以下が含まれます:

  • 右上: 音量コントロール(Digital Crown でも調整可能)
  • 左下: 再生/一時停止、巻き戻し/早送り
  • 下部中央: シークバー
  • 右下: その他のオプション(再生速度、音声トラック選択、字幕、調光効果)

調光効果(Dimming Effect)はオフにでき、動画視聴中も周囲の環境を見られます。

高度な機能

05:49

サムネイルシーク: HLS ストリームに I-frame only playlist(Trick Play トラック)が含まれる場合、進行バーをドラッグすると自動的にサムネイルが表示されます。幅 145 ピクセルの小さな Trick Play トラックを推奨します。

インタースティシャル: タイムラインにロゴ、振り返り、広告を挿入できます。AVPlayerInterstitialEventController でプログラム的に設定するか、HLS ストリーム内で記述します。

コンテキストアクション: 「イントロをスキップ」「次のエピソードを再生」などのカスタムボタンを追加できます。

カスタム情報パネル: コンテンツのメタデータや関連コンテンツの推薦を表示します。

没入型空間(Immersive Space)

07:13)App は Immersive Space を作成でき、動画スクリーンは自動的にその空間に移動し、固定サイズと位置に固定されて最適な視聴角度を保証します。コントロールはスクリーンから離れて少し近づき、操作しやすくなります。

@main
struct MoviePlayingApp: App {
    @State private var immersionStyle: ImmersionStyle = .full
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        
        ImmersiveSpace(id: "theater") {
            TheaterView()
        }
        .immersionStyle(selection: $immersionStyle, in: .full)
    }
}

struct ContentView: View {
    @Environment(\.openImmersiveSpace) var openImmersiveSpace
    
    var body: some View {
        PlayerView()
            .onAppear {
                Task {
                    await openImmersiveSpace(id: "theater")
                }
            }
    }
}

キーポイント:

  • ImmersiveSpace が 3D コンテンツシーンを定義
  • openImmersiveSpace で空間を開くと、AVPlayerViewController が自動的に動画スクリーンを移動
  • Immersive Space のデザインがプレイヤーのドッキングを収容できることを確認

詳細

動画表示方式の比較

12:32)visionOS は用途に応じた複数の動画表示方式を提供します:

方式API適用シーン3D 動画再生コントロールシステム統合
フルスクリーンプレイヤーAVPlayerViewController(ウィンドウいっぱい)映画鑑賞対応完全完全
インラインプレイヤーAVPlayerViewController(ウィンドウいっぱいでない)ドキュメント内埋め込み、プレビュー非対応簡略一部
3D シーンエンティティVideoPlayerComponentスプラッシュ画面、動画トランジション対応なしなし
カスタムジオメトリVideoMaterialエフェクト、アート展示対応なしなし

VideoPlayerComponent の使用

09:56)3D シーンで動画をエンティティとして表示する必要がある場合(スプラッシュ画面、動画トランジションなど)、RealityKit の VideoPlayerComponent を使用します:

import RealityKit
import AVFoundation

// 動画エンティティを作成
let videoEntity = Entity()

// AVPlayer を作成
let player = AVPlayer(url: videoURL)

// VideoPlayerComponent を追加
videoEntity.components[VideoPlayerComponent.self] = VideoPlayerComponent(
    avPlayer: player
)

// 通常のエンティティと同じように配置
videoEntity.position = [0, 1.5, -2]
videoEntity.scale = [2, 1.125, 1]

// シーンに追加
scene.addChild(videoEntity)

// 再生
player.play()

キーポイント:

  • VideoPlayerComponent が正しいアスペクト比の動画メッシュを自動作成
  • 字幕表示に対応
  • AVPlayerLayer より高性能、3D 動画フォーマットに対応
  • 再生コントロールやシステム統合が不要なシーンに最適

VideoMaterial の使用

10:46)より多くの制御が必要な場合(カスタムジオメトリ上に動画を表示するなど)、VideoMaterial を使用します:

import RealityKit
import AVFoundation

// カスタムジオメトリを作成
let mesh = MeshResource.generatePlane(width: 2, height: 1.125)

// VideoMaterial を作成
let player = AVPlayer(url: videoURL)
let videoMaterial = VideoMaterial(avPlayer: player)

// エンティティに適用
let videoEntity = ModelEntity(mesh: mesh, materials: [videoMaterial])
scene.addChild(videoEntity)

キーポイント:

  • VideoMaterial は任意のジオメトリ上に動画を表示可能
  • 元のアスペクト比は保証されない
  • 字幕表示は非対応
  • 動画をエフェクトとして使うシーンに最適

SwiftUI 統合の完全な例

import SwiftUI
import AVKit
import AVFoundation

struct PlayerView: UIViewControllerRepresentable {
    let videoURL: URL
    
    func makeUIViewController(context: Context) -> AVPlayerViewController {
        let controller = AVPlayerViewController()
        let player = AVPlayer()
        controller.player = player
        
// 先に player を設定してからコンテンツを読み込み、パフォーマンスを向上
        let item = AVPlayerItem(url: videoURL)
        player.replaceCurrentItem(with: item)
        
        return controller
    }
    
    func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) {}
}

struct ContentView: View {
    let videoURL = URL(string: "https://example.com/movie.m3u8")!
    
    var body: some View {
        PlayerView(videoURL: videoURL)
            .ignoresSafeArea()
    }
}

キーポイント:

  • ignoresSafeArea() でプレイヤーがウィンドウ全体を埋めることを保証
  • AVPlayerItem を作成する前に controller.player を設定し、プレイヤーが事前に表示方法を把握
  • 追加設定なしで空間オーディオと自動環境調光を取得

重要ポイント

  1. 既存の動画 App を visionOS に移行する

    • 何を作るか: 既存の iOS 動画再生 App を visionOS SDK で再ビルド
    • 価値がある理由: コード変更ゼロで大画面、空間オーディオ、環境調光を含む空間没入再生体験を獲得
    • 始め方: Xcode で visionOS ターゲットを作成し、既存の AVPlayerViewController コードを再利用
  2. 動画 App に Immersive Space を追加する

    • 何を作るか: 動画再生時に自動的に Immersive Space を開き、ユーザーをバーチャルシネマに誘導
    • 価値がある理由: 動画スクリーンが最適な視聴位置に固定され、コントロールが近づいて操作しやすく、シネマ級体験を提供
    • 始め方: openImmersiveSpace API を PlayerViewonAppear でトリガー
  3. サムネイルシークプレビューを実装する

    • 何を作るか: HLS ストリームに Trick Play トラックを追加し、進行バードラッグ時にフレームプレビューを表示
    • 価値がある理由: visionOS ではタッチスクリーンのような精密なシークができない。サムネイルが素早いナビゲーションを支援
    • 始め方: HLS パッケージング時に I-frame only playlist を追加、幅 145 ピクセル
  4. 「イントロをスキップ」コンテキストアクションを追加する

    • 何を作るか: AVPlayerViewController の contextual actions API でスマートスキップボタンを追加
    • 価値がある理由: visionOS の長尺動画体験には便利なナビゲーションが必要。コンテキストアクションは必要時に自動表示
    • 始め方: AVPlayerViewControllerDelegateplayerViewController(_:contextualActionsFor:) メソッドを実装
  5. 3D シーンで動画を環境要素として使う

    • 何を作るか: VideoPlayerComponent で RealityKit シーンに動的動画要素を追加
    • 価値がある理由: 空間体験 App に動的背景、情報表示、トランジション効果を追加
    • 始め方: RealityKit エンティティを作成し、VideoPlayerComponent を付与してシーンに配置

関連セッション

コメント

GitHub Issues · utterances