一起养成写作习惯!这是我参与「掘金日新计划 · 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;
}
- 第二种报错情况:控制台出现打印大量警告
出现该问题应该是音视频不同步问题,需要修改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);
}
});