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

  • 视觉冗余,相对于人眼的视觉特性而言 , 人类视觉系统对图像的敏感性是非均匀和非线性的,并不是所有变化都能被观察到 。
  • 结构冗余,在图像的纹理区,以及图像的像素值存在明显的分布模式 。
  • 知识冗余,对许多图像的理解与某些先验知识有相当大的相关性 , 这类规律可由先验知识和背景知识得到 。
  • 视频播放器播放本地视频文件或互联网上的流媒体文件大概需要解协议、解封装、解码、音视频同步、渲染等几个步骤,如下图所示 。
    4 HTML躬行记——Web音视频基础

    文章插图
    二、Web中的音视频HTML5 标准推出后,提供了播放视频的 video 元素 , 以及播放音频的 audio 元素 。
    为了能更精准的控制时间、容器格式转换、媒体质量和内存释放等复杂的媒体处理,W3C 推出了 MSE(Media Source Extensions)媒体源扩展标准 。
    若要访问浏览器中已有的编解码器,可以试试 WebCodecs,它可以访问原始视频帧、音频数据块、图像解码器、音频和视频编码器和解码器 。
    在浏览器中主流的视频编码格式是 H.264/MPEG-4,不过需要支付专利费 。
    4 HTML躬行记——Web音视频基础

    文章插图
    而 Google 推出的开源编码格式:VP8,除了 IE 之外,其他浏览器的高版本都能支持 。
    4 HTML躬行记——Web音视频基础

    文章插图
    最新的 H.265 和 VP9 在浏览器的兼容性上都不理想,有些第三方库会自己写一个 H.265 的解码器脚本,然后来播放视频 。
    1)播放器
    直播使用 video 元素播放视频很多功能都无法满足,因此很多时候都会引入一个播放器,例如 video.js、react-player 等 。
    这些播放器都能支持多种格式的视频,例如 flv、m3u8、mp4 等;并且有完整的控制键,例如音量、缩放、倍速等,覆盖移动和 PC 两个平台,以及可引入插件等 。
    下图是一种播放器的整体架构图,来源于《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);

    推荐阅读