HTML5 直播协议之 WebSocket 和 MSE
当前为了满足比较火热的移动 Web 端直播需求, 一系列的 HTML5 直播技术迅速的发展了起来.
常见的可用于 HTML5 的直播技术有 HLS, WebSocket 与 WebRTC. 今天我要向大家介绍一下 WebSocket 与 MSE 相关的内容, 并在最后通过一个实际的例子, 来展示其具体的用法.
大纲
- WebSocket 协议介绍.
- WebSocket Client/Server API 介绍.
- MSE 介绍.
- fMP4 介绍.
- Demo 展示.
WebSocket
通常的 Web 应用都是围绕着 HTTP 的请求/响应模型而构建的. 所有的 HTTP 通信都是通过客户端来控制的, 都是由客户端向服务器发出一个请求, 服务器接收和处理完毕后再返回结果给客户端, 客户端再将数据展现出来. 这种模式不能满足实时应用的需求, 于是出现了 SSE, Comet 等 “服务器推” 的长连接技术.
WebSocket 是直接基于 TCP 连接之上的通信协议, 可以在单个 TCP 连接上进行全双工的通信. WebSocket 在 2011 年被 IETF 定为标准 RFC 6455, 并被 RFC 7936 所补充规范, WebSocket API 被 W3C 定为标准.
WebSocket 是独立的创建在 TCP 上的协议, HTTP 协议中的那些概念都不复存在, 和 HTTP 的唯一关联是使用 HTTP 协议的 101 状态码进行协议切换, 使用的 TCP 端口是 80, 可以用于绕过大多数防火墙的限制.

WebSocket 握手
为了更方便地部署新协议,HTTP/1.1 引入了 Upgrade 机制, 它使得客户端和服务端之间可以借助已有的 HTTP 语法升级到其它协议. 这个机制在 RFC7230 的 6.7 Upgrade ) 一节中有详细描述.
要发起 HTTP/1.1 协议升级,客户端必须在请求头部中指定这两个字段:
Connection: Upgrade
Upgrade: protocol-name[/protocol-version]
如果服务端同意升级, 那么需要这样响应:
HTTP/1.1 101 Switching Protocols
Connection: upgrade
Upgrade: protocol-name[/protocol-version] [... data defined by new protocol ...]
可以看到, HTTP Upgrade 响应的状态码是 101 , 并且响应正文可以使用新协议定义的数据格式.
WebSocket 握手就利用了这种 HTTP Upgrade 机制. 一旦握手完成,后续数据传输就直接在 TCP 上完成.
WebSocket JavaScript API
目前主流的浏览器提供了 WebSocket 的 API 接口, 可以发送消息(文本或者二进制)给服务器, 并且接收事件驱动的响应数据.
Step1 检查浏览器是否支持 WebSocket.
if(window.WebSocket) {
// WebSocket代码
}
Step2 建立连接
var ws = new WebSocket('ws://localhost:8327');
Step3 注册回调函数以及收发数据
分别注册 WebSocket 对象的 onopen, onclose, onerror 以及 onmessage 回调函数.
通过 ws.send() 来进行发送数据, 这里不仅可以发送字符串, 也可以发送 Blob 或 ArrayBuffer 类型的数据.
如果接收的是二进制数据,需要将连接对象的格式设为 blob 或 arraybuffer.
ws.binaryType = 'arraybuffer';
WebSocket Golang API
服务器端 WebSocket 库我推荐使用 Google 自己的 golang.org/x/net/websocket , 可以非常方便的与 net/http 一起使用.
可以将 websocket 的 handler function 通过 websocket.Handler 转换成 http.Handler , 这样就可以跟 net/http 库一起使用了.
然后通过 websocket.Message.Receive 来接收数据, 通过 websocket.Message.Send 来发送数据.
具体代码可以看下面的 Demo 部分.
MSE
在介绍 MSE 之前, 我们先看看 HTML5 <audio> 和 <video> 有哪些限制.
HTML5
和
标签的限制
- 不支持流.
- 不支持 DRM 和加密.
- 很难自定义控制, 以及保持跨浏览器的一致性.
- 编解码和封装在不同浏览器支持不同.
MSE 是解决 HTML5 的流问题.
Media Source Extensions (MSE) 是一个主流浏览器支持的新的 Web API. MSE 是一个 W3C 标准, 允许 JavaScript 动态的构建 <video> 和 <audio> 的媒体流. 他定义了对象, 允许 JavaScript 传输媒体流片段到一个 HTMLMediaElement.
通过使用 MSE, 你可以动态地修改媒体流而不需要任何的插件. 这让前端 JavaScript 可以做更多的事情, 我们可以在 JavaScript 进行转封装, 处理, 甚至转码.
虽然 MSE 不能让流直接传输到 media tags 上, 但是 MSE 提供了构建跨浏览器播放器的核心技术, 让浏览器通过 JavaScript API 来推音视频到 media tags 上.
现在每个客户端平台都开始逐步开放流媒体相关的 API: Flash 平台有 Netstream, Android 平台有 Media Codec API, 而 Web 上对应的就是标准的 MSE. 由此可以看出, 未来的趋势是在客户端可以做越来越多的事情.
Browser Support
通过 caniuse 来检查是否浏览器支持情况.

