jellyfin-web/dashboard-ui/bower_components/emby-webcomponents/htmlvideoplayer/plugin.js
2017-01-31 16:29:59 -05:00

1 line
20 KiB
JavaScript

define(["browser","pluginManager","events","apphost","loading","playbackManager","embyRouter","appSettings","connectionManager"],function(browser,pluginManager,events,appHost,loading,playbackManager,embyRouter,appSettings,connectionManager){"use strict";return function(){function getSavedVolume(){return appSettings.get("volume")||1}function saveVolume(value){value&&appSettings.set("volume",value)}function getBaseProfileOptions(item){var disableHlsVideoAudioCodecs=[];(!canPlayNativeHls()||browser.edge&&!item.RunTimeTicks)&&(browser.edge&&disableHlsVideoAudioCodecs.push("mp3"),disableHlsVideoAudioCodecs.push("ac3"));var enableMkvProgressive=!(!item.RunTimeTicks||!browser.edgeUwp);return{enableMkvProgressive:enableMkvProgressive,disableHlsVideoAudioCodecs:disableHlsVideoAudioCodecs}}function getDeviceProfileForWindowsUwp(item){return new Promise(function(resolve,reject){require(["browserdeviceprofile","environments/windows-uwp/mediacaps"],function(profileBuilder,uwpMediaCaps){var profileOptions=getBaseProfileOptions(item);profileOptions.supportsDts=uwpMediaCaps.supportsDTS(),profileOptions.supportsTrueHd=uwpMediaCaps.supportsDolby(),profileOptions.audioChannels=uwpMediaCaps.getAudioChannels(),resolve(profileBuilder(profileOptions))})})}function updateVideoUrl(streamInfo){var isHls=streamInfo.url.toLowerCase().indexOf(".m3u8")!==-1,mediaSource=streamInfo.mediaSource,item=streamInfo.item;if(mediaSource&&item&&!mediaSource.RunTimeTicks&&isHls&&(browser.iOS||browser.osx)){var hlsPlaylistUrl=streamInfo.url.replace("master.m3u8","live.m3u8");return loading.show(),console.log("prefetching hls playlist: "+hlsPlaylistUrl),connectionManager.getApiClient(item.ServerId).ajax({type:"GET",url:hlsPlaylistUrl}).then(function(){return console.log("completed prefetching hls playlist: "+hlsPlaylistUrl),loading.hide(),streamInfo.url=hlsPlaylistUrl,Promise.resolve()},function(){return console.log("error prefetching hls playlist: "+hlsPlaylistUrl),loading.hide(),Promise.resolve()})}return Promise.resolve()}function getSupportedFeatures(){var list=[],video=document.createElement("video");return browser.ipad&&navigator.userAgent.toLowerCase().indexOf("os 9")===-1&&video.webkitSupportsPresentationMode&&video.webkitSupportsPresentationMode&&"function"==typeof video.webkitSetPresentationMode&&list.push("pictureinpicture"),list}function getCrossOriginValue(mediaSource){return"anonymous"}function requireHlsPlayer(callback){require(["hlsjs"],function(hls){window.Hls=hls,callback()})}function setCurrentSrc(elem,options){var val=options.url;console.log("playing url: "+val);var seconds=(options.playerStartPositionTicks||0)/1e7;seconds&&(val+="#t="+seconds),destroyHlsPlayer();for(var tracks=getMediaStreamTextTracks(options.mediaSource),currentTrackIndex=-1,i=0,length=tracks.length;i<length;i++)if(tracks[i].Index===options.mediaSource.DefaultSubtitleStreamIndex){currentTrackIndex=tracks[i].Index;break}if(subtitleTrackIndexToSetOnPlaying=currentTrackIndex,currentPlayOptions=options,elem.crossOrigin=getCrossOriginValue(options.mediaSource),enableHlsPlayer(val,options.item,options.mediaSource))return setTracks(elem,tracks,options.mediaSource,options.item.ServerId),new Promise(function(resolve,reject){requireHlsPlayer(function(){var hls=new Hls({manifestLoadingTimeOut:2e4});hls.loadSource(val),hls.attachMedia(elem),hls.on(Hls.Events.MANIFEST_PARSED,function(){playWithPromise(elem).then(resolve,reject)}),hls.on(Hls.Events.ERROR,function(event,data){if(console.log("HLS Error: Type: "+data.type+" Details: "+(data.details||"")+" Fatal: "+(data.fatal||!1)),data.fatal)switch(data.type){case Hls.ErrorTypes.NETWORK_ERROR:console.log("fatal network error encountered, try to recover"),hls.startLoad();break;case Hls.ErrorTypes.MEDIA_ERROR:console.log("fatal media error encountered, try to recover"),handleMediaError();break;default:hls.destroy()}}),hlsPlayer=hls,currentSrc=val,setCurrentTrackElement(currentTrackIndex)})});elem.autoplay=!0;var mimeType=options.mimeType;return mimeType&&browser.operaTv?(browser.chrome&&"video/x-matroska"===mimeType&&(mimeType="video/webm"),elem.currentSrc&&(elem.src="",elem.removeAttribute("src")),elem.innerHTML='<source src="'+val+'" type="'+mimeType+'">'+getTracksHtml(tracks,options.mediaSource,options.item.ServerId),elem.addEventListener("loadedmetadata",onLoadedMetadata)):(applySrc(elem,val),setTracks(elem,tracks,options.mediaSource,options.item.ServerId)),currentSrc=val,setCurrentTrackElement(currentTrackIndex),playWithPromise(elem)}function handleMediaError(){if(hlsPlayer){var now=Date.now();window.performance&&window.performance.now&&(now=performance.now()),!recoverDecodingErrorDate||now-recoverDecodingErrorDate>3e3?(recoverDecodingErrorDate=now,console.log("try to recover media Error ..."),hlsPlayer.recoverMediaError()):!recoverSwapAudioCodecDate||now-recoverSwapAudioCodecDate>3e3?(recoverSwapAudioCodecDate=now,console.log("try to swap Audio Codec and recover media Error ..."),hlsPlayer.swapAudioCodec(),hlsPlayer.recoverMediaError()):console.error("cannot recover, last media error recovery failed ...")}}function applySrc(elem,src){if(window.Windows){var playlist=new Windows.Media.Playback.MediaPlaybackList,source1=Windows.Media.Core.MediaSource.createFromUri(new Windows.Foundation.Uri(src));winJsPlaybackItem=new Windows.Media.Playback.MediaPlaybackItem(source1),playlist.items.append(winJsPlaybackItem),elem.src=URL.createObjectURL(playlist,{oneTimeOnly:!0})}else elem.src=src}function playWithPromise(elem){try{var promise=elem.play();return promise&&promise.then?promise.catch(function(e){var errorName=(e.name||"").toLowerCase();return"notallowederror"===errorName||"aborterror"===errorName?Promise.resolve():Promise.reject()}):Promise.resolve()}catch(err){return console.log("error calling video.play: "+err),Promise.reject()}}function destroyHlsPlayer(){var player=hlsPlayer;if(player){try{player.destroy()}catch(err){console.log(err)}hlsPlayer=null}}function onEnded(){destroyCustomTrack(this),onEndedInternal(!0)}function onEndedInternal(triggerEnded){if(self.originalDocumentTitle&&(document.title=self.originalDocumentTitle,self.originalDocumentTitle=null),triggerEnded){var stopInfo={src:currentSrc};events.trigger(self,"stopped",[stopInfo]),_currentTime=null}currentSrc=null,winJsPlaybackItem=null}function onTimeUpdate(e){var time=this.currentTime;_currentTime=time;var timeMs=1e3*time;timeMs+=(currentPlayOptions.transcodingOffsetTicks||0)/1e4,updateSubtitleText(timeMs),events.trigger(self,"timeupdate")}function onVolumeChange(){saveVolume(this.volume),events.trigger(self,"volumechange")}function onNavigatedToOsd(){videoDialog.classList.remove("videoPlayerContainer-withBackdrop"),videoDialog.classList.remove("videoPlayerContainer-onTop")}function onPlaying(e){started||(started=!0,this.removeAttribute("controls"),currentPlayOptions.title?(self.originalDocumentTitle=document.title,document.title=currentPlayOptions.title):self.originalDocumentTitle=null,setCurrentTrackElement(subtitleTrackIndexToSetOnPlaying),seekOnPlaybackStart(e.target),currentPlayOptions.fullscreen?embyRouter.showVideoOsd().then(onNavigatedToOsd):(embyRouter.setTransparency("backdrop"),videoDialog.classList.remove("videoPlayerContainer-withBackdrop"),videoDialog.classList.remove("videoPlayerContainer-onTop")),loading.hide()),events.trigger(self,"playing")}function seekOnPlaybackStart(element){var seconds=(currentPlayOptions.playerStartPositionTicks||0)/1e7;if(seconds){var src=(self.currentSrc()||"").toLowerCase();if(!browser.chrome||src.indexOf(".m3u8")!==-1){var delay=browser.safari?2500:0;delay?setTimeout(function(){element.currentTime=seconds},delay):element.currentTime=seconds}}}function onClick(){events.trigger(self,"click")}function onDblClick(){events.trigger(self,"dblclick")}function onPause(){events.trigger(self,"pause")}function onError(){var errorCode=this.error?this.error.code||0:0;console.log("Media element error code: "+errorCode.toString());var type;switch(errorCode){case 1:return;case 2:type="network";break;case 3:return void handleMediaError();case 4:}destroyCustomTrack(this)}function onLoadedMetadata(e){var mediaElem=e.target;if(mediaElem.removeEventListener("loadedmetadata",onLoadedMetadata),!hlsPlayer)try{mediaElem.play()}catch(err){console.log("error calling mediaElement.play: "+err)}}function enableHlsPlayer(src,item,mediaSource){return(!src||src.indexOf(".m3u8")!==-1)&&(null!=window.MediaSource&&((!canPlayNativeHls()||!mediaSource.RunTimeTicks)&&!(browser.safari&&!browser.osx)))}function canPlayNativeHls(){var media=document.createElement("video");return!(!media.canPlayType("application/x-mpegURL").replace(/no/,"")&&!media.canPlayType("application/vnd.apple.mpegURL").replace(/no/,""))}function setTracks(elem,tracks,mediaSource,serverId){elem.innerHTML=getTracksHtml(tracks,mediaSource,serverId)}function getTextTrackUrl(track,serverId){return playbackManager.getSubtitleUrl(track,serverId)}function getTracksHtml(tracks,mediaSource,serverId){return tracks.map(function(t){var defaultAttribute=mediaSource.DefaultSubtitleStreamIndex===t.Index?" default":"",language=t.Language||"und",label=t.Language||"und";return'<track id="textTrack'+t.Index+'" label="'+label+'" kind="subtitles" src="'+getTextTrackUrl(t,serverId)+'" srclang="'+language+'"'+defaultAttribute+"></track>"}).join("")}function enableNativeTrackSupport(track){if(browser.firefox&&(currentSrc||"").toLowerCase().indexOf(".m3u8")!==-1)return!1;if(browser.ps4)return!1;if(track){var format=(track.Codec||"").toLowerCase();if("ssa"===format||"ass"===format)return!1}return!0}function destroyCustomTrack(videoElement,isPlaying){if(window.removeEventListener("resize",onVideoResize),window.removeEventListener("orientationchange",onVideoResize),isPlaying)for(var allTracks=mediaElement.textTracks,i=0;i<allTracks.length;i++){var currentTrack=allTracks[i];currentTrack.label.indexOf("manualTrack")!==-1&&(currentTrack.mode="disabled")}customTrackIndex=-1,currentClock=null;var renderer=currentAssRenderer;renderer&&renderer.setEnabled(!1),currentAssRenderer=null}function fetchSubtitles(track,serverId){return new Promise(function(resolve,reject){require(["fetchHelper"],function(fetchHelper){fetchHelper.ajax({url:getTextTrackUrl(track,serverId).replace(".vtt",".js"),type:"GET",dataType:"json"}).then(resolve,reject)})})}function setTrackForCustomDisplay(videoElement,track){if(!track)return void destroyCustomTrack(videoElement,!0);if(customTrackIndex!==track.Index){var serverId=currentPlayOptions.item.ServerId;destroyCustomTrack(videoElement,!0),customTrackIndex=track.Index,renderTracksEvents(videoElement,track,serverId),lastCustomTrackMs=0}}function renderWithLibjass(videoElement,track,serverId){var rendererSettings={};require(["libjass"],function(libjass){libjass.ASS.fromUrl(getTextTrackUrl(track,serverId)).then(function(ass){var clock=new libjass.renderers.ManualClock;currentClock=clock;var renderer=new libjass.renderers.WebRenderer(ass,clock,videoElement.parentNode,rendererSettings);currentAssRenderer=renderer,renderer.addEventListener("ready",function(){try{renderer.resize(videoElement.offsetWidth,videoElement.offsetHeight,0,0),window.removeEventListener("resize",onVideoResize),window.addEventListener("resize",onVideoResize),window.removeEventListener("orientationchange",onVideoResize),window.addEventListener("orientationchange",onVideoResize)}catch(ex){}})})})}function onVideoResize(){var renderer=currentAssRenderer;if(renderer){var videoElement=mediaElement,width=videoElement.offsetWidth,height=videoElement.offsetHeight;console.log("videoElement resized: "+width+"x"+height),renderer.resize(width,height,0,0)}}function renderTracksEvents(videoElement,track,serverId){var format=(track.Codec||"").toLowerCase();if("ssa"===format||"ass"===format)return void renderWithLibjass(videoElement,track,serverId);for(var trackElement=null,expectedId="manualTrack"+track.Index,allTracks=videoElement.textTracks,i=0;i<allTracks.length;i++){var currentTrack=allTracks[i];if(currentTrack.label===expectedId){trackElement=currentTrack;break}currentTrack.mode="disabled"}trackElement?trackElement.mode="showing":(trackElement=videoElement.addTextTrack("subtitles","manualTrack"+track.Index,track.Language||"und"),fetchSubtitles(track,serverId).then(function(data){console.log("downloaded "+data.TrackEvents.length+" track events"),data.TrackEvents.forEach(function(trackEvent){var trackCueObject=window.VTTCue||window.TextTrackCue,cue=new trackCueObject(trackEvent.StartPositionTicks/1e7,trackEvent.EndPositionTicks/1e7,trackEvent.Text.replace(/\\N/gi,"\n"));trackElement.addCue(cue)}),trackElement.mode="showing"}))}function updateSubtitleText(timeMs){var clock=currentClock;clock&&clock.seek(timeMs/1e3)}function getMediaStreamAudioTracks(mediaSource){return mediaSource.MediaStreams.filter(function(s){return"Audio"===s.Type})}function getMediaStreamTextTracks(mediaSource){return mediaSource.MediaStreams.filter(function(s){return"Subtitle"===s.Type&&"External"===s.DeliveryMethod})}function setCurrentTrackElement(streamIndex){console.log("Setting new text track index to: "+streamIndex);var mediaStreamTextTracks=getMediaStreamTextTracks(currentPlayOptions.mediaSource),track=streamIndex===-1?null:mediaStreamTextTracks.filter(function(t){return t.Index===streamIndex})[0];enableNativeTrackSupport(track)?setTrackForCustomDisplay(mediaElement,null):(setTrackForCustomDisplay(mediaElement,track),streamIndex=-1,track=null);for(var expectedId="textTrack"+streamIndex,trackIndex=streamIndex!==-1&&track?mediaStreamTextTracks.indexOf(track):-1,modes=["disabled","showing","hidden"],allTracks=mediaElement.textTracks,i=0;i<allTracks.length;i++){var currentTrack=allTracks[i];console.log("currentTrack id: "+currentTrack.id);var mode;if(console.log("expectedId: "+expectedId+"--currentTrack.Id:"+currentTrack.id),browser.msie||browser.edge)mode=trackIndex===i?1:0;else{if(currentTrack.label.indexOf("manualTrack")!==-1)continue;mode=currentTrack.id===expectedId?1:0}console.log("Setting track "+i+" mode to: "+mode);var useNumericMode=!1;!isNaN(currentTrack.mode),useNumericMode?currentTrack.mode=mode:currentTrack.mode=modes[mode]}}function zoomIn(elem,iterations){var keyframes=[{transform:"scale3d(.2, .2, .2) ",opacity:".6",offset:0},{transform:"none",opacity:"1",offset:1}],timing={duration:240,iterations:iterations};return elem.animate(keyframes,timing)}function createMediaElement(options){return(browser.tv||browser.noAnimation||browser.iOS)&&(options.backdropUrl=null),new Promise(function(resolve,reject){var dlg=document.querySelector(".videoPlayerContainer");dlg?(options.backdropUrl&&(dlg.classList.add("videoPlayerContainer-withBackdrop"),dlg.style.backgroundImage="url('"+options.backdropUrl+"')"),resolve(dlg.querySelector("video"))):require(["css!"+pluginManager.mapPath(self,"style.css")],function(){loading.show();var dlg=document.createElement("div");dlg.classList.add("videoPlayerContainer"),options.backdropUrl&&(dlg.classList.add("videoPlayerContainer-withBackdrop"),dlg.style.backgroundImage="url('"+options.backdropUrl+"')"),options.fullscreen&&dlg.classList.add("videoPlayerContainer-onTop");var html="";html+=appHost.supports("htmlvideoautoplay")?'<video class="htmlvideoplayer" preload="metadata" autoplay="autoplay" webkit-playsinline playsinline>':'<video class="htmlvideoplayer" preload="metadata" autoplay="autoplay" controls="controls" webkit-playsinline playsinline>',html+="</video>",dlg.innerHTML=html;var videoElement=dlg.querySelector("video");videoElement.volume=getSavedVolume(),videoElement.addEventListener("timeupdate",onTimeUpdate),videoElement.addEventListener("ended",onEnded),videoElement.addEventListener("volumechange",onVolumeChange),videoElement.addEventListener("pause",onPause),videoElement.addEventListener("playing",onPlaying),videoElement.addEventListener("error",onError),videoElement.addEventListener("click",onClick),videoElement.addEventListener("dblclick",onDblClick),document.body.insertBefore(dlg,document.body.firstChild),videoDialog=dlg,mediaElement=videoElement,options.fullscreen&&dlg.animate&&!browser.slow?zoomIn(dlg,1).onfinish=function(){resolve(videoElement)}:resolve(videoElement)})})}var self=this;self.name="Html Video Player",self.type="mediaplayer",self.id="htmlvideoplayer",self.priority=1;var mediaElement,videoDialog,currentSrc,hlsPlayer,winJsPlaybackItem,currentPlayOptions,subtitleTrackIndexToSetOnPlaying,currentClock,currentAssRenderer,started=!1,lastCustomTrackMs=0,customTrackIndex=-1;self.canPlayMediaType=function(mediaType){return"video"===(mediaType||"").toLowerCase()},self.getDeviceProfile=function(item){return window.Windows?getDeviceProfileForWindowsUwp(item):new Promise(function(resolve,reject){require(["browserdeviceprofile"],function(profileBuilder){var profile=profileBuilder(getBaseProfileOptions(item));browser.edge||browser.msie||(profile.SubtitleProfiles.push({Format:"ass",Method:"External"}),profile.SubtitleProfiles.push({Format:"ssa",Method:"External"})),resolve(profile)})})},self.currentSrc=function(){return currentSrc},self.play=function(options){return browser.msie&&"Transcode"===options.playMethod?(alert("Playback of this content is not supported in Internet Explorer. For a better experience, try a modern browser such as Microsoft Edge, Google Chrome, Firefox or Opera."),Promise.reject()):(started=!1,_currentTime=null,createMediaElement(options).then(function(elem){return updateVideoUrl(options,options.mediaSource).then(function(){return setCurrentSrc(elem,options)})}))};var supportedFeatures;self.supports=function(feature){return supportedFeatures||(supportedFeatures=getSupportedFeatures()),supportedFeatures.indexOf(feature)!==-1},self.togglePictureInPicture=function(){return self.setPictureInPictureEnabled(!self.isPictureInPictureEnabled())},self.setPictureInPictureEnabled=function(isEnabled){var video=mediaElement;video&&video.webkitSupportsPresentationMode&&"function"==typeof video.webkitSetPresentationMode&&video.webkitSetPresentationMode(isEnabled?"picture-in-picture":"inline")},self.isPictureInPictureEnabled=function(isEnabled){var video=mediaElement;return!!video&&"picture-in-picture"===video.webkitPresentationMode};var recoverDecodingErrorDate,recoverSwapAudioCodecDate;self.setSubtitleStreamIndex=function(index){setCurrentTrackElement(index)},self.canSetAudioStreamIndex=function(){return!!winJsPlaybackItem},self.setAudioStreamIndex=function(index){var audioTracks=getMediaStreamAudioTracks(currentPlayOptions.mediaSource),track=audioTracks.filter(function(t){return t.Index===index})[0];if(track&&winJsPlaybackItem){var audioIndex=audioTracks.indexOf(track);winJsPlaybackItem.audioTracks.selectedIndex=audioIndex}};var _currentTime;self.currentTime=function(val){if(mediaElement)return null!=val?void(mediaElement.currentTime=val/1e3):_currentTime?1e3*_currentTime:1e3*(mediaElement.currentTime||0)},self.duration=function(val){if(mediaElement){var duration=mediaElement.duration;if(duration&&!isNaN(duration)&&duration!==Number.POSITIVE_INFINITY&&duration!==Number.NEGATIVE_INFINITY)return 1e3*duration}return null},self.stop=function(destroyPlayer,reportEnded){var elem=mediaElement,src=currentSrc;return elem&&src&&(elem.pause(),elem.src="",elem.innerHTML="",elem.removeAttribute("src"),destroyHlsPlayer(),onEndedInternal(reportEnded),destroyPlayer&&self.destroy()),destroyCustomTrack(elem),Promise.resolve()},self.destroy=function(){destroyHlsPlayer(),embyRouter.setTransparency("none");var videoElement=mediaElement;videoElement&&(mediaElement=null,destroyCustomTrack(videoElement),videoElement.removeEventListener("timeupdate",onTimeUpdate),videoElement.removeEventListener("ended",onEnded),videoElement.removeEventListener("volumechange",onVolumeChange),videoElement.removeEventListener("pause",onPause),videoElement.removeEventListener("playing",onPlaying),videoElement.removeEventListener("error",onError),videoElement.removeEventListener("loadedmetadata",onLoadedMetadata),videoElement.removeEventListener("click",onClick),videoElement.removeEventListener("dblclick",onDblClick),videoElement.parentNode.removeChild(videoElement));var dlg=videoDialog;dlg&&(videoDialog=null,dlg.parentNode.removeChild(dlg))},self.pause=function(){mediaElement&&mediaElement.pause()},self.resume=function(){mediaElement&&mediaElement.play()},self.unpause=function(){mediaElement&&mediaElement.play()},self.paused=function(){return!!mediaElement&&mediaElement.paused},self.setVolume=function(val){mediaElement&&(mediaElement.volume=val/100)},self.getVolume=function(){if(mediaElement)return 100*mediaElement.volume},self.volumeUp=function(){self.setVolume(Math.min(self.getVolume()+2,100))},self.volumeDown=function(){self.setVolume(Math.max(self.getVolume()-2,0))},self.setMute=function(mute){mediaElement&&(mediaElement.muted=mute)},self.isMuted=function(){return!!mediaElement&&mediaElement.muted}}});