Vue实战中遇到的常见的问题总结(五)---flv.js

3,166 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情

flv.js使用

实战中,遇到需要播放rtmp直播源的需求。原本是使用video.js,并使用其flash插件进行直播。但是后来谷歌禁止了flash,于是要寻求新的解决方案。于是找到flv.js这一插件,首先需要将源转化为flv流,接下来就可以借助flv.js这一插件进行播放直播流。以下就是我关于使用flv插件的方法和遇到的报错总结。

  • 下载flv.js npm install --save flv.js
  • 引用 import flvjs from ‘flv.js’;
  • 使用
 <video id="videoElement" width="700px" height="393px"  controls autoplay >
   Your browser is too old which doesn't support HTML5 video.</video>
if (flvjs.isSupported()) {
       var videoElement = document.getElementById('videoElement');
       this.flvPlayer = flvjs.createPlayer({
              type: "flv",
              isLive: true,
              fluid: true,
              stashInitialSize: 128,// 减少首桢显示等待时长
               url: 'xxxx'
        },{
               enableStashBuffer: false,
               fixAudioTimestampGap:false,
               isLive: true
         });
      this.flvPlayer.attachMediaElement(videoElement);
      this.flvPlayer.load();
      this.flvPlayer.play();
}

遇到的常见报错

  • 第一种报错情况:谷歌浏览器控制台出现的报错 出现的报错如下:Failed to read the ‘buffered’ property from ‘SourceBuffer’: This SourceBuffer has been removed from the parent media source.

这种错误提示一般是在flv源发生异常中断的时候产生的。错误提示大多数都在 mse-controller.js 这个模块中。 解决办法:需要找到flv.js源码的 mse-controller.js中(flv.js/src/core/mse-controller.js),appendMediaSegment()、_needCleanupSourceBuffer()这些方法的入口处调用检查以下MediaSource的合法性。

if (!this._mediaSource || this._mediaSource.readyState !== 'open') {
          return;
   }

db516835e10afb73b3f4a2f610b85ef2.png

  • 第二种报错情况:控制台出现打印大量警告

image-20220412105806485.png

出现该问题应该是音视频不同步问题,需要修改flv.js的配置,将config.fixAudioTimestampGap设置为false才会音视频同步。 解决办法:将参数fixAudioTimestampGap设为false(如上个模块实例使用demo)

优化

使用flv.js插件进行直播,存在直播时间越长,延时会不断累加的问题,为了解决该问题,查阅大量资料,我使用到的是判断到他的缓存时长,当超过2s时,加大他的播放速度,大概是1.2,以此累加,其实这个时候,用户是不会有感知的,因为极短时间就可以追上来,并重新以正常速度播放。这样就解决了直播的问题。(定时检测缓冲区末尾和当前播放位置的差,如果超过一定程度,就将当前播放位置指向一个接近缓冲区末尾的位置。简单来说,就是:主动发现、主动追赶,主动跳帧。) 示例如下:

   myPlayer.on('timeupdate', () => {
       let differTime = myPlayer.buffered().end(0) - myPlayer.currentTime();
       // 差值小于1.5s时根据1倍速进行播放
       if (differTime < 1.5) {
          myPlayer.playbackRate(1);
       }
      // 差值大于1.5s小于10s根据1.2倍速进行播放
       if (differTime < 10 && differTime >= 1.5) {
          myPlayer.playbackRate(1.2);
       }
      // 差值大于10s时进行重新加载直播流
      if (differTime >= 10 && differTime < 20) {
         myPlayer.playbackRate(2);
      } if (differTime > 20) {
         myPlayer.currentTime(myPlayer.buffered().end(0) - 1);
     }
  });