通过 MediaSource.isTypeSupported() 可以进一步地检查 codec MIME 类型是否支持.
比较常用的视频封装格式有 webm 和 fMP4.
WebM 和 WebP 是两个姊妹项目, 都是由 Google 赞助的. 由于 WebM 是基于 Matroska 的容器格式, 所以天生是流式的, 很适合用在流媒体领域里.
下面着重介绍一些 fMP4 格式.
我们都知道 MP4 是由一系列的 Boxes 组成的. 普通的 MP4 的是嵌套结构的, 客户端必须要从头加载一个 MP4 文件, 才能够完整播放, 不能从中间一段开始播放.
而 fMP4 由一系列的片段组成, 如果你的服务器支持 byte-range 请求, 那么, 这些片段可以独立的进行请求到客户端进行播放, 而不需要加载整个文件.
为了更加形象的说明这一点, 下面我介绍几个常用的分析 MP4 文件的工具.
- gpac 原名 mp4box, 是一个媒体开发框架, 在其源码下有大量的媒体分析工具可以使用, testapps
- mp4box.js 是 mp4box 的 Javascript 版本.
- bento4 一个专门用于 MP4 的分析工具.
- mp4parser 在线 MP4 文件分析工具.
fragment mp4 vs non-fragment mp4
下面一个 fragment mp4 文件通过 mp4parser 分析后的截图

下面一个 non-fragment mp4 文件通过 mp4parser 分析后的截图

Apple 在今年的 WWDC 大会上宣布会在 iOS 10, tvOS, macOS 的 HLS 中支持 fMP4.
值得一提的是, fMP4, CMAF, ISOBMFF 其实都是类似的东西.
MSE JavaScript API
从高层次上看, MSE 提供了 * 一套 JavaScript API 来构建 media streams. * 一个拼接和缓存模型. * 识别一些 byte 流类型: * WebM * ISO Base Media File Format * MPEG-2 Transport Streams
MSE 内部结构

