在 Safari 中使用 Group Activities 协调媒体播放
Coordinate media playback in Safari with Group Activities
2021年6月10日
一句话判断
Web 端的 SharePlay 不需要任何原生代码——只需要几行 JavaScript 调用 Group Activities API,你的网页视频就能在 FaceTime 通话中同步播放。
这场 Session 讲了什么
Session 介绍了如何在 Safari 15 中使用 Group Activities API 实现 Web 端的媒体同步播放。这是 SharePlay 功能在 Web 平台上的实现,使用 JavaScript API 与 FaceTime 通话中的 Group Activities 集成。
Web 端的 API 设计与原生端保持一致的概念模型,但通过 JavaScript 暴露。核心 API 包括 window.GroupActivities 对象、GroupActivity 接口和 GroupSession 接口。你只需要为网页中的 <video> 或 <audio> 元素关联一个 GroupActivity,系统会自动处理播放同步。当用户在 FaceTime 通话中访问你的网页时,Safari 会在播放器上方显示”一起看”的提示按钮。Session 还讲解了 Web 端如何处理参与者的播放控制事件(播放、暂停、跳转)以及如何在多人之间维持一致的播放进度。
值得深挖的点
Web 端自动同步的工作原理
Safari 15 内置了 coordinatedPlayback 支持。当 <video> 元素与一个 GroupSession 关联后,Safari 自动处理播放状态的同步——你不需要手动监听和转发 play/pause/seek 事件。系统使用 FaceTime 的底层通信通道来传递播放状态,延迟通常在 100-200ms。如果你的网页有自定义的播放控制 UI(而不是使用浏览器默认控件),需要监听 MediaSession API 的 coordinator 属性来接收同步指令。
navigator.userActivation 的安全限制
启动 GroupActivity 需要用户手势(user gesture)——不能在页面加载时自动启动。这是为了防止恶意网页滥用 FaceTime 的通信能力。必须在用户点击按钮或执行其他交互操作后才能调用 GroupActivity.activate()。Session 建议在视频播放按钮旁边放一个”一起看”的按钮,用户点击时同时开始播放和启动 SharePlay。
代码片段
// 创建并启动一个 Group Activity
async function startSharePlay(videoTitle, videoUrl) {
// 检查浏览器是否支持 Group Activities
if (!window.GroupActivities) {
console.log("当前浏览器不支持 Group Activities");
return;
}
// 定义活动元数据
const activity = new GroupActivities.GroupActivity({
metadata: {
title: videoTitle,
subtitle: "一起观看视频",
type: "watchTogether",
previewImageUrl: `https://example.com/posters/${videoId}.jpg`
}
});
// 等待会话创建
const session = await activity.activate();
if (session) {
console.log("SharePlay 会话已创建,参与者: ", session.participants);
// 将视频元素与会话关联
coordinatePlayback(session);
}
}
// 将视频元素与 GroupSession 关联,实现自动同步
function coordinatePlayback(session) {
const video = document.querySelector('video');
// 使用 Media Session API 协调播放
if ('mediaSession' in navigator) {
navigator.mediaSession.metadata = new MediaMetadata({
title: "共享视频",
artist: "Group Activities Demo"
});
// 监听协调播放事件
// Safari 自动处理 play/pause/seek 的同步
video.coordinator = session.coordinator;
// 可选:监听参与者变化
session.onparticipantschange = () => {
console.log("参与者数量: ", session.participants.length);
updateParticipantsUI(session.participants);
};
// 可选:监听会话状态变化
session.onstatechange = () => {
if (session.state === "disconnected") {
console.log("SharePlay 会话已断开");
}
};
}
}
// 自定义播放同步(不使用自动同步时的手动方案)
function manualSync(session) {
const video = document.querySelector('video');
// 广播本地播放操作给其他参与者
video.addEventListener('play', () => {
session.sendMessage({ type: 'play', time: video.currentTime });
});
video.addEventListener('pause', () => {
session.sendMessage({ type: 'pause', time: video.currentTime });
});
video.addEventListener('seeked', () => {
session.sendMessage({ type: 'seek', time: video.currentTime });
});
// 接收远程参与者的播放指令
session.onmessage = (message) => {
switch (message.type) {
case 'play':
video.play();
break;
case 'pause':
video.pause();
break;
case 'seek':
video.currentTime = message.time;
break;
}
};
}
最佳实践
- 网页中的 Group Activities 需要在 HTTPS 环境下运行。开发阶段可以在 localhost 上测试,但生产部署必须使用 TLS。
- 视频源使用 HLS 格式以获得最佳同步效果。MP4 格式的 seek 精度取决于关键帧间隔,可能导致参与者之间的进度差达数秒。
- 在视频播放器旁添加一个明确的”一起看”按钮,并标注需要 FaceTime 通话才能使用。不要假设用户知道什么是 SharePlay。
还有什么值得关注
- Safari 15 的 Group Activities API 是 W3C Community Group Draft Report,未来可能成为 Web 标准。
- Web 端的 SharePlay 支持跨平台:macOS Safari 和 iOS Safari 都可以参与同一个 GroupSession。
- 在 iOS 上,Safari 的 SharePlay 会自动和 FaceTime 的画中画窗口配合,不需要额外的 CSS 处理。