Embed: improved behavior when websocket disconnects

This commit is contained in:
Cat 2021-06-24 16:42:42 +02:00 committed by Thulinma
parent 51147c3df5
commit 8e8017dfd9
4 changed files with 196 additions and 163 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -908,7 +908,7 @@ function MistVideo(streamName,options) {
//try again without a startCombo //try again without a startCombo
delete MistVideo.options.startCombo; delete MistVideo.options.startCombo;
MistVideo.unload("No compatible players found - retrying without startCombo."); MistVideo.unload("No compatible players found - retrying without startCombo.");
MistVideo = mistPlay(MistVideo.stream,MistVideo.options); mistPlay(MistVideo.stream,MistVideo.options);
} }
else { else {
MistVideo.showError("No compatible player/source combo found.",{reload:true}); MistVideo.showError("No compatible player/source combo found.",{reload:true});
@ -966,178 +966,180 @@ function MistVideo(streamName,options) {
this.wasConnected = true; this.wasConnected = true;
//report player status to MistServer //report player status to MistServer
MistVideo.reporting = { if (!MistVideo.reporting) {
stats: { MistVideo.reporting = {
set: function(key,value){ stats: {
this.d[key] = value; set: function(key,value){
}, this.d[key] = value;
add: function(key,add){ },
if (typeof add == "undefined") { add = 1; } add: function(key,add){
this.d[key] += add; if (typeof add == "undefined") { add = 1; }
}, this.d[key] += add;
d: { },
nWaiting: 0, d: {
timeWaiting: 0, nWaiting: 0,
nStalled: 0, timeWaiting: 0,
timeStalled: 0, nStalled: 0,
timeUnpaused: 0, timeStalled: 0,
nError: 0, timeUnpaused: 0,
nLog: 0, nError: 0,
videoHeight: null, nLog: 0,
videoWidth: null, videoHeight: null,
playerHeight: null, videoWidth: null,
playerWidth: null playerHeight: null,
}, playerWidth: null
last: { },
firstPlayback: null, last: {
nWaiting: 0, firstPlayback: null,
timeWaiting: 0, nWaiting: 0,
nStalled: 0, timeWaiting: 0,
timeStalled: 0, nStalled: 0,
timeUnpaused: 0, timeStalled: 0,
nError: 0, timeUnpaused: 0,
lastError: null, nError: 0,
playbackScore: 1, lastError: null,
nLog: 0, playbackScore: 1,
autoplay: null, nLog: 0,
videoHeight: null, autoplay: null,
videoWidth: null, videoHeight: null,
playerHeight: null, videoWidth: null,
playerWidth: null playerHeight: null,
} playerWidth: null
},
report: function(d){
socket.send(JSON.stringify(d));
},
reportStats: function(){
var d = {};
var report = false;
var newlogs = MistVideo.logs.slice(this.stats.last.nLog);
for (var i in this.stats.d) {
if (this.stats.d[i] != this.stats.last[i]) {
d[i] = this.stats.d[i];
this.stats.last[i] = d[i];
report = true;
} }
} },
if (report) { report: function(d){
if (newlogs.length) { MistVideo.socket.send(JSON.stringify(d));
d.logs = []; },
for (var i in newlogs) { reportStats: function(){
d.logs.push(newlogs[i].message); var d = {};
var report = false;
var newlogs = MistVideo.logs.slice(this.stats.last.nLog);
for (var i in this.stats.d) {
if (this.stats.d[i] != this.stats.last[i]) {
d[i] = this.stats.d[i];
this.stats.last[i] = d[i];
report = true;
} }
} }
this.report(d); if (report) {
} if (newlogs.length) {
MistVideo.timers.start(function(){ d.logs = [];
MistVideo.reporting.reportStats(); for (var i in newlogs) {
},5e3); d.logs.push(newlogs[i].message);
}, }
init: function(){ }
var video = MistVideo.video; this.report(d);
}
MistVideo.timers.start(function(){
MistVideo.reporting.reportStats();
},5e3);
},
init: function(){
var video = MistVideo.video;
var firstPlay = MistUtil.event.addListener(video,"playing",function(){ var firstPlay = MistUtil.event.addListener(video,"playing",function(){
MistVideo.reporting.stats.set("firstPlayback",new Date().getTime() - MistVideo.bootMs); MistVideo.reporting.stats.set("firstPlayback",new Date().getTime() - MistVideo.bootMs);
MistUtil.event.removeListener(firstPlay); MistUtil.event.removeListener(firstPlay);
});
//set listeners for player reporting
MistUtil.event.addListener(video,"waiting",function(){
MistVideo.reporting.stats.add("nWaiting");
});
MistUtil.event.addListener(video,"stalled",function(){
MistVideo.reporting.stats.add("nStalled");
});
MistUtil.event.addListener(MistVideo.options.target,"error",function(e){
MistVideo.reporting.stats.add("nError");
MistVideo.reporting.stats.set("lastError",e.message);
});
if (Object && Object.defineProperty) {
var timeWaiting = 0;
var waitingSince = false;
var timeStalled = 0;
var stalledSince = false;
var timeUnpaused = 0;
var unpausedSince = false;
var d = MistVideo.reporting.stats.d;
Object.defineProperty(d,"timeWaiting",{
get: function(){
return timeWaiting + (waitingSince ? (new Date()).getTime() - waitingSince : 0);
}
});
Object.defineProperty(d,"timeStalled",{
get: function(){
return timeStalled + (stalledSince ? (new Date()).getTime() - stalledSince : 0);
}
});
Object.defineProperty(d,"timeUnpaused",{
get: function(){
return timeUnpaused + (unpausedSince ? (new Date()).getTime() - unpausedSince : 0);
}
});
Object.defineProperty(d,"nLog",{
get: function(){
return MistVideo.logs.length;
}
});
Object.defineProperty(d,"videoHeight",{
get: function(){
return MistVideo.video.videoHeight;
}
});
Object.defineProperty(d,"videoWidth",{
get: function(){
return MistVideo.video.videoWidth;
}
});
Object.defineProperty(d,"playerHeight",{
get: function(){
return MistVideo.video.clientHeight;
}
});
Object.defineProperty(d,"playerWidth",{
get: function(){
return MistVideo.video.clientWidth;
}
}); });
//set listeners for player reporting
MistUtil.event.addListener(video,"waiting",function(){ MistUtil.event.addListener(video,"waiting",function(){
timeWaiting = d.timeWaiting; //in case we get waiting several times in a row MistVideo.reporting.stats.add("nWaiting");
waitingSince = (new Date()).getTime();
}); });
MistUtil.event.addListener(video,"stalled",function(){ MistUtil.event.addListener(video,"stalled",function(){
timeStalled = d.timeStalled; //in case we get stalled several times in a row MistVideo.reporting.stats.add("nStalled");
stalledSince = (new Date()).getTime();
}); });
var events = ["playing","pause"]; MistUtil.event.addListener(MistVideo.options.target,"error",function(e){
for (var i in events) { MistVideo.reporting.stats.add("nError");
MistUtil.event.addListener(video,events[i],function(){ MistVideo.reporting.stats.set("lastError",e.message);
timeWaiting = d.timeWaiting; });
timeStalled = d.timeStalled;
waitingSince = false; if (Object && Object.defineProperty) {
stalledSince = false; var timeWaiting = 0;
var waitingSince = false;
var timeStalled = 0;
var stalledSince = false;
var timeUnpaused = 0;
var unpausedSince = false;
var d = MistVideo.reporting.stats.d;
Object.defineProperty(d,"timeWaiting",{
get: function(){
return timeWaiting + (waitingSince ? (new Date()).getTime() - waitingSince : 0);
}
}); });
Object.defineProperty(d,"timeStalled",{
get: function(){
return timeStalled + (stalledSince ? (new Date()).getTime() - stalledSince : 0);
}
});
Object.defineProperty(d,"timeUnpaused",{
get: function(){
return timeUnpaused + (unpausedSince ? (new Date()).getTime() - unpausedSince : 0);
}
});
Object.defineProperty(d,"nLog",{
get: function(){
return MistVideo.logs.length;
}
});
Object.defineProperty(d,"videoHeight",{
get: function(){
return MistVideo.video.videoHeight;
}
});
Object.defineProperty(d,"videoWidth",{
get: function(){
return MistVideo.video.videoWidth;
}
});
Object.defineProperty(d,"playerHeight",{
get: function(){
return MistVideo.video.clientHeight;
}
});
Object.defineProperty(d,"playerWidth",{
get: function(){
return MistVideo.video.clientWidth;
}
});
MistUtil.event.addListener(video,"waiting",function(){
timeWaiting = d.timeWaiting; //in case we get waiting several times in a row
waitingSince = (new Date()).getTime();
});
MistUtil.event.addListener(video,"stalled",function(){
timeStalled = d.timeStalled; //in case we get stalled several times in a row
stalledSince = (new Date()).getTime();
});
var events = ["playing","pause"];
for (var i in events) {
MistUtil.event.addListener(video,events[i],function(){
timeWaiting = d.timeWaiting;
timeStalled = d.timeStalled;
waitingSince = false;
stalledSince = false;
});
}
MistUtil.event.addListener(video,"playing",function(){
timeUnpaused = d.timeUnpaused; //in case we get playing several times in a row
unpausedSince = (new Date()).getTime();
});
MistUtil.event.addListener(video,"pause",function(){
timeUnpaused = d.timeUnpaused;
unpausedSince = false;
});
} }
MistUtil.event.addListener(video,"playing",function(){
timeUnpaused = d.timeUnpaused; //in case we get playing several times in a row
unpausedSince = (new Date()).getTime();
});
MistUtil.event.addListener(video,"pause",function(){
timeUnpaused = d.timeUnpaused;
unpausedSince = false;
});
//periodically send the gathered stats
this.reportStats();
} }
};
}
//periodically send the gathered stats
this.reportStats();
}
};
}; };
socket.onclose = function(e){ socket.onclose = function(e){
@ -1384,13 +1386,13 @@ function MistVideo(streamName,options) {
var time = ("player" in this && "api" in this.player ? this.player.api.currentTime : false); var time = ("player" in this && "api" in this.player ? this.player.api.currentTime : false);
this.unload(reason); this.unload(reason);
MistVideo = mistPlay(this.stream,this.options); var NewMistVideo = mistPlay(this.stream,this.options);
if ((time) && (this.info.type != "live")) { if ((time) && (this.info.type != "live")) {
//after load, try to restore the video position //after load, try to restore the video position
var f = function(){ var f = function(){
if (MistVideo.player && MistVideo.player.api) { if (NewMistVideo.player && NewMistVideo.player.api) {
MistVideo.player.api.currentTime = time; NewMistVideo.player.api.currentTime = time;
} }
this.removeEventListener("initialized",f); this.removeEventListener("initialized",f);
}; };

View file

@ -333,14 +333,45 @@ p.prototype.build = function (MistVideo,callback) {
this.ws = new WebSocket(MistVideo.source.url); this.ws = new WebSocket(MistVideo.source.url);
this.ws.binaryType = "arraybuffer"; this.ws.binaryType = "arraybuffer";
this.ws.s = this.ws.send;
this.ws.send = function(){
if (this.readyState == 1) {
return this.s.apply(this,arguments);
}
return false;
};
this.ws.onopen = function(){ this.ws.onopen = function(){
this.wasConnected = true;
resolve(); resolve();
}; };
this.ws.onerror = function(e){ this.ws.onerror = function(e){
MistVideo.showError("MP4 over WS: websocket error"); MistVideo.showError("MP4 over WS: websocket error");
} };
this.ws.onclose = function(e){ this.ws.onclose = function(e){
MistVideo.log("MP4 over WS: websocket closed"); MistVideo.log("MP4 over WS: websocket closed");
if (this.wasConnected && (!MistVideo.destroyed)) {
MistVideo.log("MP4 over WS: reopening websocket");
player.wsconnect().then(function(){
if (!player.sb) {
//retrieve codec info
var f = function(msg){
//got codec data, set up source buffer
if (!player.sb) { player.sbinit(msg.data.codecs); }
else { player.api.play(); }
player.ws.removeListener("codec_data",f);
};
player.ws.addListener("codec_data",f);
send({type:"request_codec_data",supported_codecs:MistVideo.source.supportedCodecs});
}
else {
player.api.play();
}
},function(){
Mistvideo.error("Lost connection to the Media Server");
});
}
}; };
this.ws.listeners = {}; //kind of event listener list for websocket messages this.ws.listeners = {}; //kind of event listener list for websocket messages
this.ws.addListener = function(type,f){ this.ws.addListener = function(type,f){