Skip to content

A very lightweight, RxPlayer-specialized, remote inspector

Notifications You must be signed in to change notification settings

canalplus/RxPaired

Repository files navigation

RxPaired: RxPlayer's Able Inspector for REmote Debugging

This repository contains the RxPaired tool, a lightweight remote inspector adapted for devices low on resources which displays supplementary indicators mostly useful when using the RxPlayer library.

screenshot of RxPaired

This project is functional and is regularly used at Canal+ for debugging media applications relying on the RxPlayer.

Its key features are:

  • Minimal influence on the device's CPU and memory resources when compared with Chrome's inspector and tools like weinre.

    This debugger can run for multiple hours without a noticeable performance impact, whereas chrome remote debugger lasted only a few minutes on the more constrained devices.

  • Ability to see in real time logs and useful playback indicators: which audio and video qualities are buffered at which position, information on network requests, evolution of the buffer's health etc.

  • Possibility to send any JavaScript instruction to the device.

  • "Time travel": Possibility to see the known playback conditions and its related indicators at the time a log was sent.

  • Possibility to store and export logs to either import them later or open them in your own editor.

  • It can be started even on production on any device and can be triggered during runtime.

Table Of Contents

Quick start

To quickly check if this tool can help you, you can test it easily:

  1. Make sure npm is installed and call:

    npx rx-paired

    (Note: Optionally, you can update the ports it relies on, call npx rx-paired --help to have more information on this).

  2. In a web browser, go to the inspector page which should now be served at http://127.0.0.1:8695.

  3. For our test, we will use the example token. Define it in the corresponding input and click on the Use now button to enable it. You will be redirected to a debugging page for that token.

  4. In another browser tab, go to the RxPlayer demo page (any page with the RxPlayer will do, but the RxPlayer JavaScript class - not an instance - needs to be accessible, see the script below).

    Open your browser's JavaScript console on that page and enter this code to dynamically link the inspector:

    import("http://127.0.0.1:8695/client.js#example")
      .then(() => {
        window.__RX_INSPECTOR_RUN__({
          url: "http://127.0.0.1:8695/client.js#example",
          // For other pages: the RxPlayer class needs
          // to be accessible and communicated here
          playerClass: RxPlayer,
        });
        console.info("Inspector initialized with success!");
      })
      .catch((error) =>
        console.error("Failed to dynamically import inspector:", error),
      );
  5. Play a content in that page.

  6. Go back to the inspector page. You should now see logs and graphs about playback!

If you want to understand how it all works and how to use this in more complex cases, keep reading below.

What is it?

RxPaired was first and foremost created to improve debugging and manual testing sessions on resource-constrained devices using the RxPlayer.

It aims to redirect logs received on the tested device to a web page (generally loaded on another device) while using the minimum possible resources on the tested device.

This web page also automatically exploits those logs to produce helpful graphs and metrics about what's currently happening with the player: how much data is buffered, of what audio and video quality etc.

You can also emit JavaScript instructions from the webpage to the device, as well as get responses back.

Yet, this tool was also written with modularity in mind. It should thus be very easy to remove the RxPlayer "modules" from the web inspector of RxPaired, and replace them by another logic, even for other usages than for media streaming.

How to use it?

Step 1 (simple): Running only the log server part

If you just want to obtain formatted logs and don't care about the inspector (the remote debugger part), it is much simpler to just run RxPaired with the --no-inspector option.

First make sure npm (node package manager) is installed and run in your terminal:

npx rx-paired --no-inspector

This will just start a server listening for logs and make the client script (usage described below) directly accessible, either through an URL or by copy-pasting the file.

Note: when copy-pasting, don't pay attention to the FORCED_TOKEN variable found inside this script, this is only needed when running with an inspector.

Step 1 (alternate): Running the full package, with a remote inspector

The full RxPaired tool also includes its "inspector", a remote debugger displaying metrics about playback and allowing you to send instructions to the device.

To run the full RxPaired package with the inspector included, enter in a terminal:

npx rx-paired

You can then load RxPaired's inspector pages by going to the outputed URL (https://127.0.0.1:8695 by default). You will have instructions allowing to generate a debugging "token" (multiple tokens can also be created to allow inspection of multiple devices simultaneously) and then, once you navigated to that token's page, ways to obtain the client script (more details on how to use it below).

Step 2: Linking the client script to your application

In step 1, you should either have obtained an URL, a file, or both, to a "client script". It will now need to be added to your application so it can send logs.

This client script monkey-patches some logging and networking logic to redirect logs to RxPaired's server through a WebSocket connection. To function optimally, it needs to be loaded before all other code in your application.

We thus recommend you to link this client script through a <script> tag inserted before all other <script> tags from the page you're debugging.

For example if your HTML page looks like this:

<html>
  <head>
    <title>My Page</title>
    <script src="./my-bundle.js"></script>
    <script src="./other-dependency.js"></script>
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

And if your client script can be accessed through the url http://127.0.0.1/my-script-url, you can write:

<html>
  <head>
    <title>My Page</title>
    <script src="http://127.0.0.1/my-script-url"></script>
    <script src="./my-bundle.js"></script>
    <script src="./other-dependency.js"></script>
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

If you would prefer to rely on the client script file instead, you can copy and paste it at the same location:

