4

I'd like to use Greasemonkey to add a subtitle download button for Openload VTT subtitles. However, I can't figure out how to access the <track> tag.

Take, for example, this French video clip with English subtitles. When I looked at the source code in Firefox, I found this:

<video id="olvideo" width="100%" height="100%" crossorigin="anonymous" controls>
    <track kind="captions" src="https://thumb.oloadcdn.net/subtitle/rjC09fkPLYs/vt8zTaIaVqQ.vtt" srclang="en" label="English" default />
</video>

Why doesn't my proof-of-concept Greasemonkey code work?

// ==UserScript==
// @name        Openload
// @include     *openload.co*
// @run-at      document-idle
// ==/UserScript==

var video = document.querySelector("video");

if (video) {
    var track = video.querySelector("track");
    if (track) {
        alert ("<track> FOUND.");
    } else {
        alert ("<track> NOT found!");
    }

} else { 
    alert ("<video> tag not found");
}

(When I ran the script I got the message "<track> NOT found!".)

Nemo XXX
  • 644
  • 2
  • 14
  • 35

2 Answers2

4

The link you gave doesn't ever have a <track> node, at least for me (un logged-in, and not the video's creator).

Nevertheless, this is may be a standard AJAX problem. That is, if the node is added via javascript (AJAX), the Tampermonkey script will have finished before the target node is loaded.

Use standard ajax-aware techniques for that. One way:

// ==UserScript==
// @name     Openload.co, Report on track nodes
// @match    *://openload.co/embed/*
// @match    *://interactive-examples.mdn.mozilla.net/pages/tabbed/track.html
// @require  https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @require  https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant    GM_addStyle
// @grant    GM.getValue
// ==/UserScript==
//- The @grant directives are needed to restore the proper sandbox.

waitForKeyElements ("track", reportTrackNode);

//-- For Mozilla page, which uses shadow DOM:
waitForKeyElements ("shadow-output", reportTrackNodeWithinShadowDOM);

function reportTrackNode (jNode) {
    console.log ("Found <track>:", jNode[0]);
}

function reportTrackNodeWithinShadowDOM (jNode) {
    var sr      = jNode[0].shadowRoot;
    var trck    = $(sr.childNodes).find ("track");
    if (trck.length === 0)  return true;  //  Keep waiting.

    console.log ("Found <track>:", trck[0]);
}

Note that the above code works in Tampermonkey, Violentmonkey, and earlier versions of Greasemonkey. It should work in Greasemonkey 4+, but that engine is very broken, so no guarantees.

You can see that the code does find the track when it exists (even in a shadow DOM) by installing the script and visiting this MDN video demo page.

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • Thanks for your reply! Unfortunately, your code didn't work with Greasemonkey/TamperMonkey. `The link you gave doesn't ever have a node[...]` I forgot to mention that I installed an ad blocker. (Without it, you'll see a couple of nasty ads, which, of course, don't have nodes.) Please visit the site (with an ad blocker) and wait until the video clip plays. You'll notice that it indeed plays English VTT subtitles. – Nemo XXX Oct 31 '18 at 05:58
  • @NemoXXX, I always use adblockers and scriptblockers. Even had to temporarily reduce a couple settings to see the video at all. I see the subtitles but there is no `` node. Try visiting the link in a new browser (or instance) where you are not logged in and have no cookies set. .. And you can see that the above script works by changing `track` to `video`. Or, install the updated script and visit the MDN link given. – Brock Adams Oct 31 '18 at 07:57
  • Thanks for the updated code! It works fine with the MDN link, but not with the openload video. `I see the subtitles but there is no node.` Since the subtitles aren't hard-coded, how are they played if there's no `` node? `And you can see that the above script works by changing track to video.` It does return a video element (`video id="olvideo_html5_api`). However, when I select View Page Source in Firefox, I see a different video tag (`video id="olvideo"`), which does have nodes. Most likely openload.co runs a script that adds `` nodes on the fly. – Nemo XXX Oct 31 '18 at 08:34
  • If the track nodes are added on the fly AND it's not a flash player AND it's not in a shadow DOM (those need special handling as shown), then the script would catch it anyway. I have never seen a track node on that page in neither Firefox nor Chrome. If you can come up with a reliable recipe for an unregistered, brand new user to see one, then we can figure it out. Also, that site has a few malware reports. As for how those subtitles appear, is there a shadow dom or iframe somewhere? (I didn't see one, but didn't look hard either.) – Brock Adams Oct 31 '18 at 08:42
  • Since the bounty will expire soon, I have one more question for you: why does the code that I see when I select View Page Source doesn't match the code that GreaseMonkey/TamperMonkey sees? (When I select View Page Source I see that tags that I need.) – Nemo XXX Nov 09 '18 at 05:33
  • @NemoXXX, that's probably because of ajax timing or because of something like shadow DOM. I don't see the claimed tag in either FF or Chrome. On either windows or Linux. Come up with a recipe for me to see it and I can help you further. What browser version? What OS? What happens if you switch to a different browser **where you have never logged in**? – Brock Adams Nov 09 '18 at 07:07
  • I see the vtt track only with the 64bit Linux/Windows 10 versions of Firefox 63.0.1 (View Page Source) and Opera 56.0.3051.70 (Developer > Page Source). I don't see it with MS Edge and Google Chrome. – Nemo XXX Nov 09 '18 at 07:54
  • @NemoXXX, I see and also erosman beat me to it. That site/page loads ``s *statically*, and then uses javascript to erase them from the DOM. Very hokey. Anyway, you have your workaround, fetch the page a second time, via XHR request, and custom process the source. – Brock Adams Nov 09 '18 at 19:39
2

Here is a simple/basic script. I didn't know which version of GM you are using. This is written for GM4 If you are using GM 3, then change:

GM.xmlHttpRequest -> GM_xmlhttpRequest
GM.openInTab -> GM_openInTab

It opens the subtitles in a new tab so you can save it. You can run it on both embed and normal file pages. e.g.
https://openload.co/embed/rjC09fkPLYs
https://openload.co/f/rjC09fkPLYs

// ==UserScript==
// @name          Openload Subtitle Download
// @namespace     erosman
// @description   Openload Subtitle Download
// @include       https://openload.co/f/*
// @include       https://openload.co/embed/*
// @grant         GM.xmlHttpRequest
// @grant         GM_xmlhttpRequest
// @grant         GM.openInTab
// @grant         GM_openInTab
// @author        erosman
// @version       1.0
// ==/UserScript==

/* --------- Note ---------
  This script download Openload Subtitles.
  It runs on both embed and normal file pages.
  --------- History ---------


  1.0   Initial release

*/

(() => { // anonymous function wrapper, for error checking & limiting scope, async FF52+
'use strict';

if (frameElement || !location || !document.body) { return; } // end execution if in a frame/object/embedding points


// --- get the document
GM.xmlHttpRequest({
  method: 'GET',
  url: location.href,
  onload: result => processResult(result.responseText),
  onerror: error => console.log(error)
});

function processResult(str) {

  // convert to DOM
  const doc = new DOMParser().parseFromString(str, 'text/html');

  // get tracks with source, convert to array for forEach, 
  // open each subtitle (if there are more than one) in a new tab
  // you can save it from there
  [...doc.querySelectorAll('track[src]')].forEach(item => GM.openInTab(item.src));
}

// end of anonymous function
})();
erosman
  • 7,094
  • 7
  • 27
  • 46
  • Thanks for the great script! (It works fine with Firefox & Greasemonkey and Chrome & Tampermonkey.) – Nemo XXX Nov 09 '18 at 12:51