Echo360 Super Speed

Adds faster speed options (4x, 3x) to Echo360 player and allows the user to add their own speed options.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

You will need to install an extension such as Tampermonkey to install this script.

Tendrás que instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Tendrás que instalar una extensión como Tampermonkey antes de poder instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name        Echo360 Super Speed
// @namespace   https://www.petertanner.dev/
// @description Adds faster speed options (4x, 3x) to Echo360 player and allows the user to add their own speed options.
// @include     *://echo360.net.au/*
// @include     *://echo360.org.uk/*
// @include     *://echo360.org/*
// @include     *://echo360.ca/*
// @include     *://echo360.org.au/*
// @version     1.2
// @author      Peter Tanner
// @namespace   https://github.com/peter-tanner/Echo360-Super-Speed-Userscript/
// @supportURL  https://github.com/peter-tanner/Echo360-Super-Speed-Userscript/issues
// @license     GPL-3.0
// @website     https://www.petertanner.dev/
// @run-at      document-start
// ==/UserScript==

/* USER CUSTOMIZATION BEGIN */
// NOTE: Add (or remove) speeds to this array to your liking.
// Note that there is a browser set limit of 16x, and speeds above 4x are muted.
// https://searchfox.org/mozilla-central/rev/f1c881ba5603410dacbe52874053af38bd825c3b/dom/html/HTMLMediascript_Element.cpp#179-183
const selected_speeds = [4, 3, 2, 1.75, 1.5, 1.25, 1, 0.75];
// const selected_speeds = [2, 1.75, 1.5, 1.25, 1, 0.75, 0.5, 0.25]; // Default Echo360 speeds.

// NOTE: Change this to modify how much the speed changes when you use the < or
// > hotkey to change speed
const speed_hotkey_increment = 0.25;
/* USER CUSTOMIZATION END */

// The code in compatible string representation since we are putting strings in
// script tags instead of executing them here.
const speed_code_txt =
  "[" +
  selected_speeds
    .map((speed) => `{label:"${speed}x",value:${speed}}`)
    .join(",") +
  "]";

const max_speed = Math.max(...selected_speeds);
const min_speed = Math.min(...selected_speeds);

// The page contains a script tag which is called after the player bundle
// `echoPlayerV2FullApp.react-bundle.js` is downloaded. This tag is generated
// with the page and contains information about the video (such as the title,
// institution and thumbnail paths) and calls the player with this information.
// This contextual information is stored in the variable to be called after the
// player is modified.
var player_calling_context =
  "console.error('Echo360 super speed failed to load :(')";

new MutationObserver(async (mutations, observer) => {
  let script_elem = mutations
    .flatMap((e) => [...e.addedNodes])
    .filter((e) => e.tagName === "SCRIPT")
    .find((e) => e.src.match(/echoPlayerV2FullApp\.react-bundle\.js/));

  if (script_elem) {
    // Do not load the unmodified player code
    observer.disconnect();
    script_elem.remove();

    // Download the player code for modification...
    await fetch(script_elem.src)
      .then((e) => e.text())
      .then((player_code) => {
        player_code = player_code.replace(
          // Overwrite all previous speeds in case the user wants to remove the
          // default speeds
          '[{label:"2x",value:2},{label:"1.75x",value:1.75},{label:"1.5x",value:1.5},{label:"1.25x",value:1.25},{label:"1x",value:1},{label:"0.75x",value:.75},{label:"0.5x",value:.5},{label:"0.25x",value:.25}]',

          // Replace with our custom speeds
          speed_code_txt
        );

        player_code = player_code.replace(
          // This code handles hotkeys for changing speed, adjust bounds to match new speeds.
          '{key:">",handler:function(){b<2&&I(b+.25)}},{key:"<",handler:function(){b>.25&&I(b-.25)}}',
          `{key:">",handler:function(){b<${max_speed}&&I(b+${speed_hotkey_increment})}},{key:"<",handler:function(){b>${min_speed}&&I(b-${speed_hotkey_increment})}}`
        );

        // Add the player calling context code since this event listener does
        // not block, resulting in the original player calling code being called
        // (with a harmless error, since the player code has not loaded by the
        // time it is called)
        player_code +=
          ";" +
          player_calling_context +
          "; console.log('Echo360 super speed has successfully been loaded :3')";

        // Create a new script tag containing the modified player & add to head
        const new_script = document.createElement("script");
        new_script.type = "text/javascript";
        new_script.textContent = player_code;
        document.getElementsByTagName("head")[0].append(new_script);
      });
  }
}).observe(document, {
  childList: true,
  subtree: true,
});

window.addEventListener(
  "load",
  () => {
    const script_elems = document.getElementsByTagName("script");
    player_calling_context = script_elems[script_elems.length - 1].innerText;
  },
  false
);