当前位置: 首页 > Web前端 > HTML

基于xgplayer编写一个artc插件,实现阿里云低延迟直播

时间:2023-03-28 19:23:01 HTML

基于xgplayer写一个artc插件,实现阿里云的低延迟直播。他们首先看中了潘侯年会的直播项目。里面的弹幕功能和一些播放功能,都是他们觉得符合要求的内容。矛盾的简单点就是需求方需要使用阿里云的音视频artc。o(╥﹏╥)oo(╥﹏╥)o为了快速支持artc,第一版写了一个简单的播放js。,看起来挺简单的。不过之前xgplayer的一些手柄、自定义皮肤、弹幕功能都被彻底舍弃了。需求方因为时间原因忍了下来,但是在测试过程中播放器出现了很多问题,包括全屏、播放、海报等问题。使用的纯视频在ios和android上的功能差别很大。一些已经可用的皮肤和弹幕功能丢失了。检查兼容性。问题解决查看了xgplayer的源码,提供了很多hls.js、flv等插件,用于m3u8、flv的一些兼容播放。我在想为什么我不写一个artc插件来播放artc内容。它既保留了xgplayer的基本特点和优势,又可以播放artc,提升直播体验。代码思路分析源码插件思路//插件核心代码pluginsCall(){if(Player.plugins['s_i18n']){Player.plugins['s_i18n'].call(this,this)}letself=thisif(Player.plugins){letignores=this.config.ignoresObject.keys(Player.plugins).forEach(name=>{letdescriptor=Player.plugins[name]if(!descriptor||typeofdescriptor!=='function'){console.warn('pluginname',name,'isinvalid')}else{if(!ignores.some(item=>name===item||name==='s_'+item)&&name!=='s_i18n'){if(['pc','tablet','mobile'].some(type=>type===name)){if(name===嗅探器。device){setTimeout(()=>{//如果销毁,则跳过if(!self.video)return;descriptor.call(self,self)},0)}}else{descriptor.call(this,this)}}}})}}//关键是一句descriptor.call(this,this)简单理解就是使用了原型链的call方法,用插件中的方法覆盖原来的方法查看hls.js插件源码重写importPlayerfrom'../index'importHlsfrom'hls.js'importutilsfrom'./utils'classHlsJsPlayerextendsPlayer{...player.once('complete',()=>{if(player.config.isLive){util.addClass(player.root,'xgplayer-is-live')if(!util.findDom(player.controls,'.xgplayer-live')){constlive=util.createDom('xg-live',player.lang.LIVE||'live',{},'xgplayer-live')player.controls.appendChild(live)}}})//Section一段核心代码,当加载完成后的处理,live机制this.start=()=>{console.log('starthls')if(!window.XgVideoProxy){this.root.insertBefore(this.video,this.root.firstChild)}setTimeout(()=>{this.emit('complete')if(this.danmu&&typeofthis.danmu.resize==='function'){this.danmu.resize()}},1)}//第二个核心代码重写start方法Object.defineProperty(player,'src',{get(){returnplayer.currentSrc},set(url){util.removeClass(player.root,'xgpl艾尔生活e')constliveDom=document.querySelector('.xgplayer-live')if(liveDom){liveDom.parentNode.removeChild(liveDom)}//player.config.url=urlplayer.autoplay=trueconstpaused=player.暂停if(!paused){player.pause()}player.hls.stopLoad()player.hls.detachMedia()player.hls.destroy()player.hls=newHls(player.hlsOpts)player.register(url)player.once('canplay',()=>{player.play().catch(err=>{})})player.hls.loadSource(url)player.hls.attachMedia(player.video)},configurable:true})//第三方核心代码,通过defineproerty,监听src,设置后重写执行逻辑...}编写artc.js插件importPlayerfrom'../index'//1.importAliyunrts-sdkimport{AliRTS}from'aliyun-rts-sdk'importutilsfrom'./utils'//2.默认属性定义constPLAY_EVENT={CANPLAY:"canplay",WAITING:"waiting",PLAYING:"playing"}//3.定义一个新的类名classArtcPlayerextendsPlayer{constructor(options){super(options)letutil=Player.utilletplayer=this//4.在构造函数中创建一个rts对象letaliRts=AliRTS.createClient()this.aliRts=aliRts;这个.videoSub;player.once('complete',()=>{if(player.config.isLive){util.addClass(player.root,'xgplayer-is-live')if(!util.findDom(player.controls,'.xgplayer-live')){constlive=util.createDom('xg-live',player.lang.LIVE||'live',{},'xgplayer-live')player.controls.appendChild(live)}}})this.browser=utils.getBrowserVersion()//6.添加兼容性检查/***isSupport检测是否可用*@param{Object}supportInfo检测信息*@param{Boolean}supportInfo.isReceiveVideo是否拉取视频流*@return{Promise}*/this.aliRts.isSupport(Player.sniffer.device).then(re=>{//availableconsole.log('support',re)}).catch(err=>{//不可用console.error(`notsupporterrorCode:${err.errorCode}`);console.error(`notsupportmessage:${err.message}`);return})this._start=this.start//7.修改开始方法this.start=()=>{if(!window.XgVideoProxy){this.root.insertBefore(this.video,this.root.firstChild)this.video.play()}setTimeout(()=>{this.emit('complete')if(this.danmu&&typeofthis.danmu.resize==='function'){this.danmu.resize()}},1)}//8.修改srcset方法Object.defineProperty(player,'src',{get(){returnplayer.currentSrc},set(url){util.removeClass(player.root,'xgplayer-is-live')constliveDom=document.querySelector('.xgplayer-live')if(liveDom){liveDom.parentNode.removeChild(liveDom)}player.autoplay=trueconstpaused=player.pausedif(!paused){player.pause()}player.register(url)player.once('canplay',()=>{player.play().catch(err=>{})})},可配置:true})this.register(this.config.url)this.once('完成',()=>{console.log('????complete',this.video,player)if(!player.config.videoInit){player.once('canplay',()=>{player.play().catch(err=>{})})}})this.once('destroy',()=>{//@todo})}switchURL(url){constplayer=thisplayer.url=urlplayer.config.url=urlletcurTime=player.currentTime//player.video.muted=truePlayer.util.addClass(player.root,'xgplayer-is-enter')player.once('playing',function(){Player.util.removeClass(player.root,'xgplayer-is-enter')//player.video.muted=false})player.once('canplay',function(){player.currentTime=curTimeplayer.play()})播放器.src=url}//9.重写registervideoUrl方法,重要~~~register(url){letutil=Player.utilletplayer=thisthis.videoSub=this.aliRts.subscribe(url)this.videoSub.然后(stream=>{stream.play(this.video)}).catch(err=>{console.log(`error:${err}`);})this.aliRts.on('onPLayEvent',play=>{switch(play.event){casePLAY_EVENT.CANPLAY:console.log('canplay')player.play()break;casePLAY_EVENT.WAITING:console.log('WAITING')中断;casePLAY_EVENT.PLAYING:console.log('canplay')util.addClass(player.root,'xgplayer-is-live')if(!util.findDom(player.root,'.xgplayer-live')){constlive=util.createDom('xg-live',player.lang.LIVE||'正在直播',{},'xgplayer-live')player.controls.appendChild(live)}break;默认值:中断;}})}destroy(){super.destroy();}}exportdefaultArtcPlayer测试可用性import'../player'importArtcPlayerfrom'../player/artc'this.player=newArtcPlayer({id:'mse',url:this.source,isLive:true,poster:this.poster,width:'100%',height:'100%',autoplay:true,videoInit:true,playsinline:true,'x5-video-player-type':'h5','x5-video-player-fullscreen':false,丹mu:{area:{//弹幕显示区域start:0.05,//玩家从区域顶部到玩家顶部的高度比值end:.95//高度比值theplayerfromthebottomoftheareatotheplayer},},})//使用方法和前面的hls完全一样,可以完美运行。说到底,这个2022~05-27的直播应该用的是修改过的artc播放器。其实看过的同学可以发现,源码的阅读和插件的编写并没有想象中的那么复杂和困难。你必须敢于尝试做出新的发现。Xgplayerxgplayer的设计思想和结构非常好,值得学习和借鉴。可以使用ts重构实现自己的播放器库