如何在 AirPlay 中使用媒体源扩展
媒体源扩展(MSE)是在网络上提供流媒体视频的一种流行方式。它使 JavaScript 能够控制字节发送到浏览器以进行播放的方式。在2023年全球开发者大会上,Apple 宣布了一项新的 Managed Media Source API,该 API 改进了 MSE,为 iOS 和其他设备提供了高效的视频流和更长的电池续航时间。
然而,MMS 和 MSE 本质上与 AirPlay 不兼容,AirPlay 需要一个唯一的播放 URL。AirPlay 允许你在手机上开始播放你喜爱的视频,将其传输到电视上,然后关闭手机。兼容 AirPlay 的 URL 可以是任何格式,例如 mp4、mpeg-ts 或 HTTP Live Streaming (HLS)。
本文将指导你同时提供这两种源,并在此过程中构建一个演示示例。
由于 MMS/MSE 使用附加到 SourceBuffer 的二进制 blob,因此它无法与 AirPlay 配合使用。但是,如果你创建一个可以作为 AirPlay 兼容 URL 提供的替代源,则有一种方法可以使它们协同工作。
说到 AirPlay 兼容的替代方案,HLS 是一个可以为用户提供很高效率的选择。有许多资源可以指导你将视频内容转换为使用 HLS 进行提供。Apple 提供了一个可以使用的工具包,也有许多其他选项。
const airplayURL = './video/demo.m3u8';
const videoURL = './video/demo.mp4';
const mediaType = 'video/mp4; codecs="avc1.640028"';
// Create a video element
const video = document.createElement('video');
// Set video element properties for the demo
video.controls = true;
video.loop = true;
video.muted = true;
video.autoplay = true;
在设置 MediaSource 时,可以轻松使用功能检测,以便在支持 Managed Media Source API 的浏览器上提供高效的流媒体,并在不支持时优雅地回退到 MSE。
// Feature detect MMS and fallback to MSE
const MediaSource = self.ManagedMediaSource || self.MediaSource;
const source = new MediaSource();
我们还需要一种方法来同时提供我们的 Media Source 和 AirPlay 源。HTML video
元素定义多个源的能力正好可以做到这一点。它最初的目的是允许用户代理选择最佳的视频格式进行播放,并在不支持时进行回退。
<video>
<source src="format/video.m3u8" type="application/x-mpegURL">
<source src="format/video.ogg" type="video/ogg">
<source src="format/video.mp4" type="video/mp4">
<source src="format/video.webm" type="video/webm">
</video>
浏览器将从上到下查看可用格式列表。如果没有找到匹配项,或者在解码过程中失败,它将选择列表中的下一个元素。
我们可以利用这种行为,结合用户代理选择最佳格式的能力,并允许 AirPlay 选择可播放的源。你将从 Media Source 创建一个 URL,并将其作为第一个源添加到视频元素中。这个 URL 对于用户代理来说是本地的,无法共享,因为它在本地上下文之外没有意义。然后,你将 AirPlay 兼容的 URL 作为第二个源添加。
// Add MSE/MMS streaming source
const videoSource1 = document.createElement('source');
videoSource1.type = 'video/mp4';
videoSource1.src = URL.createObjectURL(source); // Create URL from MediaSource
video.appendChild(videoSource1);
// Add AirPlay-compatible HLS source
const videoSource2 = document.createElement('source');
videoSource2. type = 'application/x-mpegURL';
videoSource2.src = airplayURL;
video.appendChild(videoSource2);
现在,当 Safari 检测到除了 MediaSource URL 对象之外还有其他可选源可用时,它将在视频播放器控件中显示熟悉的 AirPlay 图标。如果用户选择 AirPlay,它将从 MSE 切换到 AirPlay 兼容的 URL。
此演示的流媒体代码非常基础,它作为一个将视频字节传输到浏览器的示例。
document.onload = async () => {
if (!MediaSource.isTypeSupported(mediaType)) {
return console.log('Media type is not supported.');
}
await new Promise((resolve) => {
source.addEventListener("sourceopen", resolve, { once: true });
document.body.appendChild(video);
});
const sourceBuffer = source.addSourceBuffer(mediaType);
async function loadSegment() {
const response = await fetch(videoURL);
const buffer = await response.arrayBuffer();
await new Promise((resolve) => {
sourceBuffer.addEventListener("updateend", resolve, { once: true });
sourceBuffer.appendBuffer(buffer);
});
}
if (typeof(source.onstartstreaming) !== 'undefined') {
source.onstartstreaming = async () => {
loadSegment();
};
} else loadSegment();
});
反馈
提供对 MMS/MSE 和 AirPlay 的支持为用户提供了两全其美的体验,而 video
元素使提供多个源变得容易。你可以在 W3C 了解更多关于 Managed Media Source API 提案 的信息,并从 Apple 的文档中了解 HTTP Live Streaming。
我们很高兴听到你的声音。发推文给 @webkit,分享你对此功能的想法。在 Mastodon 上找到我们:@jensimmons@front-end.social 和 @jondavis@mastodon.social。你也可以在 LinkedIn 上关注 WebKit。如果你遇到任何问题,我们欢迎你提交 WebKit 错误报告,针对像这样由 WebKit 提供支持的功能。报告问题和分享你的反馈会产生巨大的影响。