- fixes as a result of documentation, fixed secondaryVideo
- added muted option, changing tracks sets options.setTracks
- no positive values for startunix when live seeking
- dashjs tracks updated, videojs display tweaked
- fixes for track selection and live seeking
This commit is contained in:
Cat 2018-12-20 16:48:39 +01:00 committed by Thulinma
parent 0a1b00cb5e
commit 998d7c6d03
22 changed files with 283 additions and 119 deletions

File diff suppressed because one or more lines are too long

View file

@ -1,7 +1,7 @@
.mistvideo{display:inline-block;position:relative;color:$stroke;font-family:sans-serif;background-color:#000;justify-content:center;align-items:center}
.mistvideo-controls{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.mistvideo.novideo{overflow:visible}
.mistvideo-video{overflow:hidden}
.mistvideo-video{overflow:hidden;outline:0}
svg.icon.loading{z-index:-1;position:absolute;top:0;left:0;right:0;bottom:0;margin:auto;opacity:0}
[data-loading]{position:relative}
[data-loading=stalled] svg.icon.loading{transition:opacity 0s 3s}
@ -61,6 +61,7 @@ svg.icon .semiFill,svg.icon.semiFill{fill:$semiFill}
svg.icon .stroke,svg.icon.stroke{stroke:$stroke;vector-effect:non-scaling-stroke}
svg.icon.off .toggle .fill,svg.icon.off .toggle .semiFill,svg.icon.off .toggle.fill,svg.icon.off .toggle.semiFill{fill:none}
svg.icon .spin,svg.icon.spin{animation:spin 1.5s infinite linear;transform-origin:50% 50%}
.vjs-text-track-display{pointer-events:none}
.mistvideo{line-height:1.2;font-size:14.5px}
.mistvideo svg{margin:2.5px}
.mistvideo-background{background-color:$background}
@ -79,7 +80,7 @@ svg.icon.timeout{display:inline-block;height:1em;width:1em;margin:0;margin-right
.mist.largeplay,.mist.muted{position:absolute;opacity:.5}
.mist.largeplay{top:50%;left:0;right:0;margin:auto;transform:translateY(-50%)}
.mist.muted{top:0;right:0;margin:1em}
.mistvideo-secondaryVideo{z-index:1;width:50%;height:50%}
.mistvideo-secondaryVideo{z-index:1;position:absolute;right:0;top:0;width:50%;height:50%;max-width:fit-content;max-height:fit-content}
.mistvideo-polling{display:inline-block;position:relative;width:25px;height:25px}
.mistvideo-polling svg.icon.loading{z-index:0;opacity:1}
.mistvideo[data-show-submenu] .mistvideo-submenu{right:5px}

View file

@ -1,7 +1,7 @@
.mistvideo{display:inline-block;position:relative;color:$stroke;font-family:sans-serif;background-color:#000;justify-content:center;align-items:center}
.mistvideo-controls{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.mistvideo.novideo{overflow:visible}
.mistvideo-video{overflow:hidden}
.mistvideo-video{overflow:hidden;outline:0}
svg.icon.loading{z-index:-1;position:absolute;top:0;left:0;right:0;bottom:0;margin:auto;opacity:0}
[data-loading]{position:relative}
[data-loading=stalled] svg.icon.loading{transition:opacity 0s 3s}
@ -61,6 +61,7 @@ svg.icon .semiFill,svg.icon.semiFill{fill:$semiFill}
svg.icon .stroke,svg.icon.stroke{stroke:$stroke;vector-effect:non-scaling-stroke}
svg.icon.off .toggle .fill,svg.icon.off .toggle .semiFill,svg.icon.off .toggle.fill,svg.icon.off .toggle.semiFill{fill:none}
svg.icon .spin,svg.icon.spin{animation:spin 1.5s infinite linear;transform-origin:50% 50%}
.vjs-text-track-display{pointer-events:none}
.mistvideo{line-height:1.2;font-size:14.5px}
.mistvideo svg{margin:2.5px}
.mistvideo-background{background-color:$background}
@ -79,7 +80,7 @@ svg.icon.timeout{display:inline-block;height:1em;width:1em;margin:0;margin-right
.mist.largeplay,.mist.muted{position:absolute;opacity:.5}
.mist.largeplay{top:50%;left:0;right:0;margin:auto;transform:translateY(-50%)}
.mist.muted{top:0;right:0;margin:1em}
.mistvideo-secondaryVideo{z-index:1;width:50%;height:50%}
.mistvideo-secondaryVideo{z-index:1;position:absolute;right:0;top:0;width:50%;height:50%;max-width:fit-content;max-height:fit-content}
.mistvideo-polling{display:inline-block;position:relative;width:25px;height:25px}
.mistvideo-polling svg.icon.loading{z-index:0;opacity:1}
.mistvideo[data-show-submenu] .mistvideo-submenu{right:5px}

View file

@ -1 +1 @@
mistplayers.dashjs={name:"Dash.js player",mimes:["dash/video/mp4"],priority:MistUtil.object.keys(mistplayers).length+1,isMimeSupported:function(t){return MistUtil.array.indexOf(this.mimes,t)==-1?false:true},isBrowserSupported:function(t,e,i){if(location.protocol!=MistUtil.http.url.split(e.url).protocol){i.log("HTTP/HTTPS mismatch for this source");return false}if(location.protocol=="file:"){i.log("This source ("+t+") won't load if the page is run via file://");return false}return"MediaSource"in window},player:function(){this.onreadylist=[]},scriptsrc:function(t){return t+"/dashjs.js"}};var p=mistplayers.dashjs.player;p.prototype=new MistPlayer;p.prototype.build=function(t,e){var i=this;this.onDashLoad=function(){if(t.destroyed){return}t.log("Building DashJS player..");var r=document.createElement("video");if("Proxy"in window){var a={get:{},set:{}};t.player.api=new Proxy(r,{get:function(t,e,i){if(e in a.get){return a.get[e].apply(t,arguments)}var r=t[e];if(typeof r==="function"){return function(){return r.apply(t,arguments)}}return r},set:function(t,e,i){if(e in a.set){return a.set[e].call(t,i)}return t[e]=i}});if(t.info.type=="live"){a.get.duration=function(){var e=0;if(this.buffered.length){e=this.buffered.end(this.buffered.length-1)}var i=((new Date).getTime()-t.player.api.lastProgress.getTime())*.001;return e+i+-1*t.player.api.liveOffset+45};a.set.currentTime=function(e){var i=e-t.player.api.duration;t.log("Seeking to "+MistUtil.format.time(e)+" ("+Math.round(i*-10)/10+"s from live)");t.video.currentTime=e};MistUtil.event.addListener(r,"progress",function(){t.player.api.lastProgress=new Date});t.player.api.lastProgress=new Date;t.player.api.liveOffset=0}}else{i.api=r}if(t.options.autoplay){r.setAttribute("autoplay","")}if(t.options.loop&&t.info.type!="live"){r.setAttribute("loop","")}if(t.options.poster){r.setAttribute("poster",t.options.poster)}if(t.options.controls=="stock"){r.setAttribute("controls","")}var s=dashjs.MediaPlayer().create();s.initialize(r,t.source.url,t.options.autoplay);i.dash=s;var o=["METRIC_ADDED","METRIC_CHANGED","METRICS_CHANGED","FRAGMENT_LOADING_STARTED","FRAGMENT_LOADING_COMPLETED","LOG","PLAYBACK_TIME_UPDATED","PLAYBACK_PROGRESS"];for(var n in dashjs.MediaPlayer.events){if(o.indexOf(n)<0){i.dash.on(dashjs.MediaPlayer.events[n],function(e){t.log("Player event fired: "+e.type)})}}t.player.setSize=function(t){this.api.style.width=t.width+"px";this.api.style.height=t.height+"px"};t.player.api.setSource=function(e){t.player.dash.attachSource(e)};t.player.api.setTrack=function(e,r){var a=MistUtil.tracks.parse(t.info.meta.tracks);if(!(e in a)||!(r in a[e])&&r!=0){t.log("Skipping trackselection of "+e+" track "+r+" because it does not exist");return}var s=i.dash.getBitrateInfoListFor("video").length-1;for(var o in t.info.meta.tracks){var n=t.info.meta.tracks[o];if(n.type==e){if(n.trackid==r){break}s--}}i.dash.setAutoSwitchQualityFor(e,false);i.dash.setFastSwitchEnabled(true);i.dash.setQualityFor(e,s)};i.dash.on("qualityChangeRendered",function(e){var r=i.dash.getBitrateInfoListFor("video").length-1;var a;for(var s in t.info.meta.tracks){var o=t.info.meta.tracks[s];if(o.type==e.mediaType){if(e.newQuality==r){a=o.trackid;break}r--}}MistUtil.event.send("playerUpdate_trackChanged",{type:e.mediaType,trackid:a},t.video)});MistUtil.event.addListener(r,"progress",function(e){if(t.container.getAttribute("data-loading")=="stalled"){t.container.removeAttribute("data-loading")}});i.api.unload=function(){i.dash.reset()};t.log("Built html");e(r)};if("dashjs"in window){this.onDashLoad()}else{var r=MistUtil.scripts.insert(t.urlappend(mistplayers.dashjs.scriptsrc(t.options.host)),{onerror:function(e){var i="Failed to load dashjs.js";if(e.message){i+=": "+e.message}t.showError(i)},onload:i.onDashLoad},t)}};
mistplayers.dashjs={name:"Dash.js player",mimes:["dash/video/mp4"],priority:MistUtil.object.keys(mistplayers).length+1,isMimeSupported:function(t){return MistUtil.array.indexOf(this.mimes,t)==-1?false:true},isBrowserSupported:function(t,e,i){if(location.protocol!=MistUtil.http.url.split(e.url).protocol){i.log("HTTP/HTTPS mismatch for this source");return false}if(location.protocol=="file:"){i.log("This source ("+t+") won't load if the page is run via file://");return false}return"MediaSource"in window},player:function(){this.onreadylist=[]},scriptsrc:function(t){return t+"/dashjs.js"}};var p=mistplayers.dashjs.player;p.prototype=new MistPlayer;p.prototype.build=function(t,e){var i=this;this.onDashLoad=function(){if(t.destroyed){return}t.log("Building DashJS player..");var r=document.createElement("video");if("Proxy"in window){var a={get:{},set:{}};t.player.api=new Proxy(r,{get:function(t,e,i){if(e in a.get){return a.get[e].apply(t,arguments)}var r=t[e];if(typeof r==="function"){return function(){return r.apply(t,arguments)}}return r},set:function(t,e,i){if(e in a.set){return a.set[e].call(t,i)}return t[e]=i}});if(t.info.type=="live"){a.get.duration=function(){var e=0;if(this.buffered.length){e=this.buffered.end(this.buffered.length-1)}var i=((new Date).getTime()-t.player.api.lastProgress.getTime())*.001;return e+i+-1*t.player.api.liveOffset+45};a.set.currentTime=function(e){var i=e-t.player.api.duration;t.log("Seeking to "+MistUtil.format.time(e)+" ("+Math.round(i*-10)/10+"s from live)");t.video.currentTime=e};MistUtil.event.addListener(r,"progress",function(){t.player.api.lastProgress=new Date});t.player.api.lastProgress=new Date;t.player.api.liveOffset=0}}else{i.api=r}if(t.options.autoplay){r.setAttribute("autoplay","")}if(t.options.loop&&t.info.type!="live"){r.setAttribute("loop","")}if(t.options.poster){r.setAttribute("poster",t.options.poster)}if(t.options.muted){r.muted=true}if(t.options.controls=="stock"){r.setAttribute("controls","")}var s=dashjs.MediaPlayer().create();s.initialize(r,t.source.url,t.options.autoplay);i.dash=s;var n=["METRIC_ADDED","METRIC_CHANGED","METRICS_CHANGED","FRAGMENT_LOADING_STARTED","FRAGMENT_LOADING_COMPLETED","LOG","PLAYBACK_TIME_UPDATED","PLAYBACK_PROGRESS"];for(var o in dashjs.MediaPlayer.events){if(n.indexOf(o)<0){i.dash.on(dashjs.MediaPlayer.events[o],function(e){t.log("Player event fired: "+e.type)})}}t.player.setSize=function(t){this.api.style.width=t.width+"px";this.api.style.height=t.height+"px"};t.player.api.setSource=function(e){t.player.dash.attachSource(e)};t.player.api.setTrack=function(e,r){var a=MistUtil.tracks.parse(t.info.meta.tracks);if(!(e in a)||!(r in a[e])&&r!=0){t.log("Skipping trackselection of "+e+" track "+r+" because it does not exist");return}var s=[];for(var n in t.info.meta.tracks){var o=t.info.meta.tracks[n];if(o.type==e){s.push(o)}}MistUtil.array.multiSort(s,["bps"]);var l=false;for(var n in s){if(s[n].trackid==r){l=n;break}}if(l===false){return false}i.dash.setAutoSwitchQualityFor(e,false);i.dash.setFastSwitchEnabled(true);i.dash.setQualityFor(e,l);return true};i.dash.on("qualityChangeRendered",function(e){var i=[];for(var r in t.info.meta.tracks){var a=t.info.meta.tracks[r];if(a.type==e.mediaType){i.push(a)}}MistUtil.array.multiSort(i,["bps"]);var s=i[e.newQuality].trackid;MistUtil.event.send("playerUpdate_trackChanged",{type:e.mediaType,trackid:s},t.video)});var l=false;i.dash.on("allTextTracksAdded",function(){l=true});t.player.api.setSubtitle=function(e){if(!l){var r=function(){t.player.api.setSubtitle(e);i.dash.off("allTextTracksAdded",r)};i.dash.on("allTextTracksAdded",r);return}if(!e){i.dash.enableText(false);return}var a=i.dash.getTracksFor("text");for(var s in a){if(a[s].id==e.trackid){i.dash.setTextTrack(s);if(!i.dash.isTextEnabled()){i.dash.enableText()}return true}}return false};MistUtil.event.addListener(r,"progress",function(e){if(t.container.getAttribute("data-loading")=="stalled"){t.container.removeAttribute("data-loading")}});i.api.unload=function(){i.dash.reset()};t.log("Built html");e(r)};if("dashjs"in window){this.onDashLoad()}else{var r=MistUtil.scripts.insert(t.urlappend(mistplayers.dashjs.scriptsrc(t.options.host)),{onerror:function(e){var i="Failed to load dashjs.js";if(e.message){i+=": "+e.message}t.showError(i)},onload:i.onDashLoad},t)}};

View file

@ -1 +1 @@
mistplayers.flash_strobe={name:"Strobe Flash media playback",mimes:["flash/10","flash/11","flash/7"],priority:MistUtil.object.keys(mistplayers).length+1,isMimeSupported:function(t){return this.mimes.indexOf(t)==-1?false:true},isBrowserSupported:function(t,e,i){if(MistUtil.http.url.split(e.url).protocol.slice(0,4)=="http"&&location.protocol!=MistUtil.http.url.split(e.url).protocol){i.log("HTTP/HTTPS mismatch for this source");return false}var r=0;try{var a=navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin;if(a.version){r=a.version.split(".")[0]}else{r=a.description.replace(/([^0-9\.])/g,"").split(".")[0]}}catch(t){}try{r=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version").replace(/([^0-9\,])/g,"").split(",")[0]}catch(t){}if(!r){return false}var l=t.split("/");return Number(r)>=Number(l[l.length-1])},player:function(){this.onreadylist=[]}};var p=mistplayers.flash_strobe.player;p.prototype=new MistPlayer;p.prototype.build=function(t,e){var i=document.createElement("object");var r=document.createElement("embed");i.appendChild(r);function a(e){var a=t.options;function l(t,e){var i=document.createElement("param");i.setAttribute("name",t);i.setAttribute("value",e);return i}MistUtil.empty(i);i.appendChild(l("movie",t.urlappend(a.host+t.source.player_url)));var s="src="+encodeURIComponent(e)+"&controlBarMode="+(a.controls?"floating":"none")+"&initialBufferTime=0.5&expandedBufferTime=5&minContinuousPlaybackTime=3"+(a.live?"&streamType=live":"")+(a.autoplay?"&autoPlay=true":"");i.appendChild(l("flashvars",s));i.appendChild(l("allowFullScreen","true"));i.appendChild(l("wmode","direct"));if(a.autoplay){i.appendChild(l("autoPlay","true"))}r.setAttribute("src",t.urlappend(t.source.player_url));r.setAttribute("type","application/x-shockwave-flash");r.setAttribute("allowfullscreen","true");r.setAttribute("flashvars",s)}a(t.source.url);this.api={};this.setSize=function(t){i.setAttribute("width",t.width);i.setAttribute("height",t.height);r.setAttribute("width",t.width);r.setAttribute("height",t.height)};this.setSize(t.calcSize());this.onready(function(){if(t.container){t.container.removeAttribute("data-loading")}});this.api.setSource=function(t){a(t)};t.log("Built html");e(i)};
mistplayers.flash_strobe={name:"Strobe Flash media playback",mimes:["flash/10","flash/11","flash/7"],priority:MistUtil.object.keys(mistplayers).length+1,isMimeSupported:function(t){return this.mimes.indexOf(t)==-1?false:true},isBrowserSupported:function(t,e,i){if(MistUtil.http.url.split(e.url).protocol.slice(0,4)=="http"&&location.protocol!=MistUtil.http.url.split(e.url).protocol){i.log("HTTP/HTTPS mismatch for this source");return false}var r=0;try{var a=navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin;if(a.version){r=a.version.split(".")[0]}else{r=a.description.replace(/([^0-9\.])/g,"").split(".")[0]}}catch(t){}try{r=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version").replace(/([^0-9\,])/g,"").split(",")[0]}catch(t){}if(!r){return false}var l=t.split("/");return Number(r)>=Number(l[l.length-1])},player:function(){this.onreadylist=[]}};var p=mistplayers.flash_strobe.player;p.prototype=new MistPlayer;p.prototype.build=function(t,e){var i=document.createElement("object");var r=document.createElement("embed");i.appendChild(r);function a(e){var a=t.options;function l(t,e){var i=document.createElement("param");i.setAttribute("name",t);i.setAttribute("value",e);return i}MistUtil.empty(i);i.appendChild(l("movie",t.urlappend(a.host+t.source.player_url)));var o="src="+encodeURIComponent(e)+"&controlBarMode="+(a.controls?"floating":"none")+"&initialBufferTime=0.5&expandedBufferTime=5&minContinuousPlaybackTime=3"+(a.live?"&streamType=live":"")+(a.autoplay?"&autoPlay=true":"")+(a.loop?"&loop=true":"")+(a.poster?"&poster="+a.poster:"")+(a.muted?"&muted=true":"");i.appendChild(l("flashvars",o));i.appendChild(l("allowFullScreen","true"));i.appendChild(l("wmode","direct"));if(a.autoplay){i.appendChild(l("autoPlay","true"))}if(a.loop){i.appendChild(l("loop","true"))}if(a.poster){i.appendChild(l("poster",a.poster))}if(a.muted){i.appendChild(l("muted","true"))}r.setAttribute("src",t.urlappend(t.source.player_url));r.setAttribute("type","application/x-shockwave-flash");r.setAttribute("allowfullscreen","true");r.setAttribute("flashvars",o)}a(t.source.url);this.api={};this.setSize=function(t){i.setAttribute("width",t.width);i.setAttribute("height",t.height);r.setAttribute("width",t.width);r.setAttribute("height",t.height)};this.setSize(t.calcSize());this.onready(function(){if(t.container){t.container.removeAttribute("data-loading")}});this.api.setSource=function(t){a(t)};t.log("Built html");e(i)};

View file

@ -1 +1 @@
mistplayers.html5={name:"HTML5 video player",mimes:["html5/application/vnd.apple.mpegurl","html5/video/mp4","html5/video/ogg","html5/video/webm","html5/audio/mp3","html5/audio/webm","html5/audio/ogg","html5/audio/wav"],priority:MistUtil.object.keys(mistplayers).length+1,isMimeSupported:function(e){return MistUtil.array.indexOf(this.mimes,e)==-1?false:true},isBrowserSupported:function(e,t,i){if(location.protocol!=MistUtil.http.url.split(t.url).protocol){if(location.protocol=="file:"&&MistUtil.http.url.split(t.url).protocol=="http:"){i.log("This page was loaded over file://, the player might not behave as intended.")}else{i.log("HTTP/HTTPS mismatch for this source");return false}}var r=false;var a=e.split("/");a.shift();try{a=a.join("/");function n(e){var t=document.createElement("video");if(t&&t.canPlayType(e)!=""){r=t.canPlayType(e)}return r}if(a=="video/mp4"){function o(e){function t(t){return("0"+e.init.charCodeAt(t).toString(16)).slice(-2)}switch(e.codec){case"AAC":return"mp4a.40.2";case"MP3":return"mp3";case"AC3":return"ec-3";case"H264":return"avc1."+t(1)+t(2)+t(3);case"HEVC":return"hev1."+t(1)+t(6)+t(7)+t(8)+t(9)+t(10)+t(11)+t(12);default:return e.codec.toLowerCase()}}var s={};for(var l in i.info.meta.tracks){if(i.info.meta.tracks[l].type!="meta"){s[o(i.info.meta.tracks[l])]=1}}s=MistUtil.object.keys(s);if(s.length){if(s.length>t.simul_tracks){var p=0;for(var l in s){var u=n(a+';codecs="'+s[l]+'"');if(u){p++}}return p>=t.simul_tracks}a+=';codecs="'+s.join(",")+'"'}}r=n(a)}catch(e){}return r},player:function(){this.onreadylist=[]},mistControls:true};var p=mistplayers.html5.player;p.prototype=new MistPlayer;p.prototype.build=function(e,t){var i=e.source.type.split("/");i.shift();var r=document.createElement("video");r.setAttribute("crossorigin","anonymous");var a=document.createElement("source");a.setAttribute("src",e.source.url);r.source=a;r.appendChild(a);a.type=i.join("/");var n=["autoplay","loop","poster"];for(var o in n){var s=n[o];if(e.options[s]){r.setAttribute(s,e.options[s]===true?"":e.options[s])}}if(e.options.controls=="stock"){r.setAttribute("controls","")}if(e.info.type=="live"){r.loop=false}if("Proxy"in window&&"Reflect"in window){var l={get:{},set:{}};e.player.api=new Proxy(r,{get:function(e,t,i){if(t in l.get){return l.get[t].apply(e,arguments)}var r=e[t];if(typeof r==="function"){return function(){return r.apply(e,arguments)}}return r},set:function(e,t,i){if(t in l.set){return l.set[t].call(e,i)}return e[t]=i}});if(e.source.type=="html5/audio/mp3"){l.set.currentTime=function(){e.log("Seek attempted, but MistServer does not currently support seeking in MP3.");return false}}if(e.info.type=="live"){l.get.duration=function(){var t=0;if(this.buffered.length){t=this.buffered.end(this.buffered.length-1)}var i=((new Date).getTime()-e.player.api.lastProgress.getTime())*.001;return t+i-e.player.api.liveOffset};l.set.currentTime=function(t){var i=t-e.player.api.duration;e.player.api.liveOffset=i;e.log("Seeking to "+MistUtil.format.time(t)+" ("+Math.round(i*-10)/10+"s from live)");e.player.api.setSource(MistUtil.http.url.addParam(e.source.url,{startunix:i}))};MistUtil.event.addListener(r,"progress",function(){e.player.api.lastProgress=new Date});e.player.api.lastProgress=new Date;e.player.api.liveOffset=0;MistUtil.event.addListener(r,"pause",function(){e.player.api.pausedAt=new Date});l.get.play=function(){return function(){if(e.player.api.paused&&e.player.api.pausedAt&&new Date-e.player.api.pausedAt>5e3){r.load();e.log("Reloading source..")}return r.play.apply(r,arguments)}};if(e.source.type=="html5/video/mp4"){l.get.currentTime=function(){return this.currentTime-e.player.api.liveOffset+e.info.lastms*.001}}}else{if(!isFinite(r.duration)){var p=0;for(var o in e.info.meta.tracks){p=Math.max(p,e.info.meta.tracks[o].lastms)}l.get.duration=function(){if(isFinite(this.duration)){return this.duration}return p*.001}}}}else{e.player.api=r}e.player.api.setSource=function(e){if(e!=this.source.src){this.source.src=e;this.load()}};e.player.api.setSubtitle=function(e){var t=r.getElementsByTagName("track");for(var i=t.length-1;i>=0;i--){r.removeChild(t[i])}if(e){var a=document.createElement("track");r.appendChild(a);a.kind="subtitles";a.label=e.label;a.srclang=e.lang;a.src=e.src;a.setAttribute("default","")}};e.player.setSize=function(e){this.api.style.width=e.width+"px";this.api.style.height=e.height+"px"};t(r)};
mistplayers.html5={name:"HTML5 video player",mimes:["html5/application/vnd.apple.mpegurl","html5/video/mp4","html5/video/ogg","html5/video/webm","html5/audio/mp3","html5/audio/webm","html5/audio/ogg","html5/audio/wav"],priority:MistUtil.object.keys(mistplayers).length+1,isMimeSupported:function(t){return MistUtil.array.indexOf(this.mimes,t)==-1?false:true},isBrowserSupported:function(t,e,i){if(location.protocol!=MistUtil.http.url.split(e.url).protocol){if(location.protocol=="file:"&&MistUtil.http.url.split(e.url).protocol=="http:"){i.log("This page was loaded over file://, the player might not behave as intended.")}else{i.log("HTTP/HTTPS mismatch for this source");return false}}var r=false;var a=t.split("/");a.shift();try{a=a.join("/");function n(t){var e=document.createElement("video");if(e&&e.canPlayType(t)!=""){r=e.canPlayType(t)}return r}if(a=="video/mp4"){function o(t){function e(e){return("0"+t.init.charCodeAt(e).toString(16)).slice(-2)}switch(t.codec){case"AAC":return"mp4a.40.2";case"MP3":return"mp3";case"AC3":return"ec-3";case"H264":return"avc1."+e(1)+e(2)+e(3);case"HEVC":return"hev1."+e(1)+e(6)+e(7)+e(8)+e(9)+e(10)+e(11)+e(12);default:return t.codec.toLowerCase()}}var s={};for(var l in i.info.meta.tracks){if(i.info.meta.tracks[l].type!="meta"){s[o(i.info.meta.tracks[l])]=1}}s=MistUtil.object.keys(s);if(s.length){if(s.length>e.simul_tracks){var p=0;for(var l in s){var u=n(a+';codecs="'+s[l]+'"');if(u){p++}}return p>=e.simul_tracks}a+=';codecs="'+s.join(",")+'"'}}r=n(a)}catch(t){}return r},player:function(){this.onreadylist=[]},mistControls:true};var p=mistplayers.html5.player;p.prototype=new MistPlayer;p.prototype.build=function(t,e){var i=t.source.type.split("/");i.shift();var r=document.createElement("video");r.setAttribute("crossorigin","anonymous");var a=document.createElement("source");a.setAttribute("src",t.source.url);r.source=a;r.appendChild(a);a.type=i.join("/");var n=["autoplay","loop","poster"];for(var o in n){var s=n[o];if(t.options[s]){r.setAttribute(s,t.options[s]===true?"":t.options[s])}}if(t.options.muted){r.muted=true}if(t.options.controls=="stock"){r.setAttribute("controls","")}if(t.info.type=="live"){r.loop=false}if("Proxy"in window&&"Reflect"in window){var l={get:{},set:{}};t.player.api=new Proxy(r,{get:function(t,e,i){if(e in l.get){return l.get[e].apply(t,arguments)}var r=t[e];if(typeof r==="function"){return function(){return r.apply(t,arguments)}}return r},set:function(t,e,i){if(e in l.set){return l.set[e].call(t,i)}return t[e]=i}});if(t.source.type=="html5/audio/mp3"){l.set.currentTime=function(){t.log("Seek attempted, but MistServer does not currently support seeking in MP3.");return false}}if(t.info.type=="live"){l.get.duration=function(){var e=0;if(this.buffered.length){e=this.buffered.end(this.buffered.length-1)}var i=((new Date).getTime()-t.player.api.lastProgress.getTime())*.001;return e+i-t.player.api.liveOffset};l.set.currentTime=function(e){var i=e-t.player.api.duration;if(i>0){i=0}t.player.api.liveOffset=i;t.log("Seeking to "+MistUtil.format.time(e)+" ("+Math.round(i*-10)/10+"s from live)");var r={startunix:i};if(i==0){r={}}t.player.api.setSource(MistUtil.http.url.addParam(t.source.url,r))};MistUtil.event.addListener(r,"progress",function(){t.player.api.lastProgress=new Date});t.player.api.lastProgress=new Date;t.player.api.liveOffset=0;MistUtil.event.addListener(r,"pause",function(){t.player.api.pausedAt=new Date});l.get.play=function(){return function(){if(t.player.api.paused&&t.player.api.pausedAt&&new Date-t.player.api.pausedAt>5e3){r.load();t.log("Reloading source..")}return r.play.apply(r,arguments)}};if(t.source.type=="html5/video/mp4"){l.get.currentTime=function(){return this.currentTime-t.player.api.liveOffset+t.info.lastms*.001}}}else{if(!isFinite(r.duration)){var p=0;for(var o in t.info.meta.tracks){p=Math.max(p,t.info.meta.tracks[o].lastms)}l.get.duration=function(){if(isFinite(this.duration)){return this.duration}return p*.001}}}}else{t.player.api=r}t.player.api.setSource=function(t){if(t!=this.source.src){this.source.src=t;this.load()}};t.player.api.setSubtitle=function(t){var e=r.getElementsByTagName("track");for(var i=e.length-1;i>=0;i--){r.removeChild(e[i])}if(t){var a=document.createElement("track");r.appendChild(a);a.kind="subtitles";a.label=t.label;a.srclang=t.lang;a.src=t.src;a.setAttribute("default","")}};t.player.setSize=function(t){this.api.style.width=t.width+"px";this.api.style.height=t.height+"px"};e(r)};

View file

@ -1 +1 @@
mistplayers.videojs={name:"VideoJS player",mimes:["html5/application/vnd.apple.mpegurl"],priority:MistUtil.object.keys(mistplayers).length+1,isMimeSupported:function(e){return this.mimes.indexOf(e)==-1?false:true},isBrowserSupported:function(e,t,i){if(location.protocol!=MistUtil.http.url.split(t.url).protocol){i.log("HTTP/HTTPS mismatch for this source");return false}if(location.protocol=="file:"&&e=="html5/application/vnd.apple"){i.log("This source ("+e+") won't load if the page is run via file://");return false}return"MediaSource"in window},player:function(){},scriptsrc:function(e){return e+"/videojs.js"}};var p=mistplayers.videojs.player;p.prototype=new MistPlayer;p.prototype.build=function(e,t){var i=this;function r(){if(e.destroyed){return}e.log("Building VideoJS player..");var r=document.createElement("video");if(e.source.type!="html5/video/ogg"){r.crossOrigin="anonymous"}var o=e.source.type.split("/");o.shift();var n=document.createElement("source");n.setAttribute("src",e.source.url);i.source=n;r.appendChild(n);n.type=o.join("/");e.log("Adding "+n.type+" source @ "+e.source.url);if(n.type=="application/vnd.apple.mpegurl"){n.type="application/x-mpegURL"}MistUtil.class.add(r,"video-js");var s={};if(e.options.autoplay){s.autoplay=true}if(e.options.loop&&e.info.type!="live"){s.loop=true;r.loop=true}if(e.options.poster){s.poster=e.options.poster}if(e.options.controls=="stock"){r.setAttribute("controls","");if(!document.getElementById("videojs-css")){var l=document.createElement("link");l.rel="stylesheet";l.href=e.options.host+"/skins/videojs.css";l.id="videojs-css";document.head.appendChild(l)}}i.onready(function(){i.videojs=videojs(r,s,function(){e.log("Videojs initialized")});i.api.unload=function(){videojs(r).dispose()}});e.log("Built html");if("Proxy"in window&&"Reflect"in window){var a={get:{},set:{}};e.player.api=new Proxy(r,{get:function(e,t,i){if(t in a.get){return a.get[t].apply(e,arguments)}var r=e[t];if(typeof r==="function"){return function(){return r.apply(e,arguments)}}return r},set:function(e,t,i){if(t in a.set){return a.set[t].call(e,i)}return e[t]=i}});if(e.info.type=="live"){function p(e){var t=0;if(e.buffered.length){t=e.buffered.end(e.buffered.length-1)}return t}var u=90;a.get.duration=function(){return(e.info.lastms+(new Date).getTime()-e.info.updated.getTime())*.001};e.player.api.lastProgress=new Date;e.player.api.liveOffset=0;MistUtil.event.addListener(r,"progress",function(){e.player.api.lastProgress=new Date});a.set.currentTime=function(t){var i=e.player.api.currentTime-t;var r=t-e.player.api.duration;e.log("Seeking to "+MistUtil.format.time(t)+" ("+Math.round(r*-10)/10+"s from live)");e.video.currentTime-=i};a.get.currentTime=function(){return this.currentTime+e.info.lastms*.001-e.player.api.liveOffset-u}}}else{i.api=r}e.player.setSize=function(t){if("videojs"in e.player){e.player.videojs.dimensions(t.width,t.height);r.parentNode.style.width=t.width+"px";r.parentNode.style.height=t.height+"px"}this.api.style.width=t.width+"px";this.api.style.height=t.height+"px"};e.player.api.setSource=function(t){if(!e.player.videojs){return}if(e.player.videojs.src()!=t){e.player.videojs.src({type:e.player.videojs.currentSource().type,src:t})}};e.player.api.setSubtitle=function(e){var t=r.getElementsByTagName("track");for(var i=t.length-1;i>=0;i--){r.removeChild(t[i])}if(e){var o=document.createElement("track");r.appendChild(o);o.kind="subtitles";o.label=e.label;o.srclang=e.lang;o.src=e.src;o.setAttribute("default","")}};t(r)}if("videojs"in window){r()}else{var o=MistUtil.scripts.insert(e.urlappend(mistplayers.videojs.scriptsrc(e.options.host)),{onerror:function(t){var i="Failed to load videojs.js";if(t.message){i+=": "+t.message}e.showError(i)},onload:r},e)}};
mistplayers.videojs={name:"VideoJS player",mimes:["html5/application/vnd.apple.mpegurl"],priority:MistUtil.object.keys(mistplayers).length+1,isMimeSupported:function(e){return this.mimes.indexOf(e)==-1?false:true},isBrowserSupported:function(e,t,i){if(location.protocol!=MistUtil.http.url.split(t.url).protocol){i.log("HTTP/HTTPS mismatch for this source");return false}if(location.protocol=="file:"&&e=="html5/application/vnd.apple"){i.log("This source ("+e+") won't load if the page is run via file://");return false}return"MediaSource"in window},player:function(){},scriptsrc:function(e){return e+"/videojs.js"}};var p=mistplayers.videojs.player;p.prototype=new MistPlayer;p.prototype.build=function(e,t){var i=this;function r(){if(e.destroyed){return}e.log("Building VideoJS player..");var r=document.createElement("video");if(e.source.type!="html5/video/ogg"){r.crossOrigin="anonymous"}var o=e.source.type.split("/");o.shift();var n=document.createElement("source");n.setAttribute("src",e.source.url);i.source=n;r.appendChild(n);n.type=o.join("/");e.log("Adding "+n.type+" source @ "+e.source.url);if(n.type=="application/vnd.apple.mpegurl"){n.type="application/x-mpegURL"}MistUtil.class.add(r,"video-js");var s={};if(e.options.autoplay){s.autoplay=true}if(e.options.loop&&e.info.type!="live"){s.loop=true;r.loop=true}if(e.options.muted){s.muted=true;r.muted=true}if(e.options.poster){s.poster=e.options.poster}if(e.options.controls=="stock"){r.setAttribute("controls","");if(!document.getElementById("videojs-css")){var l=document.createElement("link");l.rel="stylesheet";l.href=e.options.host+"/skins/videojs.css";l.id="videojs-css";document.head.appendChild(l)}}i.onready(function(){i.videojs=videojs(r,s,function(){e.log("Videojs initialized")});i.api.unload=function(){videojs(r).dispose()}});e.log("Built html");if("Proxy"in window&&"Reflect"in window){var a={get:{},set:{}};e.player.api=new Proxy(r,{get:function(e,t,i){if(t in a.get){return a.get[t].apply(e,arguments)}var r=e[t];if(typeof r==="function"){return function(){return r.apply(e,arguments)}}return r},set:function(e,t,i){if(t in a.set){return a.set[t].call(e,i)}return e[t]=i}});if(e.info.type=="live"){function p(e){var t=0;if(e.buffered.length){t=e.buffered.end(e.buffered.length-1)}return t}var u=90;a.get.duration=function(){return(e.info.lastms+(new Date).getTime()-e.info.updated.getTime())*.001};e.player.api.lastProgress=new Date;e.player.api.liveOffset=0;MistUtil.event.addListener(r,"progress",function(){e.player.api.lastProgress=new Date});a.set.currentTime=function(t){var i=e.player.api.currentTime-t;var r=t-e.player.api.duration;e.log("Seeking to "+MistUtil.format.time(t)+" ("+Math.round(r*-10)/10+"s from live)");e.video.currentTime-=i};a.get.currentTime=function(){return this.currentTime+e.info.lastms*.001-e.player.api.liveOffset-u}}}else{i.api=r}e.player.setSize=function(t){if("videojs"in e.player){e.player.videojs.dimensions(t.width,t.height);r.parentNode.style.width=t.width+"px";r.parentNode.style.height=t.height+"px"}this.api.style.width=t.width+"px";this.api.style.height=t.height+"px"};e.player.api.setSource=function(t){if(!e.player.videojs){return}if(e.player.videojs.src()!=t){e.player.videojs.src({type:e.player.videojs.currentSource().type,src:t})}};e.player.api.setSubtitle=function(e){var t=r.getElementsByTagName("track");for(var i=t.length-1;i>=0;i--){r.removeChild(t[i])}if(e){var o=document.createElement("track");r.appendChild(o);o.kind="subtitles";o.label=e.label;o.srclang=e.lang;o.src=e.src;o.setAttribute("default","")}};t(r)}if("videojs"in window){r()}else{var o=MistUtil.scripts.insert(e.urlappend(mistplayers.videojs.scriptsrc(e.options.host)),{onerror:function(t){var i="Failed to load videojs.js";if(t.message){i+=": "+t.message}e.showError(i)},onload:r},e)}};

File diff suppressed because one or more lines are too long

View file

@ -1,10 +1,20 @@
#!/bin/bash
CHANGES="$(git diff --name-only --cached | grep embed/)";
readarray -t CHANGES <<<"$CHANGES";
elementIn () {
local e match="$1";
shift;
for e; do [[ "$e" == "$match" ]] && return 0; done;
return 1;
}
echo "Minimizing player code..";
echo " Minimizing JS..";
if [ "min/player.js" -ot "util.js" ] || [ "min/player.js" -ot "skins.js" ] || [ "min/player.js" -ot "controls.js" ] || [ "min/player.js" -ot "player.js" ]; then
if elementIn "embed/util.js" "${CHANGES[@]}" || elementIn "embed/skins.js" "${CHANGES[@]}" || elementIn "embed/controls.js" "${CHANGES[@]}" || elementIn "embed/player.js" "${CHANGES[@]}" ; then
echo " Minimizing 'util.js skins.js controls.js player.js' into 'min/player.js'..";
terser -mc -o min/player.js -- util.js skins.js controls.js player.js
fi
@ -12,23 +22,23 @@ echo " Done.";
echo " Minimizing wrappers.."
if [ "min/wrappers/dashjs.js" -ot "wrappers/dashjs.js" ]; then
if elementIn "embed/wrappers/dashjs.js" "${CHANGES[@]}"; then
echo " Minimizing dashjs";
terser -mn -o min/wrappers/dashjs.js -- wrappers/dashjs.js
fi
if [ "min/wrappers/flash_strobe.js" -ot "wrappers/flash_strobe.js" ]; then
if elementIn "embed/wrappers/flash_strobe.js" "${CHANGES[@]}"; then
echo " Minimizing flash_strobe";
terser -mn -o min/wrappers/flash_strobe.js -- wrappers/flash_strobe.js
fi
if [ "min/wrappers/html5.js" -ot "wrappers/html5.js" ]; then
if elementIn "embed/wrappers/html5.js" "${CHANGES[@]}"; then
echo " Minimizing html5";
terser -mn -o min/wrappers/html5.js -- wrappers/html5.js
fi
if [ "min/wrappers/videojs.js" -ot "wrappers/videojs.js" ]; then
if elementIn "embed/wrappers/videojs.js" "${CHANGES[@]}"; then
echo " Minimizing videojs";
terser -mn -o min/wrappers/videojs.js -- wrappers/videojs.js
fi
if [ "min/wrappers/webrtc.js" -ot "wrappers/webrtc.js" ]; then
if elementIn "embed/wrappers/webrtc.js" "${CHANGES[@]}"; then
echo " Minimizing webrtc";
terser -mn -o min/wrappers/webrtc.js -- wrappers/webrtc.js
fi
@ -36,11 +46,11 @@ echo " Done.";
echo " Minimizing CSS..";
if [ "min/skins/default.css" -ot "skins/default.css" ] || [ "min/skins/default.css" -ot "skins/general.css" ]; then
if elementIn "embed/skins/default.css" "${CHANGES[@]}" || elementIn "embed/skins/general.css" "${CHANGES[@]}"; then
echo " Minimizing default";
cleancss --format keep-breaks -o min/skins/default.css skins/general.css skins/default.css
fi
if [ "min/skins/dev.css" -ot "skins/default.css" ] || [ "min/skins/dev.css" -ot "skins/general.css" ] || [ "min/skins/dev.css" -ot "skins/dev.css" ]; then
if elementIn "embed/skins/default.css" "${CHANGES[@]}" || elementIn "embed/skins/general.css" "${CHANGES[@]}" || elementIn "embed/skins/dev.css" "${CHANGES[@]}"; then
echo " Minimizing dev";
cleancss --format keep-breaks -o min/skins/dev.css skins/general.css skins/default.css skins/dev.css
fi

View file

@ -15,7 +15,8 @@ function MistVideo(streamName,options) {
autoplay: true, //start playing when loaded
controls: true, //show controls (MistControls when available)
loop: false, //don't loop when the stream has finished
poster: null, //don't show an image before the stream has started
poster: false, //don't show an image before the stream has started
muted: false, //don't start muted
callback: false, //don't call a function when the player has finished building
streaminfo: false, //don't use this streaminfo but collect it from the mistserverhost
startCombo: false, //start looking for a player/source match at the start
@ -99,7 +100,7 @@ function MistVideo(streamName,options) {
new MistSkin(this);
this.checkPlayer = function(options,quiet) {
this.checkCombo = function(options,quiet) {
if (!options) {
options = {};
}
@ -244,7 +245,7 @@ function MistVideo(streamName,options) {
this.choosePlayer = function() {
MistVideo.log("Checking available players..");
var result = this.checkPlayer();
var result = this.checkCombo();
if (!result) { return false; }
var player = mistplayers[result.player];
@ -257,7 +258,7 @@ function MistVideo(streamName,options) {
source.url = MistVideo.urlappend(source.url);
MistVideo.source = source;
MistUtil.event.send("playerChosen","Player/source combination selected",MistVideo.options.target);
MistUtil.event.send("comboChosen","Player/source combination selected",MistVideo.options.target);
return true;
}
@ -605,7 +606,7 @@ function MistVideo(streamName,options) {
if ("setSize" in MistVideo.player) {
MistVideo.player.videocontainer = MistVideo.video.parentNode;
MistVideo.video.currentTarget = MistVideo.options.target;
if (!MistUtil.class.has(MistVideo.options.target,"secondaryVideo")) {
if (!MistUtil.class.has(MistVideo.options.target,"mistvideo-secondaryVideo")) {
//this is the main MistVideo
MistVideo.player.resizeAll = function(){
function findVideo(startAt,matchTarget) {
@ -622,14 +623,18 @@ function MistVideo(streamName,options) {
}
//find the video that is in the main container, and resize that one
findVideo(MistVideo,MistVideo.options.target).p.resize();
var main = findVideo(MistVideo,MistVideo.options.target);
if (!main) { throw "Main video not found"; }
main.p.resize();
//then, resize the secondaries
if ("secondary" in MistVideo) {
function tryResize(mv){
if (mv.MistVideo) {
if ("player" in mv.MistVideo) {
findVideo(MistVideo,mv.MistVideo.options.target).p.resize();
var sec = findVideo(MistVideo,mv.MistVideo.options.target);
if (!sec) { throw "Secondary video not found"; }
sec.p.resize();
}
}
else {
@ -647,13 +652,14 @@ function MistVideo(streamName,options) {
}
MistVideo.player.resize = function(options){
if (!MistVideo.container.hasAttribute("data-fullscreen")) {
var container = MistVideo.video.currentTarget.querySelector(".mistvideo");
if (!container.hasAttribute("data-fullscreen")) {
//if ((!document.fullscreenElement) || (document.fullscreenElement.parentElement != MistVideo.video.currentTarget)) {
//first, base the size on the video dimensions
size = MistVideo.calcSize(options);
this.setSize(size);
MistVideo.container.style.width = size.width+"px";
MistVideo.container.style.height = size.height+"px";
container.style.width = size.width+"px";
container.style.height = size.height+"px";
if ((MistVideo.options.fillSpace) && (!options || !options.reiterating)) {
//if this container is set to fill the available space
@ -686,13 +692,6 @@ function MistVideo(streamName,options) {
return true;
}
else {
function findVideo(parent) {
for (var i = 0; i < parent.children.length; i++) {
if (MistUtil.class.has(parent.children[i],"video")) {
return parent.children[i];
}
}
}
//this is the video that is in the main container, and resize this one to the screen dimensions
this.setSize({
@ -704,7 +703,7 @@ function MistVideo(streamName,options) {
};
//if this is the main video
if (!MistUtil.class.has(MistVideo.options.target,"secondaryVideo")) {
if (!MistUtil.class.has(MistVideo.options.target,"mistvideo-secondaryVideo")) {
MistUtil.event.addListener(window,"resize",function(){
if (MistVideo.destroyed) { return; }
MistVideo.player.resizeAll();
@ -738,7 +737,7 @@ function MistVideo(streamName,options) {
MistVideo.log("Skipping trackselection of "+i+" track "+usetracks[i]+" because it does not exist");
delete usetracks[i];
}
if (!MistUtil.object.keys(usetracks).length) { return; }
//if (!MistUtil.object.keys(usetracks).length) { return; } //don't do this; allow switching back to auto
//create source url
var newurl;
@ -771,11 +770,13 @@ function MistVideo(streamName,options) {
this.setSourceParams(newurl,usetracks);
//restore video position
var f = function(){
this.currentTime = time;
this.removeEventListener("loadedmetadata",f);
};
MistUtil.event.addListener(MistVideo.video,"loadedmetadata",f);
if (MistVideo.info.type != "live") {
var f = function(){
this.currentTime = time;
this.removeEventListener("loadedmetadata",f);
};
MistUtil.event.addListener(MistVideo.video,"loadedmetadata",f);
}
}
@ -1091,9 +1092,9 @@ function MistVideo(streamName,options) {
source: this.source.index,
player: this.playerName
};
if (!this.checkPlayer({startCombo:startCombo},true)) {
if (!this.checkCombo({startCombo:startCombo},true)) {
//the nextCombo won't yield a result
if (this.checkPlayer({startCombo: false},true)) {
if (this.checkCombo({startCombo: false},true)) {
//..but resetting the startcombo would
startCombo = false;
}
@ -1107,7 +1108,7 @@ function MistVideo(streamName,options) {
opts.startCombo = startCombo;
MistVideo = mistPlay(this.stream,opts);
if ((time) && (isFinite(time))) {
if ((time) && (isFinite(time) && (this.info.type != "live"))) {
//after load, try to restore the video position
var f = function(){
if (("player" in MistVideo) && ("api" in MistVideo.player)) { MistVideo.player.api.currentTime = time; }

View file

@ -205,15 +205,16 @@ MistSkins["default"] = {
mode: "pos",
transition: {
hide: "left: 10px; bottom: -40px;",
show: "bottom: 10px;"
show: "bottom: 10px;",
viewport: "left: 0; right: 0; top: 0; bottom: 0"
},
button: {
type: "container",
children: [{type: "video"}]
children: [{type: "videocontainer"}]
},
window: {
type: "switchVideo",
classes: ["mistvideo-controls","mistvideo-padding","mistvideo-background"],
classes: ["mistvideo-controls","mistvideo-padding","mistvideo-background","mistvideo-pointer"],
containers: switchThese
}
};
@ -448,7 +449,8 @@ MistSkins["default"] = {
MistVideo.secondary = [];
}
var options = MistUtil.object.extend(o.options,MistVideo.options,true);
var options = MistUtil.object.extend({},MistVideo.options);
options = MistUtil.object.extend(options,o.options);
MistVideo.secondary.push(options);
var pointer = {
@ -457,7 +459,14 @@ MistSkins["default"] = {
};
options.target = document.createElement("div");
options.callback = function(mv){
delete options.container;
var mvo = {};
options.MistVideoObject = mvo;
MistUtil.event.addListener(options.target,"initialized",function(){
var mv = mvo.reference;
//options.callback = function(mv){
options.MistVideo = mv; //tell the main video we exist
pointer.secondary = mv;
@ -467,7 +476,7 @@ MistSkins["default"] = {
//as all event listeners are tied to the video element (not the container), events don't bubble up and disturb higher players
//prevent clicks on the control container from bubbling down to underlying elements
var controlContainers = options.target.querySelectorAll(".controls");
var controlContainers = options.target.querySelectorAll(".mistvideo-controls");
for (var i = 0; i < controlContainers.length; i++) {
MistUtil.event.addListener(controlContainers[i],"click",function(e){
e.stopPropagation();
@ -516,7 +525,7 @@ MistSkins["default"] = {
mv.player.api.pausedesync = false;
});
};
});
options.skin = MistUtil.object.extend({},MistVideo.skin,true);
options.skin.structure.main = MistUtil.object.extend({},MistVideo.skin.structure.secondaryVideo(pointer));
@ -582,6 +591,8 @@ MistSkins["default"] = {
},
controls: function(){
if ((this.options.controls) && (this.options.controls != "stock")) {
MistUtil.class.add(this.container,"hasControls");
var container = this.UI.buildStructure(this.skin.structure.controls);
if (MistUtil.isTouchDevice()) {
container.style.zoom = 1.5;
@ -1274,28 +1285,31 @@ MistSkins["default"] = {
function changeToTracks(type,value){
MistVideo.log("User selected "+type+" track with id "+value);
if ("setTrack" in MistVideo.player.api) {
MistVideo.player.api.setTrack(type,value);
return;
}
if (!MistVideo.options.setTracks) { MistVideo.options.setTracks = {}; }
MistVideo.options.setTracks[type] = value;
if ("setTrack" in MistVideo.player.api) {
return MistVideo.player.api.setTrack(type,value);
}
else {
//gather what tracks we should use
var usetracks = {};
for (var i in selections) {
if (i == "subtitle") { continue; } //subtitle tracks are handled seperately
if ((i == "subtitle") || (selections[i].value == "")) { continue; } //subtitle tracks are handled seperately
usetracks[i] = selections[i].value;
}
usetracks[type] = value;
if (value != ""){ usetracks[type] = value; }
//use setTracks
if ("setTracks" in MistVideo.player.api) {
MistVideo.player.api.setTracks(usetracks);
return MistVideo.player.api.setTracks(usetracks);
}
//use setSource
if ("setSource" in MistVideo.player.api) {
MistVideo.player.api.setSource(
return MistVideo.player.api.setSource(
MistUtil.http.url.addParam(MistVideo.source.url,usetracks)
);
}
}
}
//sort the tracks to ["audio","video",..,"subtitle",..etc]
@ -1373,6 +1387,7 @@ MistSkins["default"] = {
if (i == this.trackType) { continue; }
if (!checkboxes[i].checked) {
checkboxes[i].checked = true;
changeToTracks(i,true);
break;
}
}
@ -1405,13 +1420,14 @@ MistSkins["default"] = {
//var determine the display info for the tracks
function orderValues(trackinfoobj) {
var order = {
width: 1,
bps: 2,
trackid: 0,
language: 1,
width: 2,
bps: 3,
fpks: 4,
channels: 5,
rate: 7,
language: 0,
codec: 6
codec: 6,
rate: 7
};
return MistUtil.object.values(trackinfoobj,function(keya,keyb,valuea,valueb){
if (order[keya] > order[keyb]) { return 1; }
@ -1429,6 +1445,13 @@ MistSkins["default"] = {
select.trackType = type;
cell.appendChild(select);
if (type != "subtitle") {
var option = document.createElement("option");
select.appendChild(option);
option.value = "";
option.appendChild(document.createTextNode("Automatic"));
}
//display properties that are the same for all tracks
var same = orderValues(t[MistUtil.object.keys(t)[0]].same);
if (same.length) {
@ -1440,7 +1463,9 @@ MistSkins["default"] = {
//add options to the select
var options = MistUtil.object.keys(t,true); //sort them
var options = MistUtil.object.keys(t,function(a,b){
return Number(a) - Number(b);
}); //sort them
for (var i in options) {
var track = t[options[i]];
var option = document.createElement("option");
@ -1495,11 +1520,14 @@ MistSkins["default"] = {
checkboxes[this.trackType].checked = true;
}
changeToTracks(this.trackType,this.value);
if (!changeToTracks(this.trackType,this.value)) {
//trackchange failed, reset select to old value
}
});
//set to the track that plays by default
/*
if (MistVideo.info.type == "live") {
//for live, the default track is the highest index
select.value = MistUtil.object.keys(t).pop();
@ -1508,6 +1536,7 @@ MistSkins["default"] = {
//for vod, the default track is the lowest index
select.value = MistUtil.object.keys(t).shift();
}
*/
MistUtil.event.addListener(MistVideo.video,"playerUpdate_trackChanged",function(e){
@ -1736,8 +1765,8 @@ MistSkins["default"] = {
this.showError = function(message,options){
if (!options) {
options = {
softReload: true,
reload: true,//(MistVideo.options.reloadDelay ? MistVideo.options.reloadDelay : 10),
softReload: !!((MistVideo.video) && (MistVideo.video.load)),
reload: true,
nextCombo: !!MistVideo.info,
polling: false,
passive: false
@ -2456,7 +2485,7 @@ function MistSkin(MistVideo) {
if ((typeof skinOptions == "string") && (skinOptions in MistSkins)) { skinOptions = MistUtil.object.extend({},MistSkins[skinOptions],true); }
var skinParent;
if (("inherit" in skinOptions) && (skinOptions.inherit)) {
if (("inherit" in skinOptions) && (skinOptions.inherit) && (skinOptions.inherit in MistSkins)) {
skinParent = this.applySkinOptions(skinOptions.inherit);
}
else {
@ -2545,6 +2574,7 @@ function MistSkin(MistVideo) {
}
this.applySkinOptions("skin" in MistVideo.options ? MistVideo.options.skin : "default");
//load css
var styles = [];
var toload = 0;

View file

@ -88,8 +88,13 @@ svg.icon.timeout {
}
.mistvideo-secondaryVideo {
z-index: 1;
position: absolute;
right: 0;
top: 0;
width: 50%;
height: 50%;
max-width: fit-content;
max-height: fit-content;
}
.mistvideo-polling {
display: inline-block;

View file

@ -18,6 +18,7 @@
}
.mistvideo-video {
overflow: hidden;
outline: none;
}
svg.icon.loading {
z-index: -1; /* don't use display: none because of transition for [data-loading=stalled] */
@ -222,3 +223,6 @@ svg.icon.spin, svg.icon .spin {
animation: spin 1.5s infinite linear;
transform-origin: 50% 50%;
}
.vjs-text-track-display {
pointer-events: none;
}

View file

@ -213,10 +213,8 @@ var MistUtil = {
if (sorting) {
if (typeof sorting != "function") {
sorting = function(keya,keyb){
if (keya > keyb) { return 1; }
if (keya < keyb) { return -1; }
return 0;
sorting = function(a,b){
return a.localeCompare(b);
};
}
@ -764,6 +762,22 @@ var MistUtil = {
var d = MistUtil.object.values(different);
output[type][i].displayName = (d.length ? d.join(", ") : MistUtil.object.values(output[type][i].describe).join(" "));
}
//check if some tracks have the same display name
var names = {};
for (var i in output[type]) {
if (output[type][i].displayName in names) {
//we have double names, add the track id
var n = 1;
for (var i in output[type]) {
output[type][i].different.trackid = n+")";
output[type][i].displayName = "Track "+n+" ("+output[type][i].displayName+")";
n++;
}
break;
}
names[output[type][i].displayName] = 1;
}
}
return output;

View file

@ -103,6 +103,9 @@ p.prototype.build = function (MistVideo,callback) {
if (MistVideo.options.poster) {
ele.setAttribute("poster",MistVideo.options.poster);
}
if (MistVideo.options.muted) {
ele.muted = true;
}
if (MistVideo.options.controls == "stock") {
ele.setAttribute("controls","");
}
@ -141,20 +144,34 @@ p.prototype.build = function (MistVideo,callback) {
}
//figure out what the track number is
//whyyyy did it have to be reverse order
var n = me.dash.getBitrateInfoListFor("video").length - 1;
//for dash: 0 lowest bitrate, going up
//get the relevant tracks
var mistTracks = [];
for (var i in MistVideo.info.meta.tracks) {
var t = MistVideo.info.meta.tracks[i];
if (t.type == type) {
if (t.trackid == id) { break; }
n--;
mistTracks.push(t);
}
}
//sort by bitrate
MistUtil.array.multiSort(mistTracks,["bps"]);
var n = false;
for (var i in mistTracks) {
if (mistTracks[i].trackid == id) {
n = i;
break;
}
}
if (n === false) {
return false; //track not found
}
me.dash.setAutoSwitchQualityFor(type,false); //turn off ABR rules //TODO do we want this by default?
me.dash.setFastSwitchEnabled(true); //show the new track asap
me.dash.setQualityFor(type,n);
//dash does change the track, but is appended to the buffer, so it seems to take a while..
return true; //track found and change requested
}
//react to automatic trackswitching
@ -162,19 +179,19 @@ p.prototype.build = function (MistVideo,callback) {
//the newQuality-th track of type mediaType is being selected
//figure out the track id
//whyyyy did it have to be reverse order
var n = me.dash.getBitrateInfoListFor("video").length - 1;
var id;
//for dash: 0 lowest bitrate, going up
//get the relevant tracks
var mistTracks = [];
for (var i in MistVideo.info.meta.tracks) {
var t = MistVideo.info.meta.tracks[i];
if (t.type == e.mediaType) {
if (e.newQuality == n) {
id = t.trackid;
break;
}
n--;
mistTracks.push(t);
}
}
//sort by bitrate
MistUtil.array.multiSort(mistTracks,["bps"]);
//get mist's id for the track
var id = mistTracks[e.newQuality].trackid;
//create an event to pass this to the skin
MistUtil.event.send("playerUpdate_trackChanged",{
@ -183,6 +200,37 @@ p.prototype.build = function (MistVideo,callback) {
},MistVideo.video);
});
var subsloaded = false;
me.dash.on("allTextTracksAdded",function(){
subsloaded = true;
});
MistVideo.player.api.setSubtitle = function(trackmeta) {
if (!subsloaded) {
var f = function(){
MistVideo.player.api.setSubtitle(trackmeta);
me.dash.off("allTextTracksAdded",f);
};
me.dash.on("allTextTracksAdded",f);
return;
}
if (!trackmeta) {
me.dash.enableText(false);
return;
}
var dashsubs = me.dash.getTracksFor("text");
for (var i in dashsubs) {
if (dashsubs[i].id == trackmeta.trackid) {
me.dash.setTextTrack(i);
if (!me.dash.isTextEnabled()) { me.dash.enableText(); }
return true;
}
}
return false; //failed to find subtitle
};
//dashjs keeps on spamming the stalled icon >_>
MistUtil.event.addListener(ele,"progress",function(e){

View file

@ -56,13 +56,22 @@ p.prototype.build = function (MistVideo,callback) {
MistUtil.empty(ele);
ele.appendChild(createParam("movie",MistVideo.urlappend(options.host+MistVideo.source.player_url)));
var flashvars = "src="+encodeURIComponent(source)+"&controlBarMode="+(options.controls ? "floating" : "none")+"&initialBufferTime=0.5&expandedBufferTime=5&minContinuousPlaybackTime=3"+(options.live ? "&streamType=live" : "")+(options.autoplay ? "&autoPlay=true" : "" );
var flashvars = "src="+encodeURIComponent(source)+"&controlBarMode="+(options.controls ? "floating" : "none")+"&initialBufferTime=0.5&expandedBufferTime=5&minContinuousPlaybackTime=3"+(options.live ? "&streamType=live" : "")+(options.autoplay ? "&autoPlay=true" : "" )+(options.loop ? "&loop=true" : "" )+(options.poster ? "&poster="+options.poster : "" )+(options.muted ? "&muted=true" : "" );
ele.appendChild(createParam("flashvars",flashvars));
ele.appendChild(createParam("allowFullScreen","true"));
ele.appendChild(createParam("wmode","direct"));
if (options.autoplay) {
ele.appendChild(createParam("autoPlay","true"));
}
if (options.loop) {
ele.appendChild(createParam("loop","true"));
}
if (options.poster) {
ele.appendChild(createParam("poster",options.poster));
}
if (options.muted) {
ele.appendChild(createParam("muted","true"));
}
e.setAttribute("src",MistVideo.urlappend(MistVideo.source.player_url));
e.setAttribute("type","application/x-shockwave-flash");

View file

@ -114,6 +114,9 @@ p.prototype.build = function (MistVideo,callback) {
video.setAttribute(attr,(MistVideo.options[attr] === true ? "" : MistVideo.options[attr]));
}
}
if (MistVideo.options.muted) {
video.muted = true; //don't use attribute because of Chrome bug: https://stackoverflow.com/questions/14111917/html5-video-muted-but-stilly-playing?rq=1
}
if (MistVideo.options.controls == "stock") {
video.setAttribute("controls","");
}
@ -168,11 +171,19 @@ p.prototype.build = function (MistVideo,callback) {
};
overrides.set.currentTime = function(value){
var offset = value - MistVideo.player.api.duration;
if (offset > 0) {offset = 0;} //don't allow positive numbers, as Mist will interpret them as unix timestamps
MistVideo.player.api.liveOffset = offset;
MistVideo.log("Seeking to "+MistUtil.format.time(value)+" ("+Math.round(offset*-10)/10+"s from live)");
MistVideo.player.api.setSource(MistUtil.http.url.addParam(MistVideo.source.url,{startunix:offset}));
var params = {startunix:offset};
if (offset == 0) {
params = {};
}
MistVideo.player.api.setSource(MistUtil.http.url.addParam(MistVideo.source.url,params));
}
MistUtil.event.addListener(video,"progress",function(){
MistVideo.player.api.lastProgress = new Date();

View file

@ -59,6 +59,10 @@ p.prototype.build = function (MistVideo,callback) {
vjsopts.loop = true;
ele.loop = true;
}
if (MistVideo.options.muted) {
vjsopts.muted = true;
ele.muted = true;
}
if (MistVideo.options.poster) { vjsopts.poster = MistVideo.options.poster; }
if (MistVideo.options.controls == "stock") {
ele.setAttribute("controls","");
@ -71,7 +75,6 @@ p.prototype.build = function (MistVideo,callback) {
}
}
me.onready(function(){
me.videojs = videojs(ele,vjsopts,function(){
MistVideo.log("Videojs initialized");

View file

@ -49,6 +49,9 @@ p.prototype.build = function (MistVideo,callback) {
video.setAttribute(attr,(MistVideo.options[attr] === true ? "" : MistVideo.options[attr]));
}
}
if (MistVideo.options.muted) {
video.muted = true; //don't use attribute because of Chrome bug
}
if (MistVideo.info.type == "live") {
video.loop = false;
}