webRtc直播中播放器的选择(flvjs、mpegtsjs)

10,301 阅读3分钟

web直播整体流程

这里说的是直播的整体流程,包括发送端和播放端

web直播由于flash被禁用,之前的适用flash来推送rtmp流,播放端拉取rtmp流的方案已经不可行。

由于webRtc技术的成熟,所以现在的直播方案可以使用webRtc来推流,播放端使用webRtc播放,或者拉取flv、hls等视频流播放。由于flv相对于hls延迟低很多,所以选择采用flv视频流来播放。

整个流程如下

image.png

直接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里用网友建议将缓存设置小,还有尝试追帧处理等等。

02E51C1F.png

尝试去设置了发现不太管用,所以放弃了这个方案,开始寻找其它解决方案。这时候发现了flvjs项目介绍上有个推荐 image.png

有给mpegts.js做了一个广告,以及下面说flvjs维护变少的通知。

点进去mpegts.js的项目,可以看到这个项目是xqq这个作者的项目,这个作者也是flv.js的维护者。然后可以看到项目简介 image.png 这里可以知道这个项目是基于flv.js改造而来。GitHub链接

从一条作者的issues回复中可以发现这个项目相当于flv.js的改进版,支持了低延迟,支持了配置自动追帧,并且非常好迁移。

抱着试试看的态度尝试了一下

02DF3C37.gif

发现竟如此丝滑,延迟直接到2s左右,完美。

02E07D52.png

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>

02E344AF.jpg

有没有发现和上面flvjs使用方式一模一样,没错,就是把api的前缀从flv换成mpegts就行了。react版本也是一样的道理,只是把名字换一下就行了。

使用起来有几个注意项:

  • 指定了同时包含音视频的情况下hasVideo=truehasAudio=true,媒体流一定要同时包含音视频帧! 媒体流一定要同时包含音视频帧! 媒体流一定要同时包含音视频帧!
  • 播放时机放在onCanPlay事件里更好
  • 需要订阅报错事件的时候,事件回调里有三个参数,mpegts.on(mpegts.Events.ERROR,(ErrorTypes,ErrorDetails,ErrorInfo)=>{}),他的文档说明里没标注,导致找了很久

以上就是在选择播放器过程中的历程,距离真实直播场景中还有很多坑点,如报错重试、浏览器自动播放限制等。

欢迎大家讨论~