一.小程序自有组件: video / live-player ( live-pusher )
二.传统cdn直播
pc端浏览器/ 移动端安卓和ios浏览器
HLS:
其工作原理是服务端把整个流切分成一片片小的媒体流片段,客户端通过下载一个包含源数据的extended M3U(m3u8)playlist文件用于寻找可用的媒体流,随后开始下载格式为MPEG-TS的媒体片段
hls局限性:
- 在服务端对直播流进行切分处理之后客户端才能拉取到数据,所以整体延迟较高,通常延迟可达到20~30s。
- 由于直播流分片拉取,所以客户端需要频繁地进行http请求,可能会导致播放卡顿。
- 通过video标签进行hls播放,无法很好的在业务层进行定制化操作以及数据监控。
HTTP-FLV:
是将RTMP封装在HTTP协议之上的用于传输flv格式的协议,其传输的http_flv是一个文件大小无上限的http流的文件。相较于HLS,HTTP FLV无需在服务端对直播流进行切片处理,所以具有低延迟的优势,平均延迟只有1~2s。此外,HTTP FLV还具有一定程度上避免防火墙干扰、兼容302跳转、支持HTTPS通道加密等优势。
http-flv局限性:
由于HTTP FLV的支持需要依赖于MSE(Media Source Extensions) API 和 fetch+stream API ,而iOS浏览器不支持MSE API,所以flv流无法直接在iOS端播放。
FLV Web支持方案
现阶段js、sdk支持
flv.js工作原理为:通过mse将flv流转码成fmp4给video进行播放,由于其本质还需依赖MSE,所以无法支持iOS。
NodePlayer.js 工作原理:通过ASM.js软解码H.264+AAC流,利用WebGL视频渲染,WebAudio音频播放来实现移动端flv直播流播放。
WXInlinePlayer与ffmpeg-player工作原理基本相似:
- 数据流获取层:利用 XMLHttpRequest 或者 Fetch Api 从云端的HTTP-FLV 流媒体获取直播流数据。
- WASM解码层:利用web worker开启子线程,通过获取视频流metaData信息之后,对视频进行解封装,并将视频流格式化为YUV,将音频流格式化为PCM,进而将转换好的数据回调给渲染层。
- 渲染层:渲染层将获取到的视频数据与音频数据存入渲染缓存池中,WebGL 在 Canvas 上绘制视频画面,同时通过 Web Audio API 播放音频。
三.什么是WebRTC?
WebRTC 全称是(Web browsers with Real-Time Communications (RTC)
大概2011年,谷歌收购了 GIPS,它是一个为 RTC 开发出许多组件的公司,例如编解码和回声消除技术。Google 开源了 GIPS 开发的技术,并希望将其打造为行业标准。
收购花了一大笔钱,谷歌说开源就开源,确实不得不佩服,但显然对于Googl来说,打造音视频的开源生态有着更大的价值。“浏览器 + WebRTC”就是 Google 给出的一个答案。其愿景就是可以在浏览器之间快速地实现音视频通信。
发展至今日,简单来说:WebRTC是一个免费、开放的项目。使web浏览器通过简单的JavaScript api接口实现实时通信功能。
四. WebRTC几个重要API
1. 获取设备本地音视频
const constraints = {
video: true,
audio: true
};
// 非安全模式(非https/localhost)下 navigator.mediaDevices 会返回 undefined
try {
const stream = await navigator.mediaDevices.getUserMedia(constraints);
document.querySelector('video').srcObject = stream;
} catch (error) {
console.error(error);
}
以上这段demo,就是通过
getUserMedia获取stream,浏览器弹窗向用户索要权限,当允许后才能拿到stream传给video标签进行播放。
2. 获取音视频设备输入输出列表
MediaDevices.enumerateDevices()
try {
const devices = await navigator.mediaDevices.enumerateDevices();
this.videoinputs = devices.filter(device => device.kind === 'videoinput');
this.audiooutputs = devices.filter(device => device.kind === 'audiooutput');
this.audioinputs = devices.filter(device => device.kind === 'audioinput');
} catch (error) {
console.error(error);
}
3. RTCPeerConnection
RTCPeerConnection 作为创建点对点连接的 API,是我们实现音视频实时通信的关键。(参考MDN 文档)
4. 媒体协商方法
- createOffer
- createAnswer
- setLocalDesccription
- setRemoteDesccription
5. 重要事件
- onicecandidate
- onaddstream
在上个章节的描述中可以知道 P2P 通信中最重要的一个环节就是交换媒体信息
从上图不难发现,整个媒体协商过程可以简化为三个步骤对应上述四个媒体协商方法:
- 呼叫端 Amy 创建 Offer(createOffer)并将 offer 消息(内容是呼叫端 Amy 的 SDP 信息)通过信令服务器传送给接收端 Bob,同时调用 setLocalDesccription 将含有本地 SDP 信息的 Offer 保存起来
- 接收端 Bob 收到对端的 Offer 信息后调用 setRemoteDesccription 方法将含有对端 SDP 信息的 Offer 保存起来,并创建 Answer(createAnswer)并将 Answer 消息(内容是接收端 Bob 的 SDP 信息)通过信令服务器传送给呼叫端 Amy
- 呼叫端 Amy 收到对端的 Answer 信息后调用 setRemoteDesccription 方法将含有对端 SDP 信息的 Answer 保存起来
经过上述三个步骤,则完成了 P2P 通信过程中的媒体协商部分,实际上在呼叫端以及接收端调用 setLocalDesccription 同时也开始了收集各端自己的网络信息(candidate),然后各端通过监听事件 onicecandidate 收集到各自的 candidate 并通过信令服务器传送给对端,进而打通 P2P 通信的网络通道,并通过监听 onaddstream 事件拿到对方的视频流进而完成了整个视频通话过程。
五. Web直播方案
最终的方案 hls + flv( mse/wasm+ffmpeg+WebGL ) + WebRTC
UDP: 首先不可靠性体现在无连接上,通信都不需要建立连接,想发就发,这样的情况肯定不可靠。
并且收到什么数据就传递什么数据,并且也不会备份数据,发送数据也不会关心对方是否已经正确接收到数据了。
再者网络环境时好时坏,但是 UDP 因为没有拥塞控制,一直会以恒定的速度发送数据。即使网络条件不好,也不会对发送速率进行调整。这样实现的弊端就是在网络条件不好的情况下可能会导致丢包,但是优点也很明显,在某些实时性要求高的场景(比如电话会议)就需要使用 UDP 而不是 TCP。
pc端浏览器只能解析H264播放视频, wasm可以解析H265
低延迟,高并发,多路流,可互动
资料: