Code Repo: github.com/xuchi16/vis...
Project Path: github.com/xuchi16/vis...
基本概念
在 visionOS 中,视频播放框架仍然沿用了此前的框架并在此基础上进行了增强。
- AVFoundation:处理视频播放的底层工作
- AVKit:在 AVFoundation 基础上,结合 UIKit、RealityKit 等,为每个平台创建定制化的播放体验
通过 AVKit 中的AVPlayerViewController
,可以实现基本的媒体播放的功能。配合视频播放过程中的观察者(Observer)、插播(Interstitial)等功能,还可以实现更为丰富的展示和交互效果。
基本实现
简单播放器
实现一个有最基本播放功能的播放器应用步骤如下:
- 导入框架:导入 AVFoundation 和 AVKit 框架,这两个框架分别提供了视频播放的核心功能和用户界面组件。
- 创建 AVPlayerViewController:用于视频播放的主要视图控制器。
- 设置 AVPlayer:创建一个 AVPlayer 实例,并将其连接到
AVPlayerViewController
。AVPlayer 是用于播放媒体内容的核心类。 - 创建播放器项:使用内容的 URL 创建一个新的播放器项,并将其设置在播放器上。这一步可以提高性能,因为播放器会在开始加载媒体之前了解如何显示它。
- 在 SwiftUI 中使用
AVPlayerViewController
,将其包装在一个 UIViewControllerRepresentable 类中。
swift
import SwiftUI
import AVFoundation
import AVKit
struct SimplePlayerView: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> AVPlayerViewController {
let controller = AVPlayerViewController()
controller.player = AVPlayer()
controller.player?.replaceCurrentItem(with:AVPlayerItem(url: URL(string: "VIDEO_PATH")!))
return controller
}
func updateUIViewController(_:AVPlayerViewController,context:Context){
}
}
- 创建一个名为 VideoPlaybackApp 的 SwiftUI 应用,并添加刚才定义的 SimplePlayerView。
swift
@main
struct VideoPlaybackApp: App {
var body: some Scene {
WindowGroup {
SimplePlayerView()
}
}
}
足球视频
在最基本的视频播放功能外,我们可能希望提供额外的功能,如
-
在视频播放过程中触发特殊效果:如足球视频在进球后触发"GOAL"的庆祝字幕,或在沉浸场景中触发烟花效果等
-
在播放轨道特定位置标记事件:如足球比赛进球时间点
在播放轨道特定位置标记事件
插播(Interstitial)原本是用来在视频播放过程中插入广告等内容的,但也会在相应的时间点在播放时间轴上添加一个标记点。所以考虑使用 Interstitial。
- 新建一个
AVPlayerInterstitialEventController
,并传入此前的AVPlayer
- 为需要播放的视频在需要标记的时点添加相应的插播事件
- 将上述插播事件传递给 controller
swift
let interstitialController = AVPlayerInterstitialEventController(primaryPlayer: player)
var interstitialEvents: [AVPlayerInterstitialEvent] = []
if let times = currentVideo?.getEventTimesVal() {
for time in times {
interstitialEvents.append(AVPlayerInterstitialEvent(primaryItem: item!, time: time))
}
}
interstitialController.events = interstitialEvents
视频播放过程中触发特殊效果
想要定义一个进球的滚动字幕效果,当进球时,会有一个"GOAL"横幅添出现在视频上方。
- 首先定义滚动字幕的视图
GoalView
,渐变色,从左往右滚动 - 通过 ornament 将字幕视图添加到视频上方
swift
struct ContentView: View {
@Environment(PlayerModel.self) private var playerModel
@State private var isGoalPanelVisible = Visibility.hidden
var match: MatchModel
var body: some View {
Spacer()
Text(match.getTitle())
.font(.title)
PlayerView()
.onAppear() {
playerModel.load(match.video)
}
.onChange(of: playerModel.goal) { _, newValue in
if newValue {
isGoalPanelVisible = .visible
} else {
isGoalPanelVisible = .hidden
}
}
.ornament(visibility: isGoalPanelVisible,
attachmentAnchor: .scene(.top),
contentAlignment: .bottom) {
GoalView()
}
// ...
}
}
- 在
player
上使用addBoundaryTimeObserver(forTimes:queue:using:)
,在视频播放到特定的时间点时调用特定的逻辑,控制字幕 ornament 是否可见。
swift
token = player.addBoundaryTimeObserver(forTimes: times, queue: .main) {
// Callback function
}
由于 visionOS 拥有无边画布,因此除了在进球时才展示的字幕外,我们还可以添加更多的窗口展示比赛相关的信息,同时不会影响视频的播放,如阵容、比赛数据等信息。