WWDC Quick Look 💓 By SwiftGGTeam
Create a seamless multiview playback experience

Create a seamless multiview playback experience

观看原视频

Highlight

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


核心内容

想象一个场景:用户在看球赛,App 同时播放四路画面——鸟瞰镜头、近景跟拍、两个边线机位。用户按下暂停,四路画面要在同一帧停下;前进 10 秒,四路要同步跳到同一时刻;网络突然变差,最重要的鸟瞰画面要保住高清,其他可以掉到低清。在 iOS 26 之前,这些行为都得自己写——seek 时间精度、stall 恢复、启动等待,每一项都很容易出 bug。

WWDC25 这一节介绍 AVFoundation 与 AVRouting 在 iOS 26 中新增的三个 API,把这些复杂行为收进系统:AVPlaybackCoordinationMedium 处理多个 AVPlayer 之间的状态同步,AVRoutingPlaybackArbiter 处理 AirPlay 这种”只支持一路流”的外放设备如何挑选哪一路上大屏,AVPlayer.networkResourcePriority 让系统在带宽紧张时优先保住关键流的画质。三块拼起来,应用层只写几行代码就能搭出一个完整的多视图播放体验。


详细内容

多路同步:AVPlaybackCoordinationMedium

AVPlaybackCoordinationMedium 建在已有的 AVPlaybackCoordination 架构上(也就是 SharePlay 用的那一套)。每个 AVPlayer 自带一个 AVPlaybackCoordinator,负责协商本机播放器与其他已连接播放器的状态。Medium 在它们之间传消息:rate 变化、time 跳变、stall、中断、启动同步,全部走消息机制(06:17)。

接入方式很短,把每个 player 的 playbackCoordinator 通过 coordinate(using:) 接到同一个 medium 上即可(07:55):

import AVFoundation

var closeUpVideo = AVPlayer()
var birdsEyeVideo = AVPlayer()

let coordinationMedium = AVPlaybackCoordinationMedium()

do {
  try closeUpVideo.playbackCoordinator.coordinate(using: coordinationMedium)
} catch let error {
  // Handle error
}

do {
  try birdsEyeVideo.playbackCoordinator.coordinate(using: coordinationMedium)
} catch let error {
  // Handle error
}

关键点:

  • closeUpVideobirdsEyeVideo 是两个独立的 AVPlayer,各自加载不同的 asset,互不耦合。
  • AVPlaybackCoordinationMedium() 创建一个共享的协调媒介,所有要同步的 player 都接到同一个实例。
  • playbackCoordinator.coordinate(using:) 把当前 player 的协调器挂到 medium 上;该方法可能抛错,必须 try 并处理。
  • 接好之后,对任意一个 player 调用 play() / pause() / seek(to:),medium 会把状态广播给其他 player,无需自己写同步逻辑。
  • 该机制在 Picture-in-Picture、Now Playing 这类系统界面下也能保持同步(05:19)。

AirPlay 路由:AVRoutingPlaybackArbiter

AirPlay 接收方只能收一路流,应用必须告诉系统多路流里哪一路上大屏、哪一路上 HomePod。AVRoutingPlaybackArbiter 来自 AVRouting 框架,专门管这件事,分两类路由:non-mixable audio routes(HomePod 等只能放一路音频的设备)和 constrained external playback video routes(AirPlay 视频、Lightning Digital AV Adapter 等只能放一路视频的设备)(11:31)。

import AVFoundation
import AVRouting

var closeUpVideo = AVPlayer()
var birdsEyeVideo = AVPlayer()

let routingPlaybackArbiter = AVRoutingPlaybackArbiter.shared()

routingPlaybackArbiter.preferredParticipantForExternalPlayback = birdsEyeVideo

routingPlaybackArbiter.preferredParticipantForNonMixableAudioRoutes = birdsEyeVideo

关键点(13:17):

  • AVRoutingPlaybackArbiter.shared() 返回单例,全 App 只有一个仲裁器。
  • preferredParticipantForExternalPlayback 指定哪一路视频在 AirPlay 到 Apple TV 时上大屏;其他 player 仍在本地继续播放。
  • preferredParticipantForNonMixableAudioRoutes 指定哪一路音频在路由到 HomePod 等设备时被采纳。
  • 这两个属性可以指向同一个 player,也可以分别指向不同 player——视频和音频可以来自不同流。
  • 切换偏好时直接给属性赋新值即可(demo 中按下 star 按钮把 closeUpVideo 设为 preferred),上下大屏的画面会自动互换(10:17)。

画质优先级:networkResourcePriority

每个流都吃带宽。系统默认假设几路流同等重要、平均分配。但实际场景里,鸟瞰主视角必须高清、观众席机位掉一档分辨率也无所谓。AVPlayer.networkResourcePriority 三个等级:默认、.high.low14:59)。

birdsEyeVideo.networkResourcePriority = .high
closeUpVideo.networkResourcePriority = .low

关键点(16:15):

  • .high 表示这一路对网络资源需求高,系统会尽量让它跑在高分辨率档位。
  • .low 表示这一路对清晰度不敏感,带宽紧张时会先降它。
  • 这是给系统的提示,不是硬性配额。实际带宽分配还会综合考虑播放器数量、视频层尺寸、硬件约束等因素(16:35)。
  • Demo 中网络变差时,标记为 .low 的 close-up 先掉到低分辨率,标记为 .high 的 bird’s-eye 维持高清(17:52)。

核心启发

  • 做什么:把”多机位直播”做进体育/演出/教学类 App。

    • 为什么值得做:以前自研同步逻辑成本高,掉帧、seek 不齐、启动等待都是坑;Medium 把这些坑直接堵上。
    • 怎么开始:起一个最小 demo——两个 AVPlayer 加载不同机位的 HLS 流,用 AVPlaybackCoordinationMedium 串起来,验证 play / pause / seek / 启动同步在弱网下的表现。
  • 做什么:给现有视频 App 补一条手语流(ASL/CSL)通道。

    • 为什么值得做:手语流是典型的”必须严格同步、且 AirPlay 时偏好主视频”的多视图场景;用 Medium + Arbiter 几乎是零成本接入,对无障碍体验提升显著。
    • 怎么开始:主视频与手语视频两个 player 接进同一个 medium;把主视频设为 preferredParticipantForExternalPlayback,让 AirPlay 上大屏时手语流留在本机。
  • 做什么:给多视图播放页加一个”主视角/副视角”切换按钮。

    • 为什么值得做:用户长按或双击切主视角时,AirPlay 上大屏的流要跟着换;用 AVRoutingPlaybackArbiter 一行赋值就完成画面互换,体验比自己拆 player 要顺滑。
    • 怎么开始:监听用户的”标星/置顶”操作,更新 preferredParticipantForExternalPlayback;同时把 networkResourcePriority 切换为 .high / .low,让带宽也跟着主视角走。
  • 做什么:根据视图尺寸动态调整 networkResourcePriority

    • 为什么值得做:在 iPad 多视图布局里,被放大的画面理应享受更多带宽;让优先级跟视图尺寸联动,弱网下用户感知最强的那一路最先保住。
    • 怎么开始:在视图尺寸变化时(如分屏切换、PiP 切换),同步更新对应 AVPlayernetworkResourcePriority,并通过 A/B 测试看弱网下的清晰度变化。

关联 Session

评论

GitHub Issues · utterances