1、直播狀態(tài)
利用videojs實現(xiàn)rtmp直播時,遇到個問題:需要實時反映當(dāng)前直播的狀態(tài),比如當(dāng)直播未開始或者已經(jīng)結(jié)束的時候,提示暫無直播;當(dāng)直播正常播放時,則隱藏提示。
使用play可以監(jiān)聽到直播開始播放的事件,但是error和pause卻監(jiān)聽不到直播停止。在video.js的API文檔中,找到statechanged事件。
<!--vue-video-player-->
<videoPlayer
:options="playerOptions"
ref="video"
@statechanged="playerStateChanged($event)"
></videoPlayer>
/*js部分*/
methods:{
playerStateChanged($event){
console.log($event);
}
}

組件加載后,直播尚未開始推流

開始推流后

暫停推流后
由上圖可以知悉,當(dāng)觸發(fā)
loadeddata時,即開始又直播畫面出現(xiàn),然后timeupdate的值在不停的增加;當(dāng)直播暫停后,timeupdate的值不再發(fā)生改變。我們可以利用這點來判斷當(dāng)前直播是否正常。
data() {
return {
isError: true, //直播是否異常
rtmpUpdateTime: 0, //記錄直播的更新時間
videoShow: true
};
},
...
methods: {
//直播狀態(tài)改變
playerStateChanged($event) {
if($event.loadeddata){
this.isError = false;
}
if ($event.timeupdate) {
if ($event.timeupdate == this.rtmpUpdateTime) {
this.isError = true; //當(dāng)時間不再更新的時候,按直播停止處理
this.reloadVideo(); //重新加載video,達成黑屏效果
} else {
this.rtmpUpdateTime = $event.timeupdate;
// this.isError = false;
}
}
},
//重新加載video
reloadVideo() {
this.videoShow = false; //重新加載video
this.$nextTick(() => {
this.videoShow = true;
});
}
有一點需要注意,當(dāng)直播暫停后,雖然可以控制暫無直播的提示信息顯示,但是直播最后一幀的畫面仍舊在顯示,此時需要重新加載下videoPlayer組件。這里通過v-if="videoShow"來控制組件的加載(v-show果然無效)。
<videoPlayer
:options="playerOptions"
ref="video"
v-if="videoShow"
@statechanged="playerStateChanged($event)"
></videoPlayer>
補充:
1、基于對暫停情況的處理
video點擊暫停的時候,timeupdate也是不會變的,因此需要判斷下當(dāng)前視頻是否處于暫停的狀態(tài)。
if (!this.$refs.video.player.paused()){
//未暫停
}
2、網(wǎng)絡(luò)延遲問題
這個事件的觸發(fā)頻率由系統(tǒng)決定,但是會保證每秒觸發(fā)4-66次(前提是每次事件處理不會超過250ms)。
網(wǎng)絡(luò)較差的時候,會出現(xiàn)timeupdate更新不及時的情況,即可能會出現(xiàn)多次timeupdate值保持不變。
...
updateTimeRecord:[], //記錄下相同時間的,當(dāng)重復(fù)出現(xiàn)次數(shù)超過一定次數(shù)的時候按暫無直播處理
...
if ($event.timeupdate) {
if (!this.$refs.video.player.paused()) {
//未暫停
if ($event.timeupdate == this.rtmpUpdateTime) {
this.updateTimeRecord.push($event.timeupdate); //記錄下未更新的 timeupdate
if (this.updateTimeRecord.length >= 50) { //此處按50處理
this.isError = true; //當(dāng)時間不再更新的時候,按直播停止處理
this.reloadVideo(); //重新加載video,達成黑屏效果
}
} else {
this.updateTimeRecord = []; //清空記錄
this.rtmpUpdateTime = $event.timeupdate;
// this.isError = false;
}
}
}
以上只是允許在一定程度上的網(wǎng)絡(luò)延遲,不至于當(dāng)出現(xiàn)卡頓時就重新加載,導(dǎo)致直播畫面一直無法出現(xiàn)的情況。至于如何界定臨界值,需要自行做取舍。