web端的解码及渲染的实现
在前面的文章中介绍了ZLMediaKit的修改方法,在web端的播放器可以参照这个实现,基于wasm H265播放器。
基本思路就是通过emscripten将ffmpeg的编译成wasm,可以直接在浏览器中运行的软解码器。然后用webgl渲染出图像。
应用场景
单向视频流的场景
这是这个方案着重解决的场景。
webrtc datachannel(基于ZLMediaKit) + wasm解码 + webgl渲染。这种方案,非常适合单向视频流的应用场景,比如:web看摄像头。在这样的场景中,视频流是单向的,码流从摄像头到ZLMediaKit到浏览器并且没有音频。
但是方案的应用有两个需要考虑的问题:
datachannel通道的稳定性
稳定性是从传输大数据量和可靠性两个角度衡量。
datachannel是可以传输大数量的,并且也有可靠性保证:丢包重传和保证有序。为此我做了两个场景的测试:
- 内网测试:ZLMediaKit与rtmp推流端,web都部署在内网。web通过datachannel拉8M的H265码流,并没有出现过丢包(这里的丢包指的是datachannel可能不稳定而造成的数据丢弃,并非指网络丢包),也没有出现乱序。
- 外网测试:ZLMediaKit部署在外网,rtmp推流端和web部署在内网。web拉H265码流,根据云服务的带宽设置推流码率大小,只要码率值小于带宽,则并不会出现丢包和乱序(说明datachannel通道是有可靠性保证的)。
关于延迟,对于webrtc datachannel通道的延迟我并没有专门进行测试,但是在后续的播放器整体测试时,webrtc datachannel通道并没有引入不可接受的延迟。
解码性能
浏览器通过ffmpeg软解码,对于分辨率大,码流大的情况或多路视频时,还是会出现性能不足的情况。可以通过以下两种方式进行优化:
- simd解码
simd介绍见这个链接 WebAssembly中的simd。
在emscripten中通过msimd128
编译选项进行了支持。
实测效果,simd比ffmpeg的软件解码方式,性能提高了一倍。
- 硬解码
浏览器已经可以支持对H265的硬解码,但是有浏览器的版本限制。
在chrome 浏览器中可以通过webcodec的API来使用硬解码。
可以看下这个链接,chrome支持hevc硬编解码。
双向视频流的场景
我没有实际的测试经验,但是基于webrtc datachannel + wasm 编解码的方案应该是能走通的。首先data channel通道是支持双向流,稳定性也不错。编码性能方面可以通过simd编码或硬编码解决。
有音频流的场景
有音频流最大的难点是要做音视频同步,也意味着web端不再只是单纯的解码,渲染,回放。还需要与ZLMediaKit服务器交互时间同步信息(比如rtcp的sr包)。这种需求比单向视频流的场景复杂很多,并且大概率效果还不好(因为限制太多)。所以如果同时有音视频流场景,还是在服务端做转码,将H265转成H264,然后在web端通过webrtc实现音视频处理更好。