Skip to content

Latest commit

 

History

History
242 lines (174 loc) · 7.55 KB

README.md

File metadata and controls

242 lines (174 loc) · 7.55 KB

Player Debugging Tools

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 .

How to install it

Including the script directly

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 .

Adding the tool as a dependency

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://[email protected]/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);

Tools

PlayerTools is in fact multiple tools which approach different subjects:

  • Buffer management

  • EME inspecting

  • MSE inspecting

  • ISOBMFF parsing

EMESpy

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 .

MSESpy

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 .

inspectISOBMFF

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 .

Buffered state

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.

Ranges intervals

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

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:

  1. spiedObject {Object} - Object in which the function you want to spy on is in.
  2. fnName {string} - name of the function in obj
  3. 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.

Example

// 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();