This repository regroups multiple tools useful for debugging web video and audio players.
It was created in my free time with the goal to have a better debugging and reverse-engineering experience for the rx-player .
Because this is mainly a debugging application, the most straightforward way of using it is just to copy the code of the compiled bundle directly, and to copy-paste it into your console.
You will then have a global PlayerTools
object, through which you can call
any tool defined here.
Example:
PlayerTools.prettyPrintBuffered(player.getVideoElement().buffered);
This configuration can also be useful by including this script automatically in multimedia pages. This can be done through userscript managers, such as Tampermonkey for Chrome or Greasemonkey for Firefox .
The cleaner way to use these tools is to include its npm module as a dependency and to add it in your code.
You can install PlayerTools by using its github repository:
npm install git+https://git@github.com/peaberberian/player-debugging-tools.git
You will then be able to use it by importing the "player-debugging-tools"
module:
import PlayerTools from "player-debugging-tools";
PlayerTools.prettyPrintBuffered(player.getVideoElement().buffered);
PlayerTools
is in fact multiple tools which approach different subjects:
-
Buffer management
-
EME inspecting
-
MSE inspecting
-
ISOBMFF parsing
EMESpy
allows to spy on EME API calls, to know which API have been called,
at which time, with which arguments and what their response are.
It is accessible through PlayerTools.EMESpy
.
All its documentation is available in its original repository .
Like EMESpy
, MSESpy
allows to spy on API calls, but here it is for the
ones concerning the MediaSource extensions or MSE.
It is accessible through PlayerTools.MSESpy
.
All its documentation is available in its original repository .
inspectISOMFF
is a function allowing you to directly probe ISOBMFF files
in the console. It displays in a human-readable format most data an ISOBMFF file
can store.
It is accessible through PlayerTools.inspectISOBMFF
.
All its documentation is available in its original repository .
There is several functions allowing to inspect the current state of the buffer.
prettyPrintBuffered
allows to have a string representation of time ranges:
const firstVideoElt = document.getElementsByTagName("video")[0];
PlayerTools.prettyPrintBuffered(firstVideoElt.buffered);
// Result:
// "|0.00----(29.95)----|29.95 <30.05> |60.00----(29.86)----|89.86 <9.98>|99.85----(20.15)----|120.00"
//
// That result means that our video element has 29.95 seconds of buffer between
// 0 and 29.95 seconds.
// Then 30.05 seconds where no buffer is found.
// Then 29.86 seconds of buffer between 60.00 and 89.86 seconds.
// Then 9.98 seconds where no buffer is found.
// Then 20.15 seconds of buffer between 99.85 and 120 seconds.
To simplify its use, you can also call instead:
-
prettyPrintMediaElementBuffer
which just takes the media element instead:const firstVideoElt = document.getElementsByTagName("video")[0]; PlayerTools.prettyPrintMediaElementBuffer(firstVideoElt);
-
prettyPrintVideoBuffer
which just takes the first video element it find in the page:PlayerTools.prettyPrintVideoBuffer();
As often, there is only one video element, this is the variation I use the most.
A more specialized approach to understand the current buffer is by inspecting closely the current, previous and next time ranges (that is, the size of it, the distance between one another, etc.).
There is several tools that allows to do that:
prettyPrintCurrentRanges
needs you to give the current position and
TimeRanges:
const firstVideoElt = document.getElementsByTagName("video")[0];
PlayerTools.prettyPrintCurrentRanges(
firstVideoElt.currentTime,
firstVideoElt.buffered
);
// Result:
// {
// "currentPosition": 185.850631,
//
// "currentRange": {
// "start": 181.515,
// "end": 208.207,
// "duration": 26.692000000000007 // (comes with IEEE 754 rounding errors!)
// },
//
// "previousRange": {
// "start": 60.001,
// "end": 69.402,
// "duration": 9.401000000000003
// },
// "currentDeltaWithPreviousRange": 116.44863099999999,
//
// "nextRange": {
// "start": 330.001,
// "end": 340.001,
// "duration": 10
// },
// "currentDeltaWithNextRange": 144.15036899999998
// }
To simplify its use, you can also call instead:
-
prettyPrintMediaElementCurrentRanges
which just takes the media element instead:const firstVideoElt = document.getElementsByTagName("video")[0]; PlayerTools.prettyPrintMediaElementCurrentRanges(firstVideoElt);
-
prettyPrintVideoCurrentRanges
which just takes the first video element it find in the page:PlayerTools.prettyPrintVideoCurrentRanges();
Again, as there is only one video element, this is the variation I use the most.
addSpy
is a function allowing you to spy on a function:
- display log each time the function is called with its arguments
- display log each time the function returns with the return value
- optionally add a debugger statement to have a breakpoint each time it is called.
It is accessible through PlayerTools.addSpy
.
It takes two or three arguments:
- spiedObject {Object} - Object in which the function you want to spy on is in.
- fnName {string} - name of the function in
obj
- addDebugger {boolean|undefined} - If true, a debugger statement is added for each time the function is called. This value is optional.
This function returns another function which allows to remove the spy when called.
// simple appendBuffer spy
// Will display two logs each times it is called:
// - When it is called with the corresponding argument
// - When it returned with the corresponding return value
let removeSpy = addSpy(SourceBuffer.prototype, "appendBuffer");
// Remove that spy
removeSpy();
// Same but adds a debugger (a breakpoint basically) before the function is
// really called.
let removeSpy = addSpy(SourceBuffer.prototype, "appendBuffer", true);
// Remove that spy
removeSpy();