<html>
  <head>
    <title>My Page</title>
    <script>
      // THE CLIENT SCRIPT'S CODE GOES HERE
    </script>
    <script src="./my-bundle.js"></script>
    <script src="./other-dependency.js"></script>
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

NOTE: Only when running RxPaired with an inspector and copy-pasting the file, you'll need to include your token in the file's content manually. You can follow the instructions in the corresponding inspector page for more information.

Once any of those solutions is implemented, you can launch your application. A log file should now be created locally containing logs from it, and, if you ran the inspector, you should now be able to perform live debugging on it.

NOTE: When debugging on another device

In previous examples logs are sent and the client script is fetched through HTTP connections, not HTTPS ones. This can become problematic especially when debugging remote devices because HTTP connections will here most likely be blocked.

RxPaired exposes at most three HTTP ports:

  1. a port to communicate with inspectors (unless you ran in --no-inspector mode)
  2. an HTTP port to serve both the inspector pages and client script.
  3. a port listening for logs sent by your application

The inspector port should not cause any issue as inspector pages are generally only accessed locally. Also, the HTTP server is not mandatory as the client script can just be copy-pasted in your application's HTML page (instead of fetching it through an URL). However, the third port (the one listening for logs, 22626 by default) is used inside the client script and thus would need to be accessed through a secure connection.

Thankfully, easy and free solutions exist to proxify local HTTP servers from a remote HTTPS URL. ngrok for example is known to be functional but may necessitate you to login first. Other solutions should work but weren't tested by us (most notably WebSocket connections have to be properly redirected).

When using such a solution, you will need to perform a small update on the client script: the __FORCED_SERVER_URL__ variable on top of this file should now be set to the new HTTPS URL redirecting to your local port which listens for device logs (22626 by default).

The client script can then be copy-pasted in your application's page as described in step 2 (if you're relying on an inspector, don't forget to also update __FORCED_TOKEN__).

RxPaired on a server

If you plan to make RxPaired more globally accessible through a Web Server, building and running independently its three modules is more configurable:

  1. start RxPaired-server: see ./SERVER.md
  2. build and optionally serve the RxPaired-client script that will be put on the device: see ./CLIENT.md
  3. build and serve the RxPaired-inspector web page: see ./INSPECTOR.md.

For now, this will require you to first either clone the repository or to go to the directory npm installed RxPaired in. We're also thinking of easier solutions for doing that in the future.

How does it work?

RxPaired comes in three parts:

  1. The inspector web application, found in the ./inspector directory.

    This is the page that will be used to inspect what's going on on the device remotely from a browser. This page can also send instructions directly to the device (only through the page's console for now, as the user interface for this is not yet developped).

    Under the hood, this inspector relies on a WebSocket connection with the RxPaired's server to receive the device's source information (logs, requests etc.) and it contains some logic to construct graphical "modules" based on those logs: charts, curated information about playback etc.

    Note that multiple inspector pages can be created at the same time for multiple devices and multiple inspector pages can also be linked if they want to the same device. This is done through a system of "tokens", as explained in the inspector's main web page.

  2. A client-side script to deploy on the device, found in the ./client directory.

    This script mostly monkey-patches console and request-related functions so any interaction with those is communicated with the RxPaired's server through a WebSocket connection.

    This script is also able to execute commands sent from the Inspector web-application (which goes through the exact same WebSocket connection).

    The client-side script has a minimal amount of processing logic to communicate those information, so we can limit the influence on the device's performance. A single long-lived WebSocket connection is also used instead of multiple HTTP calls for those same considerations.

  3. The server, written in the ./server directory, on which the two precedent parts rely.

    The server listens on two ports for WebSocket connections: one for the inspector and the other for the client-side script.

    The server is very configurable: it can for example set-up a password to protect its access, shutdown when abnormal behavior is detected (like too many device or inspector connections, too many wrong password, too many WebSocket messages sent), create and keep log files for each inspected devices, give a maximum lifetime for each token, change the ports it listens to etc.

Why creating this tool?

The RxPlayer is an advanced media player which is used to play contents on a large panel of devices. Like for most software, we sometimes need to start debugging sessions on one of those, e.g., to investigate curious behavior.

As a player for the web platform, the RxPlayer can often profit from already available remote web inspectors to do just that from our PC. Most notably, the featureful Chrome remote debugger is a complete tool that is most often available. In cases where it isn't, weinre was also a very useful tool in the past.

However those tools have limitations on some devices. The one that hindered us the most, is that those tools often use a lot of resources: we're sometimes not even able to use the Chrome Remote Debugger for more than a minute on some targets with low memory (smart TVs, set-top boxes, ChromeCast...) and even in the time window where we can, the resource usage those tools take might provoke large side-effects and is a very frequent source of heisenbug for our team.

When what we wanted to do was just to recuperate logs from the device, this became very annoying.

After initial even-lighter tools like a simple HTTP, then WebSocket-based log server, we noticed that we could do even better in terms of usability and usefulness than a simple log server: our own remote inspector tool, whose core goal would be lightweightness and, why not, also have the advantage of being specialized for the debugging of the RxPlayer.

Enter RxPaired: The RxPlayer's Able Inspector for Remote Debugging

About

A very lightweight, RxPlayer-specialized, remote inspector

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published