web直播整体流程
这里说的是直播的整体流程,包括发送端和播放端
web直播由于flash被禁用,之前的适用flash来推送rtmp流,播放端拉取rtmp流的方案已经不可行。
由于webRtc技术的成熟,所以现在的直播方案可以使用webRtc来推流,播放端使用webRtc播放,或者拉取flv、hls等视频流播放。由于flv相对于hls延迟低很多,所以选择采用flv视频流来播放。
整个流程如下
直接webRtc播放,延迟基本为0,实时性最高,拉流播放flv会有一定得延迟,看各厂商的配置决定延迟多少。
拉流播放的播放器选择
本次不讲webRtc那一套流程,主要说一下flv流播放器的选择和使用。
想要播放flv视频的话,同学们网上一搜就能看到有个flv.js,这个播放器是B站开源的播放器,可以直接播放flv视频。
flvjs使用方式
以下官方对原生写法的示例
<script src="flv.min.js"></script>
<video id="videoElement"></video>
<script>
if (flvjs.isSupported()) {
var videoElement = document.getElementById('videoElement');
var flvPlayer = flvjs.createPlayer({
type: 'flv',
url: 'http://example.com/flv/video.flv'
});
flvPlayer.attachMediaElement(videoElement);
flvPlayer.load();
flvPlayer.play();
}
</script>
附上在react中的使用
import flvjs from 'flv.js'
const FlvPlayer = () => {
const videoEle = useRef(null)
useEffect(() => {
let flvPlayer
if (flvjs.isSupported()) {
flvPlayer = flvjs.createPlayer(
{
type: 'flv',
isLive: true,
hasAudio: true,
url: 'https://pull.example.com/live/sqtest2.flv'
})
flvPlayer.attachMediaElement(videoEle.current);
flvPlayer.load();
flvPlayer.play(); // 此处的播放时机建议放在加载完成的事件中触发
}
return () => {
flvPlayer?.pause()
flvPlayer?.unload()
flvPlayer?.detachMediaElement()
flvPlayer?.destroy()
}
}, [])
return (
<video ref={videoEle} />
)
}
需要注意的点是直播中的音视频是可以随时开关的,所以不能每次开关重新初始化实例,去指定hasAudio
,所以建议统一全设置成true
,统一让厂商提供同时包含音视频的流。
如果按照以上代码跑起来了一个demo,然后和推流端校对一下延迟,你会发现此时的延迟会保持在5s+的样子。这种情况和webRtc的0延迟相比,差距还是太大了,很多直播场景都无法使用了。看issues里用网友建议将缓存设置小,还有尝试追帧处理等等。
尝试去设置了发现不太管用,所以放弃了这个方案,开始寻找其它解决方案。这时候发现了flvjs项目介绍上有个推荐
有给mpegts.js做了一个广告,以及下面说flvjs维护变少的通知。
点进去mpegts.js的项目,可以看到这个项目是xqq这个作者的项目,这个作者也是flv.js的维护者。然后可以看到项目简介
这里可以知道这个项目是基于flv.js改造而来。GitHub链接
从一条作者的issues回复中可以发现这个项目相当于flv.js的改进版,支持了低延迟,支持了配置自动追帧,并且非常好迁移。
抱着试试看的态度尝试了一下
发现竟如此丝滑,延迟直接到2s左右,完美。
mpegts.js使用方式
原生js的使用
<script src="mpegts.js"></script>
<video id="videoElement"></video>
<script>
if (mpegts.isSupported()) {
var videoElement = document.getElementById('videoElement');
var player = mpegts.createPlayer({
type: 'flv',
isLive: true,
url: 'http://example.com/live/livestream.ts'
});
player.attachMediaElement(videoElement);
player.load();
player.play();
}
</script>
有没有发现和上面flvjs使用方式一模一样,没错,就是把api的前缀从flv换成mpegts就行了。react版本也是一样的道理,只是把名字换一下就行了。
使用起来有几个注意项:
- 指定了同时包含音视频的情况下
hasVideo=true
、hasAudio=true
,媒体流一定要同时包含音视频帧! 媒体流一定要同时包含音视频帧! 媒体流一定要同时包含音视频帧! - 播放时机放在onCanPlay事件里更好
- 需要订阅报错事件的时候,事件回调里有三个参数,
mpegts.on(mpegts.Events.ERROR,(ErrorTypes,ErrorDetails,ErrorInfo)=>{})
,他的文档说明里没标注,导致找了很久
以上就是在选择播放器过程中的历程,距离真实直播场景中还有很多坑点,如报错重试、浏览器自动播放限制等。
欢迎大家讨论~