From 3cf00701213a8b6924869dbac3418a0fc41595a4 Mon Sep 17 00:00:00 2001 From: Cat Date: Mon, 31 May 2021 10:33:26 +0200 Subject: [PATCH] Embed: mews: remove pause when tabbing out as doing so no longer seems to crash the browser --- embed/min/wrappers/mews.js | 2 +- embed/wrappers/mews.js | 45 +++++++++++++------------------------- 2 files changed, 16 insertions(+), 31 deletions(-) diff --git a/embed/min/wrappers/mews.js b/embed/min/wrappers/mews.js index b37bcaef..612849ae 100644 --- a/embed/min/wrappers/mews.js +++ b/embed/min/wrappers/mews.js @@ -1 +1 @@ -mistplayers.mews={name:"MSE websocket player",mimes:["ws/video/mp4","ws/video/webm"],priority:MistUtil.object.keys(mistplayers).length+1,isMimeSupported:function(e){return this.mimes.indexOf(e)==-1?false:true},isBrowserSupported:function(e,t,i){if(!("WebSocket"in window)||!("MediaSource"in window)){return false}if(location.protocol.replace(/^http/,"ws")!=MistUtil.http.url.split(t.url.replace(/^http/,"ws")).protocol){i.log("HTTP/HTTPS mismatch for this source");return false}if(navigator.platform.toUpperCase().indexOf("MAC")>=0){return false}function n(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"mp4a.40.34";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 r in i.info.meta.tracks){if(i.info.meta.tracks[r].type!="meta"){s[n(i.info.meta.tracks[r])]=i.info.meta.tracks[r].codec}}var a=e.split("/")[2];function o(e){return MediaSource.isTypeSupported("video/"+a+';codecs="'+e+'"')}t.supportedCodecs=[];for(var r in s){var u=o(r);if(u){t.supportedCodecs.push(s[r])}}if(!i.options.forceType&&!i.options.forcePlayer){if(t.supportedCodecs.length0},player:function(){}};var p=mistplayers.mews.player;p.prototype=new MistPlayer;p.prototype.build=function(e,t){var i=document.createElement("video");i.setAttribute("playsinline","");var n=["autoplay","loop","poster"];for(var s in n){var r=n[s];if(e.options[r]){i.setAttribute(r,e.options[r]===true?"":e.options[r])}}if(e.options.muted){i.muted=true}if(e.info.type=="live"){i.loop=false}if(e.options.controls=="stock"){i.setAttribute("controls","")}i.setAttribute("crossorigin","anonymous");this.setSize=function(e){i.style.width=e.width+"px";i.style.height=e.height+"px"};var a=this;function o(){if(a.ws.readyState==a.ws.OPEN&&a.ms.readyState=="open"&&a.sb){t(i);if(e.options.autoplay){a.api.play()}return true}}this.msinit=function(){return new Promise(function(e,t){a.ms=new MediaSource;i.src=URL.createObjectURL(a.ms);a.ms.onsourceopen=function(){e()};a.ms.onsourceclose=function(e){console.error("ms close",e);u({type:"stop"})};a.ms.onsourceended=function(e){console.error("ms ended",e);function t(e,t,n){var s,r;s=new Blob([e],{type:n});r=window.URL.createObjectURL(s);i(r,t);setTimeout(function(){return window.URL.revokeObjectURL(r)},1e3)}function i(e,t){var i;i=document.createElement("a");i.href=e;i.download=t;document.body.appendChild(i);i.style="display: none";i.click();i.remove()}if(a.debugging){var n=0;for(var s=0;s=500){s=0;a.sb._clean(10)}else{s++}var t=n.slice();n=[];for(var r in t){if(!a.sb){if(a.debugging){console.warn("I was doing on_updateend but the sb was reset")}break}if(a.sb.updating){n.concat(t.slice(r));if(a.debugging){console.warn("I was doing on_updateend but was interrupted")}break}t[r](r0&&!a.sb.updating&&!i.error){a.sb._append(this.queue.shift())}});a.sb.error=function(e){console.error("sb error",e)};a.sb.abort=function(e){console.error("sb abort",e)};a.sb._doNext=function(e){n.push(e)};a.sb._do=function(e){if(this.updating||this._busy){this._doNext(e)}else{e()}};a.sb._append=function(e){if(!e){return}if(!e.buffer){return}if(a.debugging){a.sb.appending=new Uint8Array(e)}if(a.sb._busy){if(a.debugging)console.warn("I wanted to append data, but now I won't because the thingy was still busy. Putting it back in the queue.");a.sb.queue.unshift(e);return}a.sb._busy=true;a.sb.appendBuffer(e)};if(a.msgqueue){if(a.msgqueue[0]){var r=false;if(a.msgqueue[0].length){for(var o in a.msgqueue[0]){if(a.sb.updating||a.sb.queue.length||a.sb._busy){a.sb.queue.push(a.msgqueue[0][o])}else{a.sb._append(a.msgqueue[0][o])}}}else{r=true}a.msgqueue.shift();if(a.msgqueue.length==0){a.msgqueue=false}e.log("The newly initialized source buffer was filled with data from a seperate message queue."+(a.msgqueue?" "+a.msgqueue.length+" more message queue(s) remain.":""));if(r){e.log("The seperate message queue was empty; manually triggering any onupdateend functions");a.sb.dispatchEvent(new Event("updateend"))}}}a.sb._clean=function(e){if(!e)e=180;if(i.currentTime>e){a.sb._do(function(){a.sb.remove(0,Math.max(.1,i.currentTime-e))})}};if(a.onsbinit.length){a.onsbinit.shift()()}};this.wsconnect=function(){return new Promise(function(t,n){this.ws=new WebSocket(e.source.url);this.ws.binaryType="arraybuffer";this.ws.onopen=function(){t()};this.ws.onerror=function(t){e.showError("MP4 over WS: websocket error")};this.ws.onclose=function(t){e.log("MP4 over WS: websocket closed")};this.ws.listeners={};this.ws.addListener=function(e,t){if(!(e in this.listeners)){this.listeners[e]=[]}this.listeners[e].push(t)};this.ws.removeListener=function(e,t){if(!(e in this.listeners)){return}var i=this.listeners[e].indexOf(t);if(i<0){return}this.listeners[e].splice(i,1);return true};a.msgqueue=false;var s=1;var r=[];this.ws.onmessage=function(t){if(!t.data){throw"Received invalid data"}if(typeof t.data=="string"){var n=JSON.parse(t.data);if(a.debugging&&n.type!="on_time"){console.log("ws message",n)}switch(n.type){case"on_stop":{var r;r=MistUtil.event.addListener(i,"waiting",function(e){MistUtil.event.send("ended",null,i);MistUtil.event.removeListener(r)});break}case"on_time":{var o=n.data.current-i.currentTime*1e3;var f=a.ws.serverDelay.get();var d=Math.max(500+f,f*2);if(e.info.type!="live"){d+=2e3}if(a.debugging)console.log("on_time received",n.data.current/1e3,"currtime",i.currentTime,s+"x","buffer",Math.round(o),"/",Math.round(d),e.info.type=="live"?"latency:"+Math.round(n.data.end-i.currentTime*1e3)+"ms":"","listeners",a.ws.listeners&&a.ws.listeners.on_time?a.ws.listeners.on_time:0,"msgqueue",a.msgqueue?a.msgqueue.length:0,n.data);if(!a.sb){e.log("Received on_time, but the source buffer is being cleared right now. Ignoring.");break}if(a.sb._duration!=n.data.end*.001){a.sb._duration=n.data.end*.001;MistUtil.event.send("durationchange",null,e.video)}e.info.meta.buffer_window=n.data.end-n.data.begin;a.sb.paused=false;if(e.info.type=="live"){if(s==1){if(n.data.play_rate_curr=="auto"){if(i.currentTime>0){if(o-d>d){s=1.1+Math.min(1,(o-d)/d)*.15;i.playbackRate*=s;e.log("Our buffer is big, so increase the playback speed to catch up.")}else if(o1){if(od){i.playbackRate/=s;s=1;e.log("Our buffer is big enough, so return to real time playback.")}}}else{if(s==1){if(n.data.play_rate_curr=="auto"){if(od){e.log("Our buffer is big, so request a slower download rate.");s=.5;u({type:"set_speed",play_rate:s})}}}else if(s>1){if(o>d){u({type:"set_speed",play_rate:"auto"});s=1;e.log("The buffer is big enough, so ask for realtime download rate.")}}else{if(o0){if(a.sb){a.sb._do(function(){a.sb.remove(0,n.data.current*.001)})}}e.log("Player switched tracks, keeping source buffer as codecs are the same as before.")}else{if(a.debugging){console.warn("Different codecs!");console.warn("video time",i.currentTime,"waiting until",n.data.current*.001)}a.last_codecs=n.data.codecs;if(a.msgqueue){a.msgqueue.push([])}else{a.msgqueue=[[]]}var l=function(){if(a&&a.sb){a.sb._do(function(t){if(!a.sb.updating){if(!isNaN(a.ms.duration))a.sb.remove(0,Infinity);a.sb.queue=[];a.ms.removeSourceBuffer(a.sb);a.sb=null;var s=(n.data.current*.001).toFixed(3);i.src="";a.ms.onsourceclose=null;a.ms.onsourceended=null;if(a.debugging&&t&&t.length){console.warn("There are do_on_updateend functions queued, which I *should* re-apply after clearing the sb.")}a.msinit().then(function(){a.sbinit(n.data.codecs);a.sb.do_on_updateend=t;var r=MistUtil.event.addListener(i,"loadedmetadata",function(){e.log("Buffer cleared, setting playback position to "+MistUtil.format.time(s,{ms:true}));var t=function(){i.currentTime=s;if(i.currentTimei.currentTime){var t=i.buffered.start(0);i.currentTime=t;if(i.currentTime!=t){e()}}}else{e()}})};e()}};t();MistUtil.event.removeListener(r)})})}else{l()}})}else{if(a.debugging){console.warn("sb not available to do clear")}a.onsbinit.push(l)}};if(!n.data.codecs||!n.data.codecs.length){e.showError("Track switch does not contain any codecs, aborting.");e.options.setTracks=false;l();break}if(a.debugging){console.warn("reached switching point",n.data.current*.001,MistUtil.format.time(n.data.current*.001))}l()}}}if(n.type in this.listeners){for(var p=this.listeners[n.type].length-1;p>=0;p--){this.listeners[n.type][p](n)}}return}var b=new Uint8Array(t.data);if(b){if(a.sb&&!a.msgqueue){if(a.sb.updating||a.sb.queue.length||a.sb._busy){a.sb.queue.push(b)}else{a.sb._append(b)}}else{if(!a.msgqueue){a.msgqueue=[[]]}a.msgqueue[a.msgqueue.length-1].push(b)}}else{e.log("Expecting data from websocket, but received none?!")}};this.ws.serverDelay={delays:[],log:function(e){var t=false;switch(e){case"seek":case"set_speed":{t=e;break}case"request_codec_data":{t="codec_data";break}default:{return}}if(t){var i=(new Date).getTime();function n(){a.ws.serverDelay.add((new Date).getTime()-i);a.ws.removeListener(t,n)}a.ws.addListener(t,n)}},add:function(e){this.delays.unshift(e);if(this.delays.length>5){this.delays.splice(5)}},get:function(){if(this.delays.length){let e=0;let t=0;for(null;t=3){break}e+=this.delays[t]}return e/t}return 500}}}.bind(this))};this.wsconnect().then(function(){var t=function(e){a.sbinit(e.data.codecs);o();a.ws.removeListener("codec_data",t)};this.ws.addListener("codec_data",t);u({type:"request_codec_data",supported_codecs:e.source.supportedCodecs})}.bind(this));function u(e){if(!a.ws){throw"No websocket to send to"}if(a.ws.readyState>=a.ws.CLOSING){a.wsconnect().then(function(){u(e)});return}if(a.debugging){console.log("ws send",e)}a.ws.serverDelay.log(e.type);a.ws.send(JSON.stringify(e))}a.findBuffer=function(e){var t=false;for(var n=0;n=e){t=n;break}}return t};this.api={play:function(t){return new Promise(function(n,s){var r=function(o){if(!a.sb){e.log("Attempting to play, but the source buffer is being cleared. Waiting for next on_time.");return}if(e.info.type=="live"){if(t||i.currentTime==0){var u=function(){if(i.buffered.length){var t=a.findBuffer(o.data.current*.001);if(t!==false){if(i.buffered.start(t)>i.currentTime||i.buffered.end(t)i.currentTime){a.sb.paused=false;i.play().then(n).catch(s);a.ws.removeListener("on_time",r)}};a.ws.addListener("on_time",r);var o={type:"play"};if(t){o.seek_time="live"}u(o)})},pause:function(){i.pause();u({type:"hold"});if(a.sb){a.sb.paused=true}},setTracks:function(e){e.type="tracks";e=MistUtil.object.extend({type:"tracks",audio:null,video:null,seek_time:Math.max(0,i.currentTime*1e3-(500+a.ws.serverDelay.get()))},e);u(e)},unload:function(){a.api.pause();a.sb._do(function(){a.sb.remove(0,Infinity);try{a.ms.endOfStream()}catch(e){}});a.ws.close();delete window.mistMewsOnVisibilityChange;document.removeEventListener("visibilitychange",l)}};Object.defineProperty(this.api,"currentTime",{get:function(){return i.currentTime},set:function(t){MistUtil.event.send("seeking",t,i);u({type:"seek",seek_time:Math.max(0,t*1e3-(250+a.ws.serverDelay.get()))});var n=function(e){a.ws.removeListener("seek",n);var s=function(e){a.ws.removeListener("on_time",s);t=(e.data.current*.001).toFixed(3);var n=function(){i.currentTime=t;if(i.currentTime!=t){if(a.debugging)console.log("Failed to set video.currentTime, wanted:",t,"got:",i.currentTime);a.sb._doNext(n)}};n()};a.ws.addListener("on_time",s)};a.ws.addListener("seek",n);i.currentTime=t;e.log("Seeking to "+MistUtil.format.time(t,{ms:true})+" ("+t+")")}});Object.defineProperty(this.api,"duration",{get:function(){return a.sb?a.sb._duration:1}});Object.defineProperty(this.api,"playbackRate",{get:function(){return i.playbackRate},set:function(e){var t=function(e){i.playbackRate=e.data.play_rate};a.ws.addListener("set_speed",t);u({type:"set_speed",play_rate:e==1?"auto":e})}});function f(e){Object.defineProperty(a.api,e,{get:function(){return i[e]},set:function(t){return i[e]=t}})}var d=["volume","buffered","muted","loop","paused",,"error","textTracks","webkitDroppedFrameCount","webkitDecodedFrameCount"];for(var s in d){f(d[s])}MistUtil.event.addListener(i,"ended",function(){if(a.api.loop){a.api.currentTime=0;a.sb._do(function(){a.sb.remove(0,Infinity)})}});var c=false;function l(){if(document.hidden){if(!a.sb.paused){a.api.pause();c=true;if(e.info.type=="live"){c="live"}e.log("Pausing the player as the tab is inactive.")}}else if(c){a.api.play(c=="live");c=false;e.log("Restarting the player as the tab is now active again.")}}if(!window.mistMewsOnVisibilityChange){window.mistMewsOnVisibilityChange=true;document.addEventListener("visibilitychange",l)}var p=false;MistUtil.event.addListener(i,"seeking",function(){p=true;var e=MistUtil.event.addListener(i,"seeked",function(){p=false;MistUtil.event.removeListener(e)})});MistUtil.event.addListener(i,"waiting",function(){if(p){return}var t=a.findBuffer(i.currentTime);if(t!==false){if(t+1=i.buffered.start(n)&&i.currentTime<=i.buffered.end(n)){t=true}e.push([i.buffered.start(n),i.buffered.end(n)])}console.log("waiting","currentTime",i.currentTime,"buffers",e,t?"contained":"outside of buffer","readystate",i.readyState,"networkstate",i.networkState);if(i.readyState>=2&&i.networkState>=2){console.error("Why am I waiting?!")}})}}; \ No newline at end of file +mistplayers.mews={name:"MSE websocket player",mimes:["ws/video/mp4","ws/video/webm"],priority:MistUtil.object.keys(mistplayers).length+1,isMimeSupported:function(e){return this.mimes.indexOf(e)==-1?false:true},isBrowserSupported:function(e,t,n){if(!("WebSocket"in window)||!("MediaSource"in window)){return false}if(location.protocol.replace(/^http/,"ws")!=MistUtil.http.url.split(t.url.replace(/^http/,"ws")).protocol){n.log("HTTP/HTTPS mismatch for this source");return false}if(navigator.platform.toUpperCase().indexOf("MAC")>=0){return false}function i(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"mp4a.40.34";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 r in n.info.meta.tracks){if(n.info.meta.tracks[r].type!="meta"){s[i(n.info.meta.tracks[r])]=n.info.meta.tracks[r].codec}}var a=e.split("/")[2];function o(e){return MediaSource.isTypeSupported("video/"+a+';codecs="'+e+'"')}t.supportedCodecs=[];for(var r in s){var u=o(r);if(u){t.supportedCodecs.push(s[r])}}if(!n.options.forceType&&!n.options.forcePlayer){if(t.supportedCodecs.length0},player:function(){}};var p=mistplayers.mews.player;p.prototype=new MistPlayer;p.prototype.build=function(e,t){var n=document.createElement("video");n.setAttribute("playsinline","");var i=["autoplay","loop","poster"];for(var s in i){var r=i[s];if(e.options[r]){n.setAttribute(r,e.options[r]===true?"":e.options[r])}}if(e.options.muted){n.muted=true}if(e.info.type=="live"){n.loop=false}if(e.options.controls=="stock"){n.setAttribute("controls","")}n.setAttribute("crossorigin","anonymous");this.setSize=function(e){n.style.width=e.width+"px";n.style.height=e.height+"px"};var a=this;function o(){if(a.ws.readyState==a.ws.OPEN&&a.ms.readyState=="open"&&a.sb){t(n);if(e.options.autoplay){a.api.play()}return true}}this.msinit=function(){return new Promise(function(e,t){a.ms=new MediaSource;n.src=URL.createObjectURL(a.ms);a.ms.onsourceopen=function(){e()};a.ms.onsourceclose=function(e){console.error("ms close",e);u({type:"stop"})};a.ms.onsourceended=function(e){console.error("ms ended",e);function t(e,t,i){var s,r;s=new Blob([e],{type:i});r=window.URL.createObjectURL(s);n(r,t);setTimeout(function(){return window.URL.revokeObjectURL(r)},1e3)}function n(e,t){var n;n=document.createElement("a");n.href=e;n.download=t;document.body.appendChild(n);n.style="display: none";n.click();n.remove()}if(a.debugging){var i=0;for(var s=0;s=500){s=0;a.sb._clean(10)}else{s++}var t=i.slice();i=[];for(var r in t){if(!a.sb){if(a.debugging){console.warn("I was doing on_updateend but the sb was reset")}break}if(a.sb.updating){i.concat(t.slice(r));if(a.debugging){console.warn("I was doing on_updateend but was interrupted")}break}t[r](r0&&!a.sb.updating&&!n.error){a.sb._append(this.queue.shift())}});a.sb.error=function(e){console.error("sb error",e)};a.sb.abort=function(e){console.error("sb abort",e)};a.sb._doNext=function(e){i.push(e)};a.sb._do=function(e){if(this.updating||this._busy){this._doNext(e)}else{e()}};a.sb._append=function(e){if(!e){return}if(!e.buffer){return}if(a.debugging){a.sb.appending=new Uint8Array(e)}if(a.sb._busy){if(a.debugging)console.warn("I wanted to append data, but now I won't because the thingy was still busy. Putting it back in the queue.");a.sb.queue.unshift(e);return}a.sb._busy=true;a.sb.appendBuffer(e)};if(a.msgqueue){if(a.msgqueue[0]){var r=false;if(a.msgqueue[0].length){for(var o in a.msgqueue[0]){if(a.sb.updating||a.sb.queue.length||a.sb._busy){a.sb.queue.push(a.msgqueue[0][o])}else{a.sb._append(a.msgqueue[0][o])}}}else{r=true}a.msgqueue.shift();if(a.msgqueue.length==0){a.msgqueue=false}e.log("The newly initialized source buffer was filled with data from a seperate message queue."+(a.msgqueue?" "+a.msgqueue.length+" more message queue(s) remain.":""));if(r){e.log("The seperate message queue was empty; manually triggering any onupdateend functions");a.sb.dispatchEvent(new Event("updateend"))}}}a.sb._clean=function(e){if(!e)e=180;if(n.currentTime>e){a.sb._do(function(){a.sb.remove(0,Math.max(.1,n.currentTime-e))})}};if(a.onsbinit.length){a.onsbinit.shift()()}};this.wsconnect=function(){return new Promise(function(t,i){this.ws=new WebSocket(e.source.url);this.ws.binaryType="arraybuffer";this.ws.onopen=function(){t()};this.ws.onerror=function(t){e.showError("MP4 over WS: websocket error")};this.ws.onclose=function(t){e.log("MP4 over WS: websocket closed")};this.ws.listeners={};this.ws.addListener=function(e,t){if(!(e in this.listeners)){this.listeners[e]=[]}this.listeners[e].push(t)};this.ws.removeListener=function(e,t){if(!(e in this.listeners)){return}var n=this.listeners[e].indexOf(t);if(n<0){return}this.listeners[e].splice(n,1);return true};a.msgqueue=false;var s=1;var r=[];this.ws.onmessage=function(t){if(!t.data){throw"Received invalid data"}if(typeof t.data=="string"){var i=JSON.parse(t.data);if(a.debugging&&i.type!="on_time"){console.log("ws message",i)}switch(i.type){case"on_stop":{var r;r=MistUtil.event.addListener(n,"waiting",function(e){MistUtil.event.send("ended",null,n);MistUtil.event.removeListener(r)});break}case"on_time":{var o=i.data.current-n.currentTime*1e3;var d=a.ws.serverDelay.get();var f=Math.max(500+d,d*2);if(e.info.type!="live"){f+=2e3}if(a.debugging)console.log("on_time received",i.data.current/1e3,"currtime",n.currentTime,s+"x","buffer",Math.round(o),"/",Math.round(f),e.info.type=="live"?"latency:"+Math.round(i.data.end-n.currentTime*1e3)+"ms":"","listeners",a.ws.listeners&&a.ws.listeners.on_time?a.ws.listeners.on_time:0,"msgqueue",a.msgqueue?a.msgqueue.length:0,i.data);if(!a.sb){e.log("Received on_time, but the source buffer is being cleared right now. Ignoring.");break}if(a.sb._duration!=i.data.end*.001){a.sb._duration=i.data.end*.001;MistUtil.event.send("durationchange",null,e.video)}e.info.meta.buffer_window=i.data.end-i.data.begin;a.sb.paused=false;if(e.info.type=="live"){if(s==1){if(i.data.play_rate_curr=="auto"){if(n.currentTime>0){if(o-f>f){s=1.1+Math.min(1,(o-f)/f)*.15;n.playbackRate*=s;e.log("Our buffer is big, so increase the playback speed to catch up.")}else if(o1){if(of){n.playbackRate/=s;s=1;e.log("Our buffer is big enough, so return to real time playback.")}}}else{if(s==1){if(i.data.play_rate_curr=="auto"){if(of){e.log("Our buffer is big, so request a slower download rate.");s=.5;u({type:"set_speed",play_rate:s})}}}else if(s>1){if(o>f){u({type:"set_speed",play_rate:"auto"});s=1;e.log("The buffer is big enough, so ask for realtime download rate.")}}else{if(o0){if(a.sb){a.sb._do(function(){a.sb.remove(0,i.data.current*.001)})}}e.log("Player switched tracks, keeping source buffer as codecs are the same as before.")}else{if(a.debugging){console.warn("Different codecs!");console.warn("video time",n.currentTime,"waiting until",i.data.current*.001)}a.last_codecs=i.data.codecs;if(a.msgqueue){a.msgqueue.push([])}else{a.msgqueue=[[]]}var l=function(){if(a&&a.sb){a.sb._do(function(t){if(!a.sb.updating){if(!isNaN(a.ms.duration))a.sb.remove(0,Infinity);a.sb.queue=[];a.ms.removeSourceBuffer(a.sb);a.sb=null;var s=(i.data.current*.001).toFixed(3);n.src="";a.ms.onsourceclose=null;a.ms.onsourceended=null;if(a.debugging&&t&&t.length){console.warn("There are do_on_updateend functions queued, which I *should* re-apply after clearing the sb.")}a.msinit().then(function(){a.sbinit(i.data.codecs);a.sb.do_on_updateend=t;var r=MistUtil.event.addListener(n,"loadedmetadata",function(){e.log("Buffer cleared, setting playback position to "+MistUtil.format.time(s,{ms:true}));var t=function(){n.currentTime=s;if(n.currentTimen.currentTime){var t=n.buffered.start(0);n.currentTime=t;if(n.currentTime!=t){e()}}}else{e()}})};e()}};t();MistUtil.event.removeListener(r)})})}else{l()}})}else{if(a.debugging){console.warn("sb not available to do clear")}a.onsbinit.push(l)}};if(!i.data.codecs||!i.data.codecs.length){e.showError("Track switch does not contain any codecs, aborting.");e.options.setTracks=false;l();break}if(a.debugging){console.warn("reached switching point",i.data.current*.001,MistUtil.format.time(i.data.current*.001))}l()}}}if(i.type in this.listeners){for(var p=this.listeners[i.type].length-1;p>=0;p--){this.listeners[i.type][p](i)}}return}var b=new Uint8Array(t.data);if(b){if(a.sb&&!a.msgqueue){if(a.sb.updating||a.sb.queue.length||a.sb._busy){a.sb.queue.push(b)}else{a.sb._append(b)}}else{if(!a.msgqueue){a.msgqueue=[[]]}a.msgqueue[a.msgqueue.length-1].push(b)}}else{e.log("Expecting data from websocket, but received none?!")}};this.ws.serverDelay={delays:[],log:function(e){var t=false;switch(e){case"seek":case"set_speed":{t=e;break}case"request_codec_data":{t="codec_data";break}default:{return}}if(t){var n=(new Date).getTime();function i(){a.ws.serverDelay.add((new Date).getTime()-n);a.ws.removeListener(t,i)}a.ws.addListener(t,i)}},add:function(e){this.delays.unshift(e);if(this.delays.length>5){this.delays.splice(5)}},get:function(){if(this.delays.length){let e=0;let t=0;for(null;t=3){break}e+=this.delays[t]}return e/t}return 500}}}.bind(this))};this.wsconnect().then(function(){var t=function(e){a.sbinit(e.data.codecs);o();a.ws.removeListener("codec_data",t)};this.ws.addListener("codec_data",t);u({type:"request_codec_data",supported_codecs:e.source.supportedCodecs})}.bind(this));function u(e){if(!a.ws){throw"No websocket to send to"}if(a.ws.readyState>=a.ws.CLOSING){a.wsconnect().then(function(){u(e)});return}if(a.debugging){console.log("ws send",e)}a.ws.serverDelay.log(e.type);a.ws.send(JSON.stringify(e))}a.findBuffer=function(e){var t=false;for(var i=0;i=e){t=i;break}}return t};this.api={play:function(t){return new Promise(function(i,s){var r=function(o){if(!a.sb){e.log("Attempting to play, but the source buffer is being cleared. Waiting for next on_time.");return}if(e.info.type=="live"){if(t||n.currentTime==0){var u=function(){if(n.buffered.length){var t=a.findBuffer(o.data.current*.001);if(t!==false){if(n.buffered.start(t)>n.currentTime||n.buffered.end(t)n.currentTime){a.sb.paused=false;n.play().then(i).catch(s);a.ws.removeListener("on_time",r)}};a.ws.addListener("on_time",r);var o={type:"play"};if(t){o.seek_time="live"}u(o)})},pause:function(){n.pause();u({type:"hold"});if(a.sb){a.sb.paused=true}},setTracks:function(e){e.type="tracks";e=MistUtil.object.extend({type:"tracks",audio:null,video:null,seek_time:Math.max(0,n.currentTime*1e3-(500+a.ws.serverDelay.get()))},e);u(e)},unload:function(){a.api.pause();a.sb._do(function(){a.sb.remove(0,Infinity);try{a.ms.endOfStream()}catch(e){}});a.ws.close()}};Object.defineProperty(this.api,"currentTime",{get:function(){return n.currentTime},set:function(t){MistUtil.event.send("seeking",t,n);u({type:"seek",seek_time:Math.max(0,t*1e3-(250+a.ws.serverDelay.get()))});var i=function(e){a.ws.removeListener("seek",i);var s=function(e){a.ws.removeListener("on_time",s);t=(e.data.current*.001).toFixed(3);var i=function(){n.currentTime=t;if(n.currentTime!=t){if(a.debugging)console.log("Failed to set video.currentTime, wanted:",t,"got:",n.currentTime);a.sb._doNext(i)}};i()};a.ws.addListener("on_time",s)};a.ws.addListener("seek",i);n.currentTime=t;e.log("Seeking to "+MistUtil.format.time(t,{ms:true})+" ("+t+")")}});Object.defineProperty(this.api,"duration",{get:function(){return a.sb?a.sb._duration:1}});Object.defineProperty(this.api,"playbackRate",{get:function(){return n.playbackRate},set:function(e){var t=function(e){n.playbackRate=e.data.play_rate};a.ws.addListener("set_speed",t);u({type:"set_speed",play_rate:e==1?"auto":e})}});function d(e){Object.defineProperty(a.api,e,{get:function(){return n[e]},set:function(t){return n[e]=t}})}var f=["volume","buffered","muted","loop","paused",,"error","textTracks","webkitDroppedFrameCount","webkitDecodedFrameCount"];for(var s in f){d(f[s])}MistUtil.event.addListener(n,"ended",function(){if(a.api.loop){a.api.currentTime=0;a.sb._do(function(){a.sb.remove(0,Infinity)})}});var c=false;MistUtil.event.addListener(n,"seeking",function(){c=true;var e=MistUtil.event.addListener(n,"seeked",function(){c=false;MistUtil.event.removeListener(e)})});MistUtil.event.addListener(n,"waiting",function(){if(c){return}var t=a.findBuffer(n.currentTime);if(t!==false){if(t+1=n.buffered.start(i)&&n.currentTime<=n.buffered.end(i)){t=true}e.push([n.buffered.start(i),n.buffered.end(i)])}console.log("waiting","currentTime",n.currentTime,"buffers",e,t?"contained":"outside of buffer","readystate",n.readyState,"networkstate",n.networkState);if(n.readyState>=2&&n.networkState>=2){console.error("Why am I waiting?!")}})}}; \ No newline at end of file diff --git a/embed/wrappers/mews.js b/embed/wrappers/mews.js index 190054f2..8d25cb8b 100644 --- a/embed/wrappers/mews.js +++ b/embed/wrappers/mews.js @@ -768,7 +768,7 @@ p.prototype.build = function (MistVideo,callback) { }, pause: function(){ video.pause(); - send({type: "hold",}); + send({type: "hold"}); if (player.sb) { player.sb.paused = true; } }, setTracks: function(obj){ @@ -791,9 +791,7 @@ p.prototype.build = function (MistVideo,callback) { //it's okay if it fails } catch (e) { } }); - player.ws.close(); - delete window.mistMewsOnVisibilityChange; - document.removeEventListener("visibilitychange",onVisibilityChange); + player.ws.close(); } }; @@ -881,32 +879,6 @@ p.prototype.build = function (MistVideo,callback) { }); } }); - //pause if tab is hidden to prevent buildup of frames - var autopaused = false; - //only add this once! - function onVisibilityChange() { - if (document.hidden) { - //check if we are playing (not video.paused! that already returns true) - if (!player.sb.paused) { - player.api.pause(); - autopaused = true; - if (MistVideo.info.type == "live") { - autopaused = "live"; //go to live point - //NB: even if the player wasn't near the live point when it was paused, we've likely exited the buffer while we were paused, so the current position probably won't exist anymore. Just skip to live. - } - MistVideo.log("Pausing the player as the tab is inactive."); - } - } - else if (autopaused) { - player.api.play(autopaused == "live"); - autopaused = false; - MistVideo.log("Restarting the player as the tab is now active again."); - } - } - if (!window.mistMewsOnVisibilityChange) { - window.mistMewsOnVisibilityChange = true; - document.addEventListener("visibilitychange",onVisibilityChange); - } var seeking = false; MistUtil.event.addListener(video,"seeking",function(){ @@ -927,6 +899,19 @@ p.prototype.build = function (MistVideo,callback) { } } }); + MistUtil.event.addListener(video,"pause",function(){ + if (player.sb && !player.sb.paused) { + MistVideo.log("The browser paused the vid - probably because it has no audio and the tab is no longer visible. Pausing download."); + send({type:"hold"}); + player.sb.paused = true; + var p = MistUtil.event.addListener(video,"play",function(){ + if (player.sb && player.sb.paused) { + send({type:"play"}); + } + MistUtil.event.removeListener(p); + }); + } + }); if (player.debugging) { MistUtil.event.addListener(video,"waiting",function(){