大多数浏览器和
Developer App 均支持流媒体播放。
-
在 Safari 浏览器中使用群组活动协调媒体播放
创建可供用户在网页和您的配套 app 中享受的 SharePlay 体验。了解如何将群组活动框架与配套网站结合使用,将 SharePlay 引入 Safari 浏览器,让人们即使尚未从 App Store 下载您的 app,也能相互联系进行愉快的群组互动。
资源
相关视频
WWDC21
-
下载
♪ (利用GroupActivities 在Safari中播放共享视频) 大家好 我是杰瑞 我从事媒体播放组件相关工作 在苹果公司的 WebKit和Safari部门工作 人们喜欢聚在一起看他们最爱的 节目和电影 一起听最爱的歌 无论他们是否呆在一起 是在隔壁 还是分隔在地球两端 现在有了 GroupActivities 这给您的用户提供了比以往 更方便的SharePlay体验 不管他们身在何处 在这一课程中 我们有四个主题 首先介绍Safari的 共享播放功能 然后是如何让您的iOS应用和 Safari上的SharePlay一起使用 接着是如何在您的应用网页上接入 Media Session API 最后是如何跨多个设备给共享播放 建立一个新的Web API 现在我们先来 探讨SharePlay 和Safari 在之前的课程中 您已了解如何 在您的iPhone和iPad应用中 利用GroupActivities 打造美妙的SharePlay体验 在macOS Monterey上 您可以把同样的体验 与您的iPhone 和iPad应用一起 通过Catalyst移植到Mac上 如果您的应用程序有配套网站 您可以分享同样美妙的 SharePlay体验 给您Mac Safari 15的用户 这些用户无需从App Store 下载您的应用 这就是我要在本课程中 向您展示的 我在研发一个iPhone应用 是用来看电影预告片的 我已经在我的应用中加入了 对GroupActivities的支持 这样我的朋友们 就可以通过FaceTime 一起观看电影预告片了 但我的电影预告片 应用还有一个配套网站 接着来就为您展示 我在该网站中加入 对GroupActivities 的支持后是什么样子的 我在和我的朋友山姆 用FaceTime通话 山姆喜欢看电影预告片 所以我让他们 帮我测试这个新的电影预告片应用 我们通话期间 当他们开始在该应用上 播放新预告片 我就会收到被邀请 观看那个预告片的通知 我可以选择是否 加入Safari上的会话 当我点击那个通知 Safari便会使用 共享内容的URL启动 当山姆开始播放预告片 在Safari上也会同时播放 我可以暂停 播放 甚至可以 在Safari上搜索视频 会话中的其他人都能看到同样的指令 在他们本机的视频中同时显示 这真的是棒极了 那么 要如何将对 GroupActivities的支持 添加到电影预告片的网站上? 在我们看Safari的后台之前 也就是新的Web API 在Safari 15上可用之前 让我们先谈谈如何让您的应用能够 通过GroupActivities使用Safari 为了能加入Safari的 GroupActivities会话 iPhone或 iPad应用用户 需要创建一个 GroupSessionActivity 带有指向您网站的fallbackURL 这个fallbackURL 不仅 必须要识别出您的网站 还要识别出要播放的特定内容 当一位iPhone用户 发送了一同观看的邀请 给一位Mac用户 Safari会启动并被要求加载 您在GroupSessionActivity提供的URL 一旦fallbackURL 在Safari上加载 您的网站就需要执行 一些简单但很重要的Web API 首先是Media Session Media Session是 标准的Web API 让您的站点能告诉浏览器 也就是Safari 更多关于媒体播放在您网页中 的当前状态 您的站点可以告诉浏览器 当前的播放状态 和内容的持续时间 它可以为现在播放的内容提供插图 甚至可以告诉浏览器现在的内容 是广告 可以跳过 一旦浏览器有了这些元数据 便可以将元数据提供给 操作系统的其他组件 并在自身的浏览器窗口之外 把它呈现给用户 操作系统显示数据的一个地方 叫做Now Playing Now Playing可以很好地 让用户快速查看 和控制他们正在观看的视频 在iOS中 用户可以轻松进入 Now Playing 从控制中心和锁屏界面都可以 现在在macOS Monterey中 用户可以直接 从菜单栏进入 Now Playing Safari会用到的信息 由Media Session提供 用来填入Now Playing 包括内容标题 持续时长 播放状态 插图 等等 Now Playing还允许 用户控制播放 他们正在收听的内容 通过给用户显示的 一组简单的播放控件即可实现 您的站点可以在 Media Session注册 以便具体执行操作 让用户与 Now Playing实现互动 举个例子 当用户轻击Now Playing 的播放按键 Safari会运行您站点上的 操作处理程序 来开始视频播放 Media Session让 您的站点可完全控制 将哪些元数据向浏览器公开 并且还能控制如何执行播放命令 需要在开始播放前 做些设置和预检工作? 没问题 有了Media Session的 播放操作处理程序 便可轻松实现 如果您的站点预先 采用了Media Session 那么您就已经成功了一半 但电影预告片网站还未 采用Media Session 所以现在我们来为其添加支持 这个站点需要添加播放 暂停和搜索等操作 为此 我们要用到 mediaSession属性 中的navigator 首先来添加播放的操作处理程序 我们会调用 mediaSession.setActionHandler() 传递字串play 以及在我们的视频要素 中调用play()的内联函数 然后 暂停和搜索也采用同样的方式 为了确保我们准确地 在浏览器中显示出了播放状态 我们要添加事件监听器到视频要素中 并且在状态发生变化时 刷新mediaSession 首先 要添加一个函数 叫做updateMediaSessionState() 它会查询视频要素 来识别它是在播放还是暂停 然后它会将mediaSession中的 playbackState属性 设置成字串 playing或paused 具体取决于视频要素的播放状态 下一步 它会查询 视频要素的持续时长 播放速度和当前时间 然后 利用这些取值 它会调用mediaSession的 setPositionState()函数 在dictionary参数中 传递这些取值 之后 加入事件监听器 来监测这些取值的变化 并调用updateMediaSessionState() 用这些新数值去 更新mediaSession 我们需要事件监听器来监测播放 暂停 时长变化 速度变化及时间变化 最后 因为这个电影预告片网站 不仅有标题字串还有 标题插图的URL 我们可以将Media Session的 元数据属性设置 成包括这些数值的 新MediaMetadata对象 来试试看吧 我会在Safari刷新 我的页面 然后开始播放 点击系统菜单中的 Now Playing图标 我在Now Playing面板中 看到了标题和插图 当我轻击暂停按钮 暂停操作处理程序 会被调用 即可暂停播放 Media Session属于 基本的构成要素 让网页实现了共同观看的体验 它给浏览器提供了一个机制 告诉网页 该开始还是该停止播放了 接下来我们讨论第二个主题 在网页中打造共同观看体验: 在会话中跨不同设备实现同步播放 为此 我们扩展了 Media Session 加入了新的属性 Coordinator 您的网页会用到 Media Session的Coordinator 来告知会话中的 每位用户网页的意图 是开始还是停止播放 还是搜索视频时间轴上的具体时刻 还是跳到播放列表中的下一项 Coordinator会与 会话中的所有其它设备沟通其意图 并监听所有其它设备播放状态的变化 解决冲突 并等待每位用户准备好开始播放 当大家都准备好 Coordinator会用 我们之前添加的 Media Session操作处理程序 来开始播放 和会话中的其他用户同时进行 如果另一位用户因为 某些原因停止播放 Coordinator会调用 您Media Session 的暂停操作处理程序 尽管如此 我还是要 指出一些注意事项 Coordinator接口是 一个实验性的Web API 还没有经过规范化 当有进程可能要改进此API时 这个API的某些方面 可能会发生改变 如果想进一步了解 请观看W3C的 Media Session GitHub网页 这个API目前只在 Safari上使用 虽然GroupActivities框架 就是Safari用来执行 Coordinator的框架 可以并且我们也希望能 被其它Mac浏览器采用 最后的注意事项是当您的用户加入 Safari的一个现有会话 当前的小组会话必须是由 iPhone iPad或 macOS应用发起的 所以现在就加入 Coordinator支持吧 一旦加入支持 我首先 要做的就是加入会话 所以我要将 coordinatorchange事件监听器 加入到mediaSession中 在处理程序中 如果有非空的 coordinator属性 在meidaSession中 我就会调用它的join()函数 我还想在我的控件中加入一个图标 来展示我们正在会话中播放视频 所以在处理程序中 是否会显示图标 取决于是否有 coordinator属性 在mediaSession中 我还会为这个图标连接一个 可点击的事件监听器 来调用coordinator 中的leave() 下一步 我要修改事件处理程序 来设置我的自定义控件 以检查coordinator的 存在 如果存在 则转而调用对应的 coordinator函数 我会给我的播放按钮 暂停按钮 和进度条各添加一个控件 来看看它的实际效果吧 我从朋友山姆那里收到了邀请 我准备接受邀请 我的网页加载的内容 和山姆的iPhone上 看到的一样 当我点击播放按钮 山姆的iPhone 和我的网页开始同步播放 我们到那儿的路线是一场冒险 我很害怕 如果你没有这种感觉 就不能称之为一场冒险了 ♪ 这太棒了 既然预告片播完了 山姆使用iPhone 把进度条拉回开头
我们认为用户会喜欢在应用中 一起观看或者收听他们最爱的内容 无论他们用的是iPhone iPad Apple TV 还是在他们的Mac上 运行的Safari 我们希望您现在能够给 您的所有用户带来这样的体验 不管他们身在何处 更多关于 GroupActivities API的信息 可以观看以下课程 《利用GroupActivities 播放共享视频》 以及《GroupActivities的设计》 如果您对其它 可用于Safari 15的 新Web API感兴趣 可以观看以下课程 《开发高级的网页内容》 感谢观看 请继续观看其它WWDC21课程 ♪
-
-
2:50 - Preparing your app
struct WatchTogether: GroupActivity { var contentIdentifier: String func metadata() async -> GroupActivityMetadata { var metadata = ActivityMetadata() metadata.fallbackURL = URL(string: "https://example.com/title/\(contentIdentifier)") return metadata } }
-
5:29 - Adopting Media Session
if (navigator.mediaSession) { navigator.mediaSession.setActionHandler('play', () => video.play() ); navigator.mediaSession.setActionHandler('pause', () => video.pause() ); navigator.mediaSession.setActionHandler('seekto', details => { video.currentTime = details.seekTime; }); } let updateMediaSessionState = function() { if (!navigator.mediaSession) return; let playbackState = video.paused ? 'paused' : 'playing'; navigator.mediaSession.playbackState = playbackState; let positionState = { video.duration, video.playbackRate, video.currentTime }; navigator.mediaSession.setPositionState(positionState); }; for (var event of ['playing', 'pause', 'durationchange', 'ratechange', 'timechange']) video.addEventListener(event, updateMediaSessionState); navigator.mediaSession.metadata = new MediaMetadata({ title: myPlayer.titleString, artwork: [{ src: myPlayer.artworkURL }] });
-
9:32 - Adopting Coordinator
navigator.mediaSession.addEventListener('coordinatorchange', coordinator => { if (coordinator) coordinator.join(); controls.inSessionIcon.style.hidden = !coordinator; }); controls.inSessionIcon.addEventListener('click', event => { let coordinator = navigator.mediaSession.coordinator; if (coordinator && coordinator.state == 'joined') navigator.mediaSession.coordinator.leave(); }); controls.playButton.addEventHandler('click', event => { if (navigator.mediaSession.coordinator) navigator.mediaSession.coordinator.play(); else video.play(); }); controls.pauseButton.addEventHandler('click', event => { if (navigator.mediaSession.coordinator) navigator.mediaSession.coordinator.pause(); else video.pause(); }); controls.timeline.addEventHandler('onchange', event => { if (navigator.mediaSession.coordinator) navigator.mediaSession.coordinator.seekTo(event.target.value); else video.currentTime = event.target.value; });
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。