Create a seamless multiview playback experience
Audio & Video 进阶 2m

打造无缝多视角播放体验

Create a seamless multiview playback experience

2025年6月9日

在 Apple 官方观看视频

一句话判断

多路音视频同步播放——体育赛事多机位、演唱会多视角、手语流——以前要自己管状态同步和 AirPlay 路由,现在 AVFoundation 和 AVRouting 给了一套完整方案。

这场 Session 讲了什么

Session 聚焦三个痛点:多播放器之间的播放同步、AirPlay 多路流的路由管理、以及多路流的画质优先级控制。

对于需要同步的场景(比如足球赛的不同机位),新增了 AVPlaybackCoordinationMedium,它建立在已有的 AVPlaybackCoordination(SharePlay 用的那个)之上,把多个 player 的状态变更通过消息机制同步。对于不需要同步的场景(比如同时看奥运田径和游泳),也有对应的 API 支持。

AirPlay 方面,AVRoutingPlaybackArbiter 解决了”AirPlay 只能接收一路流”的问题——你可以指定哪个 player 优先路由到大屏,其他继续在本地播放。画质方面,networkResourcePriority 让你标记哪些流更重要,系统在网络带宽有限时优先保证高优先级流的清晰度。

值得深挖的点

AVPlaybackCoordinationMedium 的消息模型

这个 Medium 本质上是一个状态协调中心。每个 AVPlayer 有自己的 AVPlaybackCoordination,Medium 在这些 coordinator 之间传递消息——播放速率、时间跳转、暂停/播放、启动同步、中断恢复。一个 player 暂停,Medium 会通知所有其他 player 同步暂停。实现起来只需要几行代码:创建 Medium,然后把每个 player coordinate 进去。支持 2 个以上的 player。

值得注意的是,这个架构和 SharePlay 的 AVPlaybackCoordination 是同源的。如果你之前做过 Group Activities 的共享播放,迁移到多视角场景几乎是零学习成本。

AVRoutingPlaybackArbiter 的两种路由

Arbiter 管理两类受限路由:不可混合的音频路由(比如 HomePod,同一时间只能播放一个源的音频)和受限的外部视频路由(比如 AirPlay 到 Apple TV,只支持一路视频)。你可以分别设置 preferredParticipantForExternalPlayback(视频优先)和 preferredParticipantForNonMixableAudioRoutes(音频优先)。两个属性可以指向不同的 player。

切换优先级是运行时动态的——用户可以通过 UI 按钮改变哪个 player 是”主视角”,AirPlay 路由会无缝跟着切换,不需要断开重连。

networkResourcePriority 的实际效果

这个优先级不是”保证某个流拿到 N% 带宽”的硬控制,而是给系统带宽分配器的一个信号。系统会综合考虑优先级、播放器视图大小、硬件限制等因素。实际效果是:网络条件好时所有流都是高清,网络变差时低优先级流先降分辨率。Session 的 demo 里,鸟瞰视角(high priority)保持高清,特写视角(low priority)先降了分辨率。

代码片段

1. 多播放器同步播放

场景:体育赛事四个机位同步播放。

import AVFoundation

let closeUpPlayer = AVPlayer(url: closeUpURL)
let birdsEyePlayer = AVPlayer(url: birdsEyeURL)

// 创建协调中心
let coordinationMedium = AVPlaybackCoordinationMedium()

// 把所有 player 连接上去
try coordinationMedium.coordinate(player: closeUpPlayer)
try coordinationMedium.coordinate(player: birdsEyePlayer)

// 现在操作任一 player,其他会自动同步
closeUpPlayer.pause() // 所有 player 同步暂停
closeUpPlayer.seek(to: someTime) // 所有 player 同步 seek

2. AirPlay 多路路由管理

场景:AirPlay 时鸟瞰视角优先上大屏。

import AVRouting

let arbiter = AVRoutingPlaybackArbiter.sharedInstance
arbiter.preferredParticipantForExternalPlayback = birdsEyePlayer
arbiter.preferredParticipantForNonMixableAudioRoutes = birdsEyePlayer

// 用户切换主视角时动态更新
func switchPrimaryView(to player: AVPlayer) {
    arbiter.preferredParticipantForExternalPlayback = player
}

3. 画质优先级控制

场景:鸟瞰视角高清优先,观众特写可以降画质。

birdsEyePlayer.networkResourcePriority = .high
crowdCloseUpPlayer.networkResourcePriority = .low

坑:带宽分配受多个因素影响(player 数量、视图大小、硬件),priority 只是信号之一,不能精确控制每个流拿到多少带宽。

最佳实践

如果多个流需要同步(体育、手语、多机位),必须用 AVPlaybackCoordinationMedium。自己实现同步逻辑很容易出问题——seek 时的时间精度、中断恢复、启动时的等待策略,这些 Medium 都帮你处理了。

AirPlay 集成建议从第一天就做。AVRoutingPlaybackArbiter 的 API 很简单,不集成的话用户 AirPlay 时的体验会很混乱(不知道哪路流会上大屏)。

画质优先级方面,根据内容实际重要性来标记,不要全部设 high——全部 high 等于没有优先级。一般主视角 high,辅助视角 low 或不设置(默认)。

还有什么值得关注

  • Picture-in-Picture 下的同步:即使切换到 PiP 模式,同步播放依然生效,不需要额外处理。
  • Now Playing 界面集成:多路流的播放控制也能在系统 Now Playing 界面中同步操作。
  • 非同步多路播放:如果你的场景不需要同步(比如同时看多个比赛),可以直接用多个独立 AVPlayer,配合 Arbiter 管理路由,不需要 Medium。
Audio & Video