4 HTML躬行记——Web音视频基础( 三 )


下图是一种播放器的整体架构图 , 来源于《Web端H.265播放器研发解密》 。

4 HTML躬行记——Web音视频基础

文章插图
除了常规的使用 video 元素播放视频之外 , 还可以用 canvas 播放 , 具体实现可以参考 JSMpeg 。
2)MSE
在 MSE 规范中 , 提供了 MediaSource 对象 , 它可以附着在 HTMLMediaElement 中 , 即 video 元素的 src 的属性值可以是它 。
一个 MediaSource 包含一个或多个 SourceBuffer 实例(下图来源于W3C官网) , SourceBuffer 表示通过 MediaSource 传递到 HTMLMediaElement 并播放的媒体片段 。
4 HTML躬行记——Web音视频基础

文章插图
下面是一个使用 MSE 的完整示例 , 修改了 MDN 中的代码首先是声明视频路径和 MIME 参数 , 注意 , 要正确指定 codecs 参数 , 否则视频无法播放 。
const video = document.getElementById('video');const assetURL = 'demo.mp4';const mime = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';然后实例化 MediaSource 类 , 并将其与 video 元素关联 , 注册 sourceopen 事件 。
const mediaSource = new MediaSource();video.src = https://www.huyubaike.com/biancheng/URL.createObjectURL(mediaSource);mediaSource.addEventListener('sourceopen', sourceOpen);最后实现 sourceOpen 函数 , 通过 fetch() 请求视频资源 , 将读取到的 ArrayBuffer 数据附加到 sourceBuffer 中 。
function sourceOpen(e) {URL.revokeObjectURL(video.src);const mediaSource = e.target;// 创建指定 MIME 类型的 SourceBuffer 并添加到 MediaSource 的 SourceBuffers 列表const sourceBuffer = mediaSource.addSourceBuffer(mime);// 请求资源fetch(assetURL).then(function(response) {return response.arrayBuffer();// 转换成 ArrayBuffer}).then(function(buf) {sourceBuffer.addEventListener('updateend', function() {if (!sourceBuffer.updating && mediaSource.readyState === 'open') {mediaSource.endOfStream();// 视频流传输完成后关闭流video.play();}});sourceBuffer.appendBuffer(buf); // 添加已转换成 ArrayBuffer 的视频流数据});}为 sourceBuffer 注册 updateend 事件 , 并在视频流传输完成后关闭流 。
注意 , 要想看到视频的播放 , 不能直接静态 HTML 文件 , 需要将文件附加到 HTTP 服务器中 。
本文借助 Node.js , 搭建了一个极简的 HTTP 服务器 , 当然也可以将 HTML 文件挂载到 Nginx 或 IIS 服务器中 。
const http = require('http');const fs = require('fs');// HTTP服务器const server = http.createServer((req, res) => {// 实例化 URL 类const url = new URL(req.url, 'http://localhost:1000');const { pathname } = url;// 路由if(pathname === '/') {res.writeHead(200, { 'Content-Type': 'text/html' });res.end(fs.readFileSync('./index.html'));}else if(pathname === '/demo.mp4') {res.writeHead(200, { 'Content-Type': 'video/mp4' });res.end(fs.readFileSync('./demo.mp4'));}else if(pathname === '/client.js') {res.writeHead(200, { 'Content-Type': 'application/javascript' });res.end(fs.readFileSync('./client.js'));}});server.listen(1000);B站的 flv.js 播放器是依赖 MSE , 可自动解析 flv 格式的文件并在 video 元素中播放 , 完全抛弃了 Flash 。
顺便说一句 , flv 格式的数据传输一般采用 RTMP(Real Time Messaging Protocol)直播协议 , 这是由 Adobe 公司提出的私有协议 , 工作在 TCP 协议之上 。
参考资料:
视频和音频内容
网页视频编码指南
Support for ISOBMFF-based MIME types in Browsers
WebRTC应用该使用哪种音视频编解码器
三种视频流浏览器播放解决方案

经验总结扩展阅读