大多数浏览器和
Developer App 均支持流媒体播放。
-
打造出色的视频播放体验
了解如何利用最新的 iOS 和 iPadOS 系统媒体播放器,开发出让人惊叹的媒体 App。我们将分享更新版播放器的设计,为您提供最佳实践和技巧以帮助您设计独特的媒体体验。我们还将探索视频的“实时文本”功能,并说明如何在您的 App 中集成插播式广告和播放速度控制。
资源
相关视频
WWDC22
-
下载
♪ ♪
Jake: 大家好 我是 Jake 是 AVKit 团队的一名工程师 欢迎观看 打造出色的视频播放体验 在 iOS 和 iPadOS 16 中 我们从头开始搭建了全新的 媒体播放器 带来全新的外观和感觉 旨在保持对内容的关注 并适合更广泛的 App 我们还构建了许多新颖的交互模型 让使用这款新媒体播放器 有更加直观和无缝的体验 我们认为开发者会爱上它 在本期讲座中 我们将深入探讨 新的系统媒体播放器 我们将学习如何 设计令人惊艳的播放体验 我们将在 macOS 和 iOS 中 看到一些 令人兴奋的新的视觉智能功能 我将介绍全新的 新媒体播放器附带 插页式广告体验 并介绍我们从 tvOS 带来的一些新 API 最后 我们将介绍 AVKit 中的一个新功能 可选播放速度 我们重新设计了 tvOS 15.0 的系统播放器 带来了全新的外观和感觉 以及系统播放器的许多新功能 和可用性改进 好吧 我们听到了大家的需求 很高兴地告诉大家我们也改进了 iOS 系统播放器 我们已经完全重新设计了 原生媒体播放器 采用了 tvOS 播放器的观感 但重新设计了触控优先设备 我们已经删除了面板上的颜色 让界面在更广泛的 App 中具有原生感 并为用户带来更现代的感觉 我们来更深入地了解一下 所做的一些改进 首先 我们将播放 暂停和 跳跃控制放在前面和中间 使它们更容易与之交互 我们还将跳跃间隔从 15 秒 下调至 10 秒 可以更轻松地跟踪 连续跳跃的距离 接下来 我们还对时间轴的可用性 进行了一些重大改进 我们将移除用于标记 时间轴当前位置的滑块旋钮 相反 现在可以从滑块的任意位置 与时间线进行交互 拖动不再需要从当前时间标记开始 这使得大家更容易 准确地找到您想去的位置 我们还用更直观的缩放手势 取代了视频方面的控制 我稍后会展示 当然 新的 UI 对于竖屏内容 看起来也很棒
在 iPadOS 上 播放器无缝集成到系统中 全面支持键盘 触控板 鼠标 游戏控制器等等 我们还添加了一些 与控件交互的新方法 使导航内容和一些常见的交互 更容易和直观 让我们来看看这些 首先 我们添加了一种更改 视频缩放填充的新方法 您现在可以使用捏合手势 在可用缩放级别之间转换 捏合将使视频 位于显示屏的安全区域内 扩展将放大视频以完全填满显示屏 接下来 我们让 最常见的交互之一更流畅 播放或暂停 您现在可以点击显示屏的中心 哪怕播放和暂停视频的控制键 被隐藏了 最后 我们添加了一种通过 媒体时间轴导航的新方法 现在 您可以使用大家都了解 和喜爱的滚动视图中相同的交互 从视频的任何位置滚动时间轴 当您滚动视频帧时 界面消失 只留下最相关的 UI 允许将焦点保留在内容上 我们还带来了 tvOS 播放器的一些新功能 AVPlayerViewController 现在支持在全屏 UI 中 显示内容标题 副标题和描述 您可以通过传递 AVMetadataItems 为每个现有的 AVKit API 提供这些内容的字符串 让我们看看这是如何完成的 默认情况下 标题 副标题和 内容描述将从 媒体的元数据中提取 但是 如果需要 媒体中的值可以通过 AVPlayerItem 上的 externalMetadata API 被重写
可以通过使用标识符 commonIdentifierTitle 创建一个 AVMetadataItem 并将其添加到 playerItems 的 externalMetadata 属性中 标题应简短且具有描述性 以避免使 UI 混乱 同样 这里我们通过创建 带有标识符 .iTunesMetadataTrackSubtitle 的 AVMetadataItem 来添加字幕 字幕将显示在内容标题上方 并且应该用几个词来描述内容
最后 可以使用标识符 .commonIdentifierDescription 来添加描述 这将在标题和副标题的 右侧显示一个 V 形 选择标题将显示 包含内容描述的信息面板 描述应该是几句话 包含有关内容的更多信息 点击任意位置都会关闭信息面板
总结一下 我们对 iOS 系统播放器 进行全新的外观和感觉的提升 使用全新的流线型触控优先交互模型 附带许多其他改进 在您的 App 中使用 AVPlayerViewController 将得到系统播放器的全面支持 支持画中画 SharePlay 视觉分析 原生 Catalyst 支持 新硬件和功能支持 还有很多很多 当然 开发者只需几行代码即可获得 所有的这一切 现在 让我们谈谈如何在开发者的 App 中设计令人惊艳的播放体验 当我们着手重新 设计系统媒体播放器时 我们从过去构建的内容 以及为其他平台构建的内容中 后退一步 问自己 怎样才能创造出优秀的用户体验 我们想与开发者分享这个过程 我们是如何设计新播放器的 为什么要按照我们的方式设计 我们认为定义了 令人惊艳的媒体体验 我们认为有三件事可以让 媒体体验变得很棒 体验应该是直观的 它应该让人感觉轻松 熟悉 自然 即使您从未使用过 它应该与您的 App 和系统紧密结合 最后 它应该以内容优先 说到底 用户是来体验媒体的 您的 App 和设计应该反映这一点 现在让我们深入探究这三个方法 首先让体验更直观 通常情况下 当一款 App 让人感觉很直观时 很难说出原因 当您看到它时就知道了 那么究竟是什么让用户界面 或体验更直观呢 您怎么设计呢 我们认为是熟悉 当您可以利用过去的经验 来帮助理解新事物时 这就是直观 当您不需要解释它的工作原理 甚至不需要思考它是如何工作的 它完全按照您的预期运行
我们每个人都在构建 日常交互技术和现实世界的体验 这两者都是经验熟悉的重要来源 也是我们在设计 新系统媒体播放器时的起点 我们可以从许多类型的经验中 获得直觉 但我想重点谈谈两个方面 这两个是我们在设计 系统媒体播放器时最常依赖的 平台范例 和现实世界 第一个来自我们每天使用技术的经验 多年使用电视遥控器告诉您 方向键左右移动焦点 同样 轻按触控设备上的 音量按钮可以使音频静音 这些交互感觉很直观 因为它们很熟悉 您可以在您的媒体体验中 使用这一类的熟悉的交互 有助于使您的 App 感觉更直观 引人入胜 甚至自然使用 相反 发现不熟悉或意料之外的交互 可能会令人困惑 有时甚至令人沮丧 让我们看一些在系统播放器中 利用这种平台熟悉度的例子 一个很好的例子是 iOS 系统播放器的 展示和关闭模型 播放器从底部动画展现 轻轻一击 播放器可以通过将其推回而消失 我们看到这个模型在 触控优先设备中广泛使用 例如 Music 中正在播放的 UI 从底部的迷你栏中呈现 并且可以通过 向下交互式滑动来关闭 在某些情况下 我们的经验并非来自 对技术的理解 而是来自日常生活
这些类型的体验来自现实世界 数百万年的进化帮助我们 对自然过程形成了一种 深刻的本能理解 您可以利用这种理解 帮助在软件中构建熟悉和直观的体验 一个很好的例子是我们 在 iOS 播放器中的新滚动手势 类似于在桌子上滚动玩具车 视频上的每一次滑动都有动量 在直接交互后继续移动时间轴 直到时间轴慢慢停止 这里的动量本身 就与现实世界中的移动对象 建立了联系 这种联系有助于您 发现互动的微妙深度 就像玩具车一样 我可以通过更加大力地推动 或连续推几次 让它跑得更快 如果我抓住它 就会停止 感觉很自然 因为它很自然 最好的部分是 如果您使用系统播放器 您的 App 会感觉很直观 我们建立并继承对系统播放器的 直观和熟悉的所有自然交互 所有的设计范式都以 tvOS iOS 和 macOS 用户能够自然理解的方式优化 所有这些只需要几行代码就能得到
构建直观的设计 是让您的媒体体验很棒的一个方面 但如果没有人们所期待的 所有功能和整合点 您的 App 可能会 无意中将注意力从内容中移开 这将我们引向了令人惊艳的 媒体体验的第二个关键方面 紧密集成 当体验紧密集成时 人们期望运行的 所有功能 特性和设备都能正常工作 重要的是 他们的工作方式与其期望一致 随着人们使用设备 就习惯于依赖 平台的功能 例如 下拉控制中心 在 Now Playing 媒体控件中 看到您的内容 或者在看电视节目时响应通知 并让视频顺利进入画中画 将这种紧密的系统集成 构建到您的 App 中 是实现无缝体验的关键 您的 App 应该感觉 像是系统的原生部分 我们努力为开发者提供 实现这一目标所需的工具 包括诸如 CoreSpotlight 集成之类的东西 使您的内容可搜索 现在播放信息 以便您的内容 可以出现在系统媒体 UI 中 MediaRemote 命令允许 您的 App 响应诸如 键盘或电视遥控器上按下播放按钮 我们甚至可以将您的媒体 直接集成到电视 App 中 将您的内容提供给更广泛的受众 除了让您的 App 感觉原生化之外 提供用户喜欢的所有功能很重要 AirPlay SharePlay 和画中画等功能 我们认为大家会期待这些功能 并提供它们来增强 App 的使用体验 用户将在许多设备上使用您的 App 甚至更多的输入格式 为所有这些提供支持对于 确保每个人都能获得 您的体验至关重要 这在 tvOS 上尤其重要 因为支持所有可用的远程设备 对确保每个人都能使用 您的 App 至关重要 这是我们始终建议在 tvOS 上 使用系统媒体播放器的原因之一 您的 App 应确保所有电视遥控器 键盘 触控板 游戏控制器和耳机控制 此外 您应该确保您的 App 的 UI 元素 是在屏幕的安全区域内绘制的 以避免与显示屏中的圆角 或凹槽发生冲突 我们认识到为所有 这些集成点建立支持 功能和硬件配置可能令人生畏 这就是我们构建 AVPlayerViewController 的原因 所以只需几行代码 任何使用您 App 的人都可以获得 惊艳的媒体体验
所有这些都将我们引向 设计媒体体验最重要的方面 使内容前置 这应该是您设计的主要目标 这也是我们认为优秀媒体体验的 决定性因素 当您的 App 感觉直观时 当所有的集成点 和人们期望的所有功能 都能正常运行时 您就可以聚焦到内容 而其他所有部分都会淡出背景
有几件事您应该记住 尤其对于设计您的内容 确保在您的界面和系统中 提供所有适当的元数据 提供此信息有助于为您的媒体 提供背景信息 并允许系统在控制中心 和锁屏提供更好的体验 这包括诸如标题和副标题之类的内容 描述 缩略图 季和集信息 或直播的开始和结束日期 始终保持媒体的原始纵横比 这允许系统将您的视频 定位在屏幕上的 正确位置 对您的内容添加黑边 会带来这样的体验 或者这样的体验 确保尽可能支持最新的媒体标准 例如 HDR 和杜比全景声 最后 确保包含音频和字幕轨道 的多语言版本 让尽可能多的人 可以访问您的媒体
如果说这部分演讲 有什么值得注意的话 您应该把注意力集中在内容上 我们已经构建了通过 AVPlayerViewController 来提供 系统媒体播放器 以使开发者 尽可能轻松地实现这一目标 现在 让我们谈一谈添加到 AVPlayerViewController 的一些新功能 从新视觉智能功能开始 在本例中 我们让一个视频 暂停在一个带有代码片段的帧上 长按代码片段可以选中它 然后 您可以将其复制并 直接粘贴到 Playground 中进行试用 这也适用于 macOS 将光标悬停在相同的代码上 将显示光标 表示文本是可选的 然后您可以用光标来使它高亮显示 或使用 CMD+A 全选 我们正在引入一个新的 API 来配合这个功能 iOS 上的 AVPlayerViewController 和 macOS 上的 AVPlayerView 中可用 allowsVideoFrameAnalysis 切换此功能 这将为链接到新 SDK 的 所有 App 启用 当 allowedVideoFrameAnalysis 设置为 true 一旦媒体暂停 AVKit 将在设定的时间段后 开始分析当前视频帧 请注意 出于性能原因 我们不会分析在滚动时的帧 或 FairPlay 受保护的内容 总的来说 我们认为人们 在大多数情况下都会期待这个功能 但是 也有一些情况是 在您的 App 中 可能需要禁用可视分析 例如 在性能关键的 App 中 例如视频的集合视图 或在不期望与视频交互的情况下 如启动屏幕 有关更多如何集成 视觉智能功能集 到您的 App 的信息 请参看我们关于 VisionKit 的相关演讲 接下来 让我们看看我们对 插页式广告所做的一些改进 到目前为止 仅有 tvOS 上的 AVPlayerViewController 中 支持插页式广告 好吧 我很高兴地宣布 我们也将为 iOS 带来相同级别的支持 无论是在流中还是通过 AVPlayerInterstitialEvents 在本地定义的插页式广告 现在将沿时间线标记 当时间轴抵达标记 就会播放插页广告 如果您的插页式广告 已在您的 HLS 播放列表中完全定义 您会自动得到这种行为 无需采用 如果没有 或者您的 App 需要更多自定义行为 我们还引入了一些新的 API AVInterstitialTimeRange 正在从 tvOS 移植到 iOS 这些将自动填充到 AVPlayerItem 属性 interstitialTimeRanges 中 这也是从 tvOS 带来的 使用 HLS 流时 将为流中的每个插页式广告合成 AVInterstitialTimeRange AVFoundation API 在本地创建插页式事件时 将为每个 AVInterstitialTimeRange 合成 AVPlayerInterstitialEvent 然而 与 tvOS 不同 interstitialTimeRanges 是一个只读属性 插页式广告需要在 HLS 流中或通过 AVPlayerInterstitialEvents 来定义 对于那些从他们的 tvOS App 迁移支持的人 这就相当于将 translatesPlayerInterstitialEvents 设置为 Yes 我们还从 tvOS 引入了两个委托方法 这些可用于了解插页式广告何时开始 或结束播放 让我们看看如何使用 这些 API 来添加跳过按钮 用于 iOS 上的贴片广告 首先 我们将为主要媒体的播放器 创建一个 AVPlayerInterstitialEventController 接下来 我们将创建一个插页式事件 并且为它定义一些限制 这些限制可防止在插页式广告中搜索 并防止跳过插页式广告 然后我们将插页式广告 添加到事件控制器 最后 我们可以实现 willPresentInterstitial 委托回调 设定的时间间隔后 调出广告跳过按钮 跳过按钮后 我们将取消插页式广告 就这么容易 请注意 将任何 custom UI 元素 添加到 AVPlayerViewController 时 比如这个广告跳过按钮 总是确保将它们添加为 contentOverlayView 的子视图 要详细了解如何整合插页式广告 直接进入您的 HLS 播放列表 或如何使用 AVFoundation interstitials API 查看我们关于探索 HLS 动态片前和片中广告的相关演讲 现在我们看一下 今年在所有平台上添加的一个新功能 原生支持播放速度控制 AVPlayerView 和 AVPlayerViewController 使用我们添加的一些新 API 显示播放速度菜单
我们在 macOS iOS 和 tvOS 上 提供此功能 让我们来看看这是什么样子的 在 tvOS上 您会在传输栏中 看到一个新控件 选择控件将显示可供选择的 可用播放速度列表 在 iOS 上 此菜单将出现 在传输控制悬浮菜单中 同样 在 macOS 上 控件将出现在悬浮菜单中 链接到新的 iOS macOS 和 tvOS SDK 的所有 App 将自动获得此功能 无需额外更改 但是 根据您的场景 某些 App 可能想要修改速度列表 以编程方式选择速度 或完全禁用菜单 为了适应这些场景 我们添加了一些新的 API 到 AVPlayerView 和 AVPlayerViewController 让我们来看看这些
首先 我们在 AVKit 中新增了 一个类 AVPlaybackSpeed AVPlaybackSpeeds 代表 用户可选择的速度选项 在播放 UI 中 它们具有三个属性 一个速率值 在初始化时定义 选择播放速度时将在播放器上设置 本地化名称 用于表示播放速度 在无障碍系统内 例如 2.5 的速度可能会使用本地化名称 两倍半的速度 和一个本地化的数字名称 这个值是从 rate 属性合成的 并且将是播放速度菜单中 显示的字符串 如果您的 App 需要 自定义播放速度菜单 在播放器外部 使用此字符串表示速度
最后 AVPlaybackSpeed 定义了列表应尽可能使用的 系统默认速度 您可以将 AVPlaybackSpeed 与 AVPlayerView 和 AVPlayerViewController 上的 一些新 API 结合使用 适应您的 App 速度属性允许定义 播放速度的自定义列表 默认情况下 此属性将设置为 AVPlaybackSpeed systemDefaultSpeeds 列表 将其设置为空列表将会隐藏菜单 selectedSpeed 属性将返回 当前活动的速度 最后是 selectSpeed 函数 允许程序化选择 当前速度 请注意 您应该只使用此功能 响应在播放器 UI 之外显式选择速度 永远不要隐式覆盖选择的播放速度 让我们看一个例子 我们在这里创建一个 AVPlayerViewController 并展示 默认情况下 将使用系统提供的播放速度列表 您可以通过创建 AVPlaybackSpeed 向菜单添加新速度 并将其添加到 AVPlayerViewController 的速度列表中 我们还可以通过设置 一个空的速度列表来禁用菜单 就这么简单 但请注意 您应该始终 调用 AVPlayer play() 开始回放 永远不要通过调用 setRate:1.0 开始播放 因为所选速率可能不是 1.0 至此 我想结束本次演讲 我们看到了新设计的 iOS 系统播放器 我们了解了 如何设计自己的惊艳播放体验 我们看到了一些 很酷的新视觉智能功能 并查看了新的 插页式广告和播放速度 API 我希望您喜欢这个讲座 并期待在开发者的 App 中 看到这些功能 请享受研讨会余下的部分吧
-
-
4:08 - Setting content external metadata
// Setting content external metadata let titleItem = AVMutableMetadataItem() titleItem.identifier = .commonIdentifierTitle titleItem.value = // Title string let subtitleItem = AVMutableMetadataItem() subtitleItem.identifier = .iTunesMetadataTrackSubTitle subtitleItem.value = // Subtitle string let infoItem = AVMutableMetadataItem() infoItem.identifier = .commonIdentifierDescription infoItem.value = // Descriptive info paragraph playerItem.externalMetadata = [titleItem, subtitleItem, infoItem]
-
19:03 - Creating a skip button for a preroll ad
// Creating a skip button for a preroll ad let eventController = AVPlayerInterstitialEventController(primaryPlayer: mediaPlayer) let event = AVPlayerInterstitialEvent(primaryItem: interstitialItem, time: .zero) event.restrictions = [ .requiresPlaybackAtPreferredRateForAdvancement, .constrainsSeekingForwardInPrimaryContent ] eventController.events.append(event) func playerViewController(playerViewController: AVPlayerViewController, willPresent interstitial: AVInterstitialTimeRange) { showSkipButton(afterTime: 5.0, onPress: { eventController.cancelCurrentEvent(withResumptionOffset: CMTime.zero) }) }
-
21:14 - Setting custom playback speeds
// Setting custom playback speeds let player = AVPlayerViewController() player.player = // Some AVPlayer present(player, animated: true) let newSpeed = AVPlaybackSpeed(rate: 2.5, localizedName: "Two and a half times speed”) player.speeds.append(newSpeed)
-
23:02 - Hiding the playback speed menu
// Hiding the playback speed menu let player = AVPlayerViewController() player.player = // Some AVPlayer present(player, animated: true) player.speeds = []
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。