YouTube Thumbnails - Full Video Thumbnails for YouTube

Shows complete video thumbnails for YouTube videos. You can click a thumbnail image to jump to that point in the video.

Old: v0.4.1 - 2017-09-01 - Fixed some issues with Youtube's dynamic loading
New: v0.4.2 - 2017-09-01 - Fixed compatibility with old YouTube layout

  • --- /tmp/diffy20240424-1652143-chvhc4 2024-04-24 05:53:49.012868381 +0000
  • +++ /tmp/diffy20240424-1652143-gr93r2 2024-04-24 05:53:49.012868381 +0000
  • @@ -3,8 +3,8 @@
  • // @namespace driver8.net
  • // @description Shows complete video thumbnails for YouTube videos. You can click a thumbnail image to jump to that point in the video.
  • // @match *://*.youtube.com/*
  • -// @version 0.4.1
  • -// @require https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js
  • +// @version 0.4.2
  • +// @require https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js
  • // @grant GM_addStyle
  • // @grant unsafeWindow
  • // @grant GM_registerMenuCommand
  • @@ -25,7 +25,7 @@
  • var MAX_IMAGES = 400;
  • var LOGGING = true;
  • -var $thumbDiv, $thumbHeader, $titleDiv, storyboard_spec, storyboard, best_size_idx, best_size, len_seconds, tries;
  • +var $thumbDiv, $thumbHeader, $titleDiv, storyboard_spec, storyboard, best_size_idx, best_size, len_seconds, tries, yp, scriptStarted = false;
  • function log(msg) {
  • LOGGING && console.log(msg);
  • @@ -34,40 +34,52 @@
  • console.log("Hi");
  • function findStuff(event) {
  • + scriptStarted = true;
  • event && console.log(event);
  • if (!window.location.href.match(/watch\?/)) { return; }
  • - $('#thumbDiv').size() > 0 && $('#thumbDiv').remove();
  • - var y = window.ytcfg || unsafeWindow.ytcfg;
  • - console.log('ytcfg', y);
  • - var reqHeaders = {
  • - "X-YouTube-Client-Name": y.data_.INNERTUBE_CONTEXT_CLIENT_NAME,
  • - "X-YouTube-Client-Version": y.data_.INNERTUBE_CONTEXT_CLIENT_VERSION,
  • - "X-Youtube-Identity-Token": y.data_.XSRF_TOKEN,
  • - "X-YouTube-Page-CL": y.data_.PAGE_CL,
  • - "X-YouTube-Page-Label": y.data_.PAGE_BUILD_LABEL,
  • - "X-YouTube-Variants-Checksum": y.data_.VARIANTS_CHECKSUM
  • - };
  • - console.log('req headers', reqHeaders);
  • - GM_xmlhttpRequest({
  • - method: 'GET',
  • - url: window.location.href + '&pbj=1',
  • - headers: reqHeaders,
  • - onload: function (resp) {
  • - console.log(resp);
  • - var foo = JSON.parse(resp.responseText);
  • - console.log(foo);
  • - storyboard_spec = foo[2].player.args.storyboard_spec;
  • - console.log(foo[2].player.args.storyboard_spec);
  • - tries = 0;
  • - tryTitle();
  • - }
  • - });
  • + yp = (window && window.ytplayer) || (unsafeWindow && unsafeWindow.ytplayer);
  • + storyboard_spec = yp && yp.config.args.storyboard_spec;
  • +
  • + if ($('#thumbDiv').size() > 0) {
  • + $('#thumbDiv').remove();
  • + storyboard_spec = null;
  • + }
  • +
  • + if (storyboard_spec) {
  • + tryTitle();
  • + } else {
  • + var y = window.ytcfg || unsafeWindow.ytcfg;
  • + console.log('ytcfg', y);
  • + var reqHeaders = {
  • + "X-YouTube-Client-Name": y.data_.INNERTUBE_CONTEXT_CLIENT_NAME,
  • + "X-YouTube-Client-Version": y.data_.INNERTUBE_CONTEXT_CLIENT_VERSION,
  • + "X-Youtube-Identity-Token": y.data_.XSRF_TOKEN,
  • + "X-YouTube-Page-CL": y.data_.PAGE_CL,
  • + "X-YouTube-Page-Label": y.data_.PAGE_BUILD_LABEL,
  • + "X-YouTube-Variants-Checksum": y.data_.VARIANTS_CHECKSUM
  • + };
  • + console.log('req headers', reqHeaders);
  • + GM_xmlhttpRequest({
  • + method: 'GET',
  • + url: window.location.href + '&pbj=1',
  • + headers: reqHeaders,
  • + onload: function (resp) {
  • + console.log(resp);
  • + var foo = JSON.parse(resp.responseText);
  • + console.log(foo);
  • + storyboard_spec = foo[2].player.args.storyboard_spec;
  • + console.log(foo[2].player.args.storyboard_spec);
  • + tries = 0;
  • + tryTitle();
  • + }
  • + });
  • + }
  • +
  • }
  • function tryTitle() {
  • console.log('tryTitle');
  • - $titleDiv = $('div#info.ytd-watch');
  • + $titleDiv = $('div#info.ytd-watch, #watch-header');
  • if (!$titleDiv || $titleDiv.prop('nodeName') !== 'DIV') {
  • if (tries++ < MAX_TRIES) {
  • console.log("no title div");
  • @@ -79,7 +91,6 @@
  • }
  • }
  • -
  • function setUp() {
  • if (storyboard_spec) {
  • console.log('sb_spec', storyboard_spec);
  • @@ -88,23 +99,21 @@
  • best_size_idx = chooseBestStoryboardSize(storyboard);
  • best_size = storyboard.sizes[best_size_idx];
  • console.log(best_size);
  • - len_str = unsafeWindow.ytplayer.config.args.length_seconds || $('div.ytp-progress-bar').attr('aria-valuemax');
  • - //console.log($('div.ytp-progress-bar'));
  • - //len_str = $('div.ytp-progress-bar').attr('aria-valuemax');
  • -
  • + len_str = yp.config.args.length_seconds || $('div.ytp-progress-bar').attr('aria-valuemax');
  • len_seconds = parseInt(len_str);
  • console.log("len: " + len_seconds);
  • - $thumbDiv = $('<div id="thumbDiv" class="style-scope thumb-inactive"></div>');
  • + $thumbDiv = $('<div id="thumbDiv" class="style-scope yt-card thumb-inactive"></div>');
  • $thumbHeader = $('<h1 width="100%" class="title ytd-video-primary-info-renderer">Thumbnails</h1>');
  • $thumbDiv.append($thumbHeader);
  • $thumbDiv.click(showThumbs);
  • } else if (unsafeWindow.ytplayer) {
  • - $thumbDiv = $('<div id="thumbDiv" class="style-scope no-thumbs"></div>');
  • + $thumbDiv = $('<div id="thumbDiv" class="style-scope yt-card no-thumbs"></div>');
  • $thumbHeader = $('<h1 width="100%" class="title ytd-video-primary-info-renderer">No Thumbnails Available</h1>');
  • $thumbDiv.append($thumbHeader);
  • } else {
  • console.log("Reload for thumbs");
  • - $thumbDiv = $('<div id="thumbDiv" class="style-scope no-thumbs"></div>');
  • + $thumbDiv = $('<div id="thumbDiv" class="style-scope yt-card no-thumbs"></div>');
  • $thumbHeader = $('<h1 width="100%" class="title ytd-video-primary-info-renderer">Reload for Thumbnails</h1>');
  • $thumbDiv.append($thumbHeader);
  • }
  • @@ -374,13 +383,21 @@
  • //window.addEventListener('readystatechange',username,true);
  • //window.addEventListener('readystatechange', findStuff);
  • // Runs the function when the page changes via SPF method: https://github.com/youtube/spfjs/
  • -//window.addEventListener('spfdone', findStuff);
  • +window.addEventListener('spfdone', findStuff);
  • //window.addEventListener('yt-navigate', findStuff);
  • //window.addEventListener('yt-page-type-changed', findStuff);
  • window.addEventListener('yt-navigate-finish', findStuff);
  • window.addEventListener('yt-navigate-finish', killSPF);
  • //findStuff();
  • killSPF();
  • +window.setTimeout(function() {
  • + if (!scriptStarted) {
  • + console.log('timed start');
  • + findStuff();
  • + } else {
  • + console.log('no timed start');
  • + }
  • +}, 20);
  • //VIMEO info