User:Yaron Koren/tmh-engagement.js
Appearance
Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: press Ctrl-F5, Mozilla: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Opera/Konqueror: press F5, Safari: hold down Shift + Alt while clicking Reload, Chrome: hold down Shift while clicking Reload.
| Documentation for this user script can be added at User:Yaron Koren/tmh-engagement. |
// "TimedMediaHandler engagement" script
// Tries to get the amount of time (in seconds) that a user watched/listened to any audio/video file
// handled by the TimedMediaHandler extension. This information is then sent to the API at
// https://commons-play-listener.toolforge.org/, along with the filename and total duration of that
// audio/video (but *no* identifying personal information). All of the information is then aggregated
// together to get a sense of "engagement" for media files, i.e. what percentage is consumed.
// You can have this script get called for your Wikipedia, etc. viewing by adding the following line
// to the /common.js subpage of your user page:
// mw.loader.load( '//commons.wikimedia.org/w/index.php?title=User:Yaron_Koren/tmh-engagement.js&action=raw&ctype=text/javascript' );
// Created by Yaron Koren for the Wiki Project Med Foundation.
( function( mw, $ ) {
var allActivePlayers = {};
onPlay = function(event) {
let player = event.target.player;
if ( player.timeoutID ) {
// Cancel the 30-minute "pause" timer.
clearTimeout(player.timeoutID);
}
if ( player.fileName == undefined ) {
// Initialize data.
player.fileName = player.tagAttributes['data-mwtitle'];
allActivePlayers[player.fileName] = player;
}
};
/**
* Despite its name, this function is called when the video/audio is either paused or ends naturally.
*/
onPause = function(event) {
let player = event.target.player;
if ( player.playAmountSubmitted ) {
return;
}
let totalSeconds = player.duration();
let playedSeconds = getSecondsPlayed( player );
if ( playedSeconds >= totalSeconds ) {
submitPlayerData( player, totalSeconds, playedSeconds );
player.playAmountSubmitted = true;
delete allActivePlayers[player.fileName];
return;
}
// If the pause goes on for 30 minutes without a restart, assume the user has finished
// watching/listening, and send the metrics along.
player.timeoutID = setTimeout(() => {
if (! player.playAmountSubmitted ) {
let playedSeconds = getSecondsPlayed( player );
submitPlayerData( player, player.duration(), playedSeconds );
player.playAmountSubmitted = true;
delete allActivePlayers[player.fileName];
}
}, 30 * 60 * 1000);
};
mw.hook('tmh.player.loaded').add( ( videojsPlayer ) => {
videojsPlayer.on('play', onPlay);
videojsPlayer.on('pause', onPause);
});
window.onpagehide = (event) => {
for ( const fileName in allActivePlayers ) {
let curPlayer = allActivePlayers[fileName];
let playedSeconds = getSecondsPlayed( curPlayer );
submitPlayerData( curPlayer, curPlayer.duration(), playedSeconds );
delete allActivePlayers[fileName];
}
};
getSecondsPlayed = function( player ) {
// Calculate total amount played so far.
let playedRanges = player.played();
let playedSeconds = 0;
for (let i = 0; i < playedRanges.length; i++ ) {
playedSeconds += ( playedRanges.end(i) - playedRanges.start(i) );
}
return playedSeconds;
}
submitPlayerData = function( player, totalSeconds, playedSeconds) {
$.post( 'https://commons-play-listener.toolforge.org',
{ filename: player.fileName, totalDuration: totalSeconds, amountPlayed: playedSeconds });
}
}( mediaWiki, jQuery ) );