2 lines
11 KiB
JavaScript
2 lines
11 KiB
JavaScript
import f from"events";import h from"../utils/logger.js";import m from"../utils/browser.js";import n from"./player-events.js";import c from"../core/transmuxer.js";import a from"../core/transmuxing-events.js";import E from"../core/mse-controller.js";import o from"../core/mse-events.js";import{ErrorTypes as _,ErrorDetails as g}from"./player-errors.js";import{createDefaultConfig as p}from"../config.js";import{InvalidArgumentException as T,IllegalStateException as u}from"../utils/exception.js";class v{constructor(e,t){if(this.TAG="FlvPlayer",this._type="FlvPlayer",this._emitter=new f,this._config=p(),typeof t=="object"&&Object.assign(this._config,t),e.type.toLowerCase()!=="flv")throw new T("FlvPlayer requires an flv MediaDataSource input!");e.isLive===!0&&(this._config.isLive=!0),this.e={onvLoadedMetadata:this._onvLoadedMetadata.bind(this),onvSeeking:this._onvSeeking.bind(this),onvCanPlay:this._onvCanPlay.bind(this),onvStalled:this._onvStalled.bind(this),onvProgress:this._onvProgress.bind(this)},self.performance&&self.performance.now?this._now=self.performance.now.bind(self.performance):this._now=Date.now,this._pendingSeekTime=null,this._requestSetTime=!1,this._seekpointRecord=null,this._progressChecker=null,this._mediaDataSource=e,this._mediaElement=null,this._msectl=null,this._transmuxer=null,this._mseSourceOpened=!1,this._hasPendingLoad=!1,this._receivedCanPlay=!1,this._mediaInfo=null,this._statisticsInfo=null;let i=m.chrome&&(m.version.major<50||m.version.major===50&&m.version.build<2661);this._alwaysSeekKeyframe=!!(i||m.msedge||m.msie),this._alwaysSeekKeyframe&&(this._config.accurateSeek=!1)}destroy(){this._progressChecker!=null&&(window.clearInterval(this._progressChecker),this._progressChecker=null),this._transmuxer&&this.unload(),this._mediaElement&&this.detachMediaElement(),this.e=null,this._mediaDataSource=null,this._emitter.removeAllListeners(),this._emitter=null}on(e,t){e===n.MEDIA_INFO?this._mediaInfo!=null&&Promise.resolve().then(()=>{this._emitter.emit(n.MEDIA_INFO,this.mediaInfo)}):e===n.STATISTICS_INFO&&this._statisticsInfo!=null&&Promise.resolve().then(()=>{this._emitter.emit(n.STATISTICS_INFO,this.statisticsInfo)}),this._emitter.addListener(e,t)}off(e,t){this._emitter.removeListener(e,t)}attachMediaElement(e){if(this._mediaElement=e,e.addEventListener("loadedmetadata",this.e.onvLoadedMetadata),e.addEventListener("seeking",this.e.onvSeeking),e.addEventListener("canplay",this.e.onvCanPlay),e.addEventListener("stalled",this.e.onvStalled),e.addEventListener("progress",this.e.onvProgress),this._msectl=new E(this._config),this._msectl.on(o.UPDATE_END,this._onmseUpdateEnd.bind(this)),this._msectl.on(o.BUFFER_FULL,this._onmseBufferFull.bind(this)),this._msectl.on(o.SOURCE_OPEN,()=>{this._mseSourceOpened=!0,this._hasPendingLoad&&(this._hasPendingLoad=!1,this.load())}),this._msectl.on(o.ERROR,t=>{this._emitter.emit(n.ERROR,_.MEDIA_ERROR,g.MEDIA_MSE_ERROR,t)}),this._msectl.attachMediaElement(e),this._pendingSeekTime!=null)try{e.currentTime=this._pendingSeekTime,this._pendingSeekTime=null}catch(t){}}detachMediaElement(){this._mediaElement&&(this._msectl.detachMediaElement(),this._mediaElement.removeEventListener("loadedmetadata",this.e.onvLoadedMetadata),this._mediaElement.removeEventListener("seeking",this.e.onvSeeking),this._mediaElement.removeEventListener("canplay",this.e.onvCanPlay),this._mediaElement.removeEventListener("stalled",this.e.onvStalled),this._mediaElement.removeEventListener("progress",this.e.onvProgress),this._mediaElement=null),this._msectl&&(this._msectl.destroy(),this._msectl=null)}load(){if(!this._mediaElement)throw new u("HTMLMediaElement must be attached before load()!");if(this._transmuxer)throw new u("FlvPlayer.load() has been called, please call unload() first!");if(!this._hasPendingLoad){if(this._config.deferLoadAfterSourceOpen&&this._mseSourceOpened===!1){this._hasPendingLoad=!0;return}this._mediaElement.readyState>0&&(this._requestSetTime=!0,this._mediaElement.currentTime=0),this._transmuxer=new c(this._mediaDataSource,this._config),this._transmuxer.on(a.INIT_SEGMENT,(e,t)=>{this._msectl.appendInitSegment(t)}),this._transmuxer.on(a.MEDIA_SEGMENT,(e,t)=>{if(this._msectl.appendMediaSegment(t),this._config.lazyLoad&&!this._config.isLive){let i=this._mediaElement.currentTime;t.info.endDts>=(i+this._config.lazyLoadMaxDuration)*1e3&&this._progressChecker==null&&(h.v(this.TAG,"Maximum buffering duration exceeded, suspend transmuxing task"),this._suspendTransmuxer())}}),this._transmuxer.on(a.LOADING_COMPLETE,()=>{this._msectl.endOfStream(),this._emitter.emit(n.LOADING_COMPLETE)}),this._transmuxer.on(a.RECOVERED_EARLY_EOF,()=>{this._emitter.emit(n.RECOVERED_EARLY_EOF)}),this._transmuxer.on(a.IO_ERROR,(e,t)=>{this._emitter.emit(n.ERROR,_.NETWORK_ERROR,e,t)}),this._transmuxer.on(a.DEMUX_ERROR,(e,t)=>{this._emitter.emit(n.ERROR,_.MEDIA_ERROR,e,{code:-1,msg:t})}),this._transmuxer.on(a.MEDIA_INFO,e=>{this._mediaInfo=e,this._emitter.emit(n.MEDIA_INFO,Object.assign({},e))}),this._transmuxer.on(a.METADATA_ARRIVED,e=>{this._emitter.emit(n.METADATA_ARRIVED,e)}),this._transmuxer.on(a.SCRIPTDATA_ARRIVED,e=>{this._emitter.emit(n.SCRIPTDATA_ARRIVED,e)}),this._transmuxer.on(a.STATISTICS_INFO,e=>{this._statisticsInfo=this._fillStatisticsInfo(e),this._emitter.emit(n.STATISTICS_INFO,Object.assign({},this._statisticsInfo))}),this._transmuxer.on(a.RECOMMEND_SEEKPOINT,e=>{this._mediaElement&&!this._config.accurateSeek&&(this._requestSetTime=!0,this._mediaElement.currentTime=e/1e3)}),this._transmuxer.open()}}unload(){this._mediaElement&&this._mediaElement.pause(),this._msectl&&this._msectl.seek(0),this._transmuxer&&(this._transmuxer.close(),this._transmuxer.destroy(),this._transmuxer=null)}play(){return this._mediaElement.play()}pause(){this._mediaElement.pause()}get type(){return this._type}get buffered(){return this._mediaElement.buffered}get duration(){return this._mediaElement.duration}get volume(){return this._mediaElement.volume}set volume(e){this._mediaElement.volume=e}get muted(){return this._mediaElement.muted}set muted(e){this._mediaElement.muted=e}get currentTime(){return this._mediaElement?this._mediaElement.currentTime:0}set currentTime(e){this._mediaElement?this._internalSeek(e):this._pendingSeekTime=e}get mediaInfo(){return Object.assign({},this._mediaInfo)}get statisticsInfo(){return this._statisticsInfo==null&&(this._statisticsInfo={}),this._statisticsInfo=this._fillStatisticsInfo(this._statisticsInfo),Object.assign({},this._statisticsInfo)}_fillStatisticsInfo(e){if(e.playerType=this._type,!(this._mediaElement instanceof HTMLVideoElement))return e;let t=!0,i=0,s=0;if(this._mediaElement.getVideoPlaybackQuality){let r=this._mediaElement.getVideoPlaybackQuality();i=r.totalVideoFrames,s=r.droppedVideoFrames}else this._mediaElement.webkitDecodedFrameCount!=null?(i=this._mediaElement.webkitDecodedFrameCount,s=this._mediaElement.webkitDroppedFrameCount):t=!1;return t&&(e.decodedFrames=i,e.droppedFrames=s),e}_onmseUpdateEnd(){if(!this._config.lazyLoad||this._config.isLive)return;let e=this._mediaElement.buffered,t=this._mediaElement.currentTime,i=0,s=0;for(let r=0;r<e.length;r++){let l=e.start(r),d=e.end(r);if(l<=t&&t<d){i=l,s=d;break}}s>=t+this._config.lazyLoadMaxDuration&&this._progressChecker==null&&(h.v(this.TAG,"Maximum buffering duration exceeded, suspend transmuxing task"),this._suspendTransmuxer())}_onmseBufferFull(){h.v(this.TAG,"MSE SourceBuffer is full, suspend transmuxing task"),this._progressChecker==null&&this._suspendTransmuxer()}_suspendTransmuxer(){this._transmuxer&&(this._transmuxer.pause(),this._progressChecker==null&&(this._progressChecker=window.setInterval(this._checkProgressAndResume.bind(this),1e3)))}_checkProgressAndResume(){let e=this._mediaElement.currentTime,t=this._mediaElement.buffered,i=!1;for(let s=0;s<t.length;s++){let r=t.start(s),l=t.end(s);if(e>=r&&e<l){e>=l-this._config.lazyLoadRecoverDuration&&(i=!0);break}}i&&(window.clearInterval(this._progressChecker),this._progressChecker=null,i&&(h.v(this.TAG,"Continue loading from paused position"),this._transmuxer.resume()))}_isTimepointBuffered(e){let t=this._mediaElement.buffered;for(let i=0;i<t.length;i++){let s=t.start(i),r=t.end(i);if(e>=s&&e<r)return!0}return!1}_internalSeek(e){let t=this._isTimepointBuffered(e),i=!1,s=0;if(e<1&&this._mediaElement.buffered.length>0){let r=this._mediaElement.buffered.start(0);(r<1&&e<r||m.safari)&&(i=!0,s=m.safari?.1:r)}if(i)this._requestSetTime=!0,this._mediaElement.currentTime=s;else if(t){if(!this._alwaysSeekKeyframe)this._requestSetTime=!0,this._mediaElement.currentTime=e;else{let r=this._msectl.getNearestKeyframe(Math.floor(e*1e3));this._requestSetTime=!0,r!=null?this._mediaElement.currentTime=r.dts/1e3:this._mediaElement.currentTime=e}this._progressChecker!=null&&this._checkProgressAndResume()}else this._progressChecker!=null&&(window.clearInterval(this._progressChecker),this._progressChecker=null),this._msectl.seek(e),this._transmuxer.seek(Math.floor(e*1e3)),this._config.accurateSeek&&(this._requestSetTime=!0,this._mediaElement.currentTime=e)}_checkAndApplyUnbufferedSeekpoint(){if(this._seekpointRecord)if(this._seekpointRecord.recordTime<=this._now()-100){let e=this._mediaElement.currentTime;this._seekpointRecord=null,this._isTimepointBuffered(e)||(this._progressChecker!=null&&(window.clearTimeout(this._progressChecker),this._progressChecker=null),this._msectl.seek(e),this._transmuxer.seek(Math.floor(e*1e3)),this._config.accurateSeek&&(this._requestSetTime=!0,this._mediaElement.currentTime=e))}else window.setTimeout(this._checkAndApplyUnbufferedSeekpoint.bind(this),50)}_checkAndResumeStuckPlayback(e){let t=this._mediaElement;if(e||!this._receivedCanPlay||t.readyState<2){let i=t.buffered;i.length>0&&t.currentTime<i.start(0)&&(h.w(this.TAG,`Playback seems stuck at ${t.currentTime}, seek to ${i.start(0)}`),this._requestSetTime=!0,this._mediaElement.currentTime=i.start(0),this._mediaElement.removeEventListener("progress",this.e.onvProgress))}else this._mediaElement.removeEventListener("progress",this.e.onvProgress)}_onvLoadedMetadata(e){this._pendingSeekTime!=null&&(this._mediaElement.currentTime=this._pendingSeekTime,this._pendingSeekTime=null)}_onvSeeking(e){let t=this._mediaElement.currentTime,i=this._mediaElement.buffered;if(this._requestSetTime){this._requestSetTime=!1;return}if(t<1&&i.length>0){let s=i.start(0);if(s<1&&t<s||m.safari){this._requestSetTime=!0,this._mediaElement.currentTime=m.safari?.1:s;return}}if(this._isTimepointBuffered(t)){if(this._alwaysSeekKeyframe){let s=this._msectl.getNearestKeyframe(Math.floor(t*1e3));s!=null&&(this._requestSetTime=!0,this._mediaElement.currentTime=s.dts/1e3)}this._progressChecker!=null&&this._checkProgressAndResume();return}this._seekpointRecord={seekPoint:t,recordTime:this._now()},window.setTimeout(this._checkAndApplyUnbufferedSeekpoint.bind(this),50)}_onvCanPlay(e){this._receivedCanPlay=!0,this._mediaElement.removeEventListener("canplay",this.e.onvCanPlay)}_onvStalled(e){this._checkAndResumeStuckPlayback(!0)}_onvProgress(e){this._checkAndResumeStuckPlayback()}}export default v;
|