MSE 本身的设计是不依赖任务特定的编解码和容器格式的, 但是不同的浏览器支持程度是不一样的. 可以通过传递一个 MIME 类型的字符串到静态方法: MediaSource.isTypeSupported 来检查.
比如:
MediaSource.isTypeSupported('audio/mp3'); // false
MediaSource.isTypeSupported('video/mp4'); // true
MediaSource.isTypeSupported('video/mp4; codecs="avc1.4D4028, mp4a.40.2"'); // true
获取 Codec MIME string 的方法可以通过在线的 mp4info 或者使用命令行 mp4info test.mp4 | grep Codecs
可以得到类似如下结果:
❯ mp4info fmp4.mp4| grep Codec
Codecs String: mp4a.40.2
Codecs String: avc1.42E01E
当前, H.264 + AAC 的 MP4 容器在所有的浏览器都支持.
普通的 MP4 文件是不能和 MSE 一起使用的, 需要将 MP4 进行 fragment 化.
检查一个 MP4 是否已经 fragment 的方法
mp4dump test.mp4 | grep "\[m"
如果是 non-fragment 会显示类似信息.
❯ mp4dump nfmp4.mp4 | grep "\[m"
[mdat] size=8+50873
[moov] size=8+7804
[mvhd] size=12+96
[mdia] size=8+3335
[mdhd] size=12+20
[minf] size=8+3250
[mdia] size=8+3975
[mdhd] size=12+20
[minf] size=8+3890
[mp4a] size=8+82
[meta] size=12+78
如果已经 fragment, 会显示如下类似信息.
❯ mp4dump fmp4.mp4 | grep "\[m" | head -n 30
[moov] size=8+1871
[mvhd] size=12+96
[mdia] size=8+312
[mdhd] size=12+20
[minf] size=8+219
[mp4a] size=8+67
[mdia] size=8+371
[mdhd] size=12+20
[minf] size=8+278
[mdia] size=8+248
[mdhd] size=12+20
[minf] size=8+156
[mdia] size=8+248
[mdhd] size=12+20
[minf] size=8+156
[mvex] size=8+144
[mehd] size=12+4
[moof] size=8+600
[mfhd] size=12+4
[mdat] size=8+138679
[moof] size=8+536
[mfhd] size=12+4
[mdat] size=8+24490
[moof] size=8+592
[mfhd] size=12+4
[mdat] size=8+14444
[moof] size=8+312
[mfhd] size=12+4
[mdat] size=8+1840
[moof] size=8+600
把一个 non-fragment MP4 转换成 fragment MP4.
可以使用 FFmpeg 的 -movflags 来转换
对于原始文件为非 MP4 文件
ffmpeg -i trailer_1080p.mov -c:v copy -c:a copy -movflags frag_keyframe+empty_moov bunny_fragmented.mp4
对于原始文件已经是 MP4 文件
ffmpeg -i non_fragmented.mp4 -movflags frag_keyframe+empty_moov fragmented.mp4
或者使用 mp4fragment
mp4fragment input.mp4 output.mp4
demo
- MSE Vod Demo 展示利用 MSE 和 WebSocket 实现一个点播服务.
- MSE Live Demo 展示利用 MSE 和 WebSocket 实现一个直播服务.
MSE VOD Demo
Your browser does not support the video tag.
MSE Live Demo
Your browser does not support the video tag.
Refs
WebSocket
来自:http://akagi201.org/post/websocket-mse/
HTML5 直播协议之 WebSocket 和 MSE的更多相关文章
- HTML5新协议介绍 WebSocket
WebSocket protocol 是HTML5一种新的协议(protocol).它是实现了浏览器与服务器全双工通信(full-duplex). 现在,很多网站为了实现即时通讯(real-time) ...
- WebSocket+MSE——HTML5 直播技术解析
作者 | 刘博(又拍云多媒体开发工程师) 当前为了满足比较火热的移动 Web 端直播需求,一系列的 HTML5 直播技术迅速的发展起来. 常见的可用于 HTML5 的直播技术有 HLS.WebSock ...
- 从Html5直播到互动直播,看直播协议的选择
目前,国内主流的直播协议有HLS.RTMP.HTTP FLV,适用于不同的直播场景. 一.HLS.RTMP与HTTP FLV 1.HLS HLS 全称是 HTTP Live Streaming, 是一 ...
- H5 的直播协议和视频监控方案
H5 的直播协议和视频监控方案 一.流媒体主要实现方式 二.流媒体技术 2.1 流媒体 2.2 直播 2.3 流协议 2.3.1 HLS 协议 2.3.2 RTMP 协议 2.3.3 RTSP 协议 ...
- HTML5学习总结-08 WebSocket 服务器推送
一 WebSocket 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展 ...
- 直播协议 HTTP-FLV 详解
传统的直播协议要么使用 Adobe 的基于 TCP 的 RTMP 协议,要么使用 Apple 的基于 HTTP 的 HLS 协议. 今天我要向大家介绍另外一种结合了 RTMP 的低延时,以及可以复用现 ...
- RTMP、HTTP-FLV、HLS,你了解常见的三大直播协议吗
随着直播行业大火,游戏.乐秀.教育.发布会等直播类产品层出不穷,能够满足各方人员的需求.在直播中,总能在其中找到适合自己的产品内容.喜欢玩游戏的可以看游戏直播,想学点工作技能的,也可以观看大牛现场授课 ...
- RTSP协议转换RTMP直播协议
RTSP协议转换RTMP直播协议 RTSP协议也是广泛使用的直播/点播流媒体协议,最近实现了一个RTSP协议转换RTMP直播协议的程序,为的是可以接收远端设备或服务器的多路RTSP直播数据,实时转换为 ...
- 园 首页 新随笔 联系 管理 订阅 订阅 RTSP协议转换RTMP直播协议
RTSP协议转换RTMP直播协议 RTSP协议也是广泛使用的直播/点播流媒体协议,最近实现了一个RTSP协议转换RTMP直播协议的程序,为的是可以接收远端设备或服务器的多路RTSP直播数据,实时转换为 ...
随机推荐
- C++ template的一些高级用法(元编码,可变参数,仿函数,using使用方法,. C++ 智能指针)
1 . 通用函数可变参数模板 对于有些时候,我们无法确切的知道,函数的参数个数时,而又不想过多的使用所谓的函数重载,那么就可以效仿下面的例子: #include<iostream> #i ...
- CPU的高速缓存存储器知识整理
基于缓存的存储器层次结构 基于缓存的存储器层次结构行之有效,是因为较慢的存储设备比较快的存储设备更便宜,还因为程序往往展示局部性: 时间局部性:被引用过一次的存储器的位置很可能在不远的将来被再次引用. ...
- 三星在GPL下发布其exFAT文件系统实现源码
exFAT文件系统是微软的一个产品,设计让外置储存设备和PC之间实现无缝的TB级数据转移和数据交换,它只支持Windows和OS X,不支持Linux.作为一个含有大量专利的私有产品,没有人会预计它会 ...
- css小知识点
1.div如何让背景是透明的 如:<div class="ha"></div> <style> .ha{ background:transpar ...
- Citrix 虚拟化笔记
利用win7 x64/Vmware workstation 10练习Citrix虚拟化 [安装Xenserver 6.2] 1)硬盘空间不足:要求最小8G 2)不支持硬件虚拟化:找到建立的XENSER ...
- 如何在CentOS 7.x中安装OpenERP(Odoo)
各位好,这篇教程关于的是如何在CentOS 7中安装Odoo(就是我们所知的OpenERP).你是不是在考虑为你的业务安装一个不错的ERP(企业资源规划)软件?那么OpenERP就是你寻找的最好的程序 ...
- 获取本地soapUI项目路径
def projectDir = ${projectDir}
- Java与数据库之间时间的处理
Java与数据库之间时间的处理 在数据库中建表: DROP TABLE IF EXISTS `times`; CREATE TABLE `times` ( `id` int(11) NOT NULL ...
- 闭包的理解-from my own opinion
闭包,说起来那么难,其实理解了作用域,那么理解闭包就容易多了. 全局环境,局部环境,这两个概念很好理解了.那么要深入理解下函数的局部环境. 函数的局部环境,也就是说在一个函数内定义的变量,这个变量只能 ...
- 搭建Tomcat6源代码阅读环境
目标:使用MyEclipse8.5阅读Tomcat6源码. 第一步:在MyEclipse8.5中集成SVN插件. 第二步:从地址http://svn.apache.org/repos/asf/tomc ...