Embed: player reporting
This commit is contained in:
parent
d9d72aab99
commit
35a98178f1
7 changed files with 240 additions and 24 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
214
embed/player.js
214
embed/player.js
|
@ -62,6 +62,7 @@ function MistVideo(streamName,options) {
|
|||
return event;
|
||||
};
|
||||
this.log("Initializing..");
|
||||
this.bootMs = new Date().getTime();
|
||||
|
||||
this.timers = {
|
||||
list: {}, //will contain the timeouts, format timeOutIndex: endTime
|
||||
|
@ -402,6 +403,15 @@ function MistVideo(streamName,options) {
|
|||
|
||||
if (MistVideo.choosePlayer()) {
|
||||
|
||||
if (MistVideo.reporting) {
|
||||
MistVideo.reporting.report({
|
||||
player: MistVideo.playerName,
|
||||
sourceType: MistVideo.source.type,
|
||||
sourceUrl: MistVideo.source.url,
|
||||
pageUrl: location.href
|
||||
});
|
||||
}
|
||||
|
||||
//build player
|
||||
MistVideo.player = new mistplayers[MistVideo.playerName].player();
|
||||
|
||||
|
@ -417,6 +427,10 @@ function MistVideo(streamName,options) {
|
|||
MistVideo.container.removeAttribute("data-loading");
|
||||
MistVideo.video = video;
|
||||
|
||||
if (MistVideo.reporting) {
|
||||
MistVideo.reporting.init();
|
||||
}
|
||||
|
||||
if ("api" in MistVideo.player) {
|
||||
|
||||
//add monitoring
|
||||
|
@ -495,6 +509,11 @@ function MistVideo(streamName,options) {
|
|||
score = Math.max(score,list[list.length-1].score);
|
||||
|
||||
this.vars.score = score;
|
||||
|
||||
if (MistVideo.reporting) {
|
||||
MistVideo.reporting.stats.set("playbackScore",Math.round(score*10)/10);
|
||||
}
|
||||
|
||||
return score;
|
||||
},
|
||||
valueToScore: function(a,b){ //calculate the moving average
|
||||
|
@ -568,7 +587,6 @@ function MistVideo(streamName,options) {
|
|||
if (MistVideo.monitor) { MistVideo.monitor.reset(); }
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//remove placeholder and add UI structure
|
||||
|
@ -874,6 +892,7 @@ function MistVideo(streamName,options) {
|
|||
|
||||
MistUtil.event.send("initialized",null,options.target);
|
||||
MistVideo.log("Initialized");
|
||||
|
||||
if (MistVideo.options.callback) { options.callback(MistVideo); }
|
||||
|
||||
});
|
||||
|
@ -881,7 +900,7 @@ function MistVideo(streamName,options) {
|
|||
else if (MistVideo.options.startCombo) {
|
||||
//try again without a startCombo
|
||||
delete MistVideo.options.startCombo;
|
||||
MistVideo.unload();
|
||||
MistVideo.unload("No compatible players found - retrying without startCombo.");
|
||||
MistVideo = mistPlay(MistVideo.stream,MistVideo.options);
|
||||
}
|
||||
else {
|
||||
|
@ -937,6 +956,182 @@ function MistVideo(streamName,options) {
|
|||
};
|
||||
socket.onopen = function(e){
|
||||
this.wasConnected = true;
|
||||
|
||||
//report player status to MistServer
|
||||
MistVideo.reporting = {
|
||||
stats: {
|
||||
set: function(key,value){
|
||||
this.d[key] = value;
|
||||
},
|
||||
add: function(key,add){
|
||||
if (typeof add == "undefined") { add = 1; }
|
||||
this.d[key] += add;
|
||||
},
|
||||
d: {
|
||||
nWaiting: 0,
|
||||
timeWaiting: 0,
|
||||
nStalled: 0,
|
||||
timeStalled: 0,
|
||||
timeUnpaused: 0,
|
||||
nError: 0,
|
||||
nLog: 0,
|
||||
videoHeight: null,
|
||||
videoWidth: null,
|
||||
playerHeight: null,
|
||||
playerWidth: null
|
||||
},
|
||||
last: {
|
||||
firstPlayback: null,
|
||||
nWaiting: 0,
|
||||
timeWaiting: 0,
|
||||
nStalled: 0,
|
||||
timeStalled: 0,
|
||||
timeUnpaused: 0,
|
||||
nError: 0,
|
||||
lastError: null,
|
||||
playbackScore: 1,
|
||||
nLog: 0,
|
||||
autoplay: null,
|
||||
videoHeight: null,
|
||||
videoWidth: 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) {
|
||||
if (newlogs.length) {
|
||||
d.logs = [];
|
||||
for (var i in newlogs) {
|
||||
d.logs.push(newlogs[i].message);
|
||||
}
|
||||
}
|
||||
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(){
|
||||
MistVideo.reporting.stats.set("firstPlayback",new Date().getTime() - MistVideo.bootMs);
|
||||
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;
|
||||
}
|
||||
});
|
||||
|
||||
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;
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//periodically send the gathered stats
|
||||
this.reportStats();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
socket.onclose = function(e){
|
||||
if (this.die) {
|
||||
|
@ -1063,7 +1258,7 @@ function MistVideo(streamName,options) {
|
|||
|
||||
if ("source" in diff) {
|
||||
if ("error" in MistVideo.info) {
|
||||
MistVideo.reload();
|
||||
MistVideo.reload("Reloading, stream info has error");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1111,6 +1306,8 @@ function MistVideo(streamName,options) {
|
|||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
openSocket();
|
||||
}
|
||||
|
@ -1118,7 +1315,7 @@ function MistVideo(streamName,options) {
|
|||
openWithGet();
|
||||
}
|
||||
|
||||
this.unload = function(){
|
||||
this.unload = function(reason){
|
||||
if (this.destroyed) { return; }
|
||||
|
||||
this.log("Unloading..");
|
||||
|
@ -1138,6 +1335,9 @@ function MistVideo(streamName,options) {
|
|||
MistVideo.monitor.destroy();
|
||||
}
|
||||
if (this.socket) {
|
||||
if (this.reporting) {
|
||||
this.reporting.report({unload:reason ? reason : null});
|
||||
}
|
||||
this.socket.destroy();
|
||||
}
|
||||
if ((this.player) && (this.player.api)) {
|
||||
|
@ -1173,10 +1373,10 @@ function MistVideo(streamName,options) {
|
|||
delete this.video;
|
||||
|
||||
};
|
||||
this.reload = function(){
|
||||
this.reload = function(reason){
|
||||
var time = ("player" in this && "api" in this.player ? this.player.api.currentTime : false);
|
||||
|
||||
this.unload();
|
||||
this.unload(reason);
|
||||
MistVideo = mistPlay(this.stream,this.options);
|
||||
|
||||
if ((time) && (this.info.type != "live")) {
|
||||
|
@ -1212,7 +1412,7 @@ function MistVideo(streamName,options) {
|
|||
}
|
||||
}
|
||||
|
||||
this.unload();
|
||||
this.unload("nextCombo");
|
||||
var opts = this.options;
|
||||
opts.startCombo = startCombo;
|
||||
MistVideo = mistPlay(this.stream,opts);
|
||||
|
|
|
@ -357,9 +357,12 @@ MistSkins["default"] = {
|
|||
|
||||
var promise = MistVideo.player.api.play();
|
||||
if (promise) {
|
||||
promise.catch(function(){
|
||||
promise.then(function(){
|
||||
if (MistVideo.reporting) { MistVideo.reporting.stats.d.autoplay = "success"; }
|
||||
}).catch(function(){
|
||||
if (MistVideo.destroyed) { return; }
|
||||
MistVideo.log("Autoplay failed even with muted video. Unmuting and showing play button.");
|
||||
if (MistVideo.reporting) { MistVideo.reporting.stats.d.autoplay = "failed"; }
|
||||
MistVideo.player.api.muted = false;
|
||||
|
||||
//play has failed
|
||||
|
@ -388,6 +391,8 @@ MistSkins["default"] = {
|
|||
|
||||
MistVideo.log("Autoplay worked! Video will be unmuted on mouseover if the page has been interacted with.");
|
||||
|
||||
if (MistVideo.reporting) { MistVideo.reporting.stats.d.autoplay = "muted"; }
|
||||
|
||||
//show large "muted" icon
|
||||
var largeMutedButton = MistVideo.skin.icons.build("muted",100);
|
||||
MistUtil.class.add(largeMutedButton,"mistvideo-pointer");
|
||||
|
@ -432,9 +437,11 @@ MistSkins["default"] = {
|
|||
},function(){});
|
||||
}
|
||||
}
|
||||
else if (MistVideo.reporting) { MistVideo.reporting.stats.d.autoplay = "failed"; }
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (MistVideo.reporting) { MistVideo.reporting.stats.d.autoplay = "success"; }
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1953,7 +1960,7 @@ MistSkins["default"] = {
|
|||
type: "button",
|
||||
label: "Reload player",
|
||||
onclick: function(){
|
||||
MistVideo.reload();
|
||||
MistVideo.reload("Reloading because reload button was clicked.");
|
||||
}
|
||||
};
|
||||
if (!isNaN(options.reload+"")) { obj.delay = options.reload; }
|
||||
|
@ -2470,7 +2477,7 @@ MistSkins.dev = {
|
|||
MistUtil.event.addListener(select,"change",function(){
|
||||
MistVideo.options.forcePlayer = (this.value == "" ? false : this.value);
|
||||
if (MistVideo.options.forcePlayer != MistVideo.playerName) { //only reload if there is a change
|
||||
MistVideo.reload();
|
||||
MistVideo.reload("Reloading to force player.");
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -2512,7 +2519,7 @@ MistSkins.dev = {
|
|||
MistUtil.event.addListener(select,"change",function(){
|
||||
MistVideo.options.forceType = (this.value == "" ? false : this.value);
|
||||
if ((!MistVideo.source) || (MistVideo.options.forceType != MistVideo.source.type)) { //only reload if there is a change
|
||||
MistVideo.reload();
|
||||
MistVideo.reload("Reloading to force new type.");
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -2546,7 +2553,7 @@ MistSkins.dev = {
|
|||
MistUtil.event.addListener(select,"change",function(){
|
||||
MistVideo.options.forceSource = (this.value == "" ? false : this.value);
|
||||
if (MistVideo.options.forceSource != MistVideo.source.index) { //only reload if there is a change
|
||||
MistVideo.reload();
|
||||
MistVideo.reload("Reloading to force new source.");
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -2601,7 +2608,7 @@ MistSkins.dev.structure.submenu.children.unshift({
|
|||
title: "Build MistVideo again",
|
||||
label: "MistVideo.reload();",
|
||||
onclick: function(){
|
||||
this.reload();
|
||||
this.reload("Dev-reload button clicked.");
|
||||
}
|
||||
},{
|
||||
type: "button",
|
||||
|
|
|
@ -467,6 +467,11 @@ p.prototype.build = function (MistVideo,callback) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (MistVideo.reporting && msg.data.tracks) {
|
||||
MistVideo.reporting.stats.d.tracks = msg.data.tracks.join(",");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case "tracks": {
|
||||
|
|
|
@ -157,6 +157,10 @@ p.prototype.build = function (MistVideo,callback) {
|
|||
|
||||
currenttracks = ev.tracks;
|
||||
}
|
||||
|
||||
if (MistVideo.reporting && ev.tracks) {
|
||||
MistVideo.reporting.stats.d.tracks = ev.tracks.join(",");
|
||||
}
|
||||
},
|
||||
on_seek: function(e){
|
||||
var thisPlayer = this;
|
||||
|
|
Loading…
Add table
Reference in a new issue