Get YouTube Thumbnail

Adds button to view largest thumbnail image for any video

  1. // ==UserScript==
  2. // @name Get YouTube Thumbnail
  3. // @version 0.9
  4. // @description Adds button to view largest thumbnail image for any video
  5. // @author Drazen Bjelovuk
  6. // @match *://www.youtube.com/*
  7. // @grant none
  8. // @run-at document-end
  9. // @namespace https://greasyfork.org/users/11679
  10. // @contributionURL https://goo.gl/dYIygm
  11. // ==/UserScript==
  12.  
  13. document.addEventListener('spfdone', addThumbnailButton);
  14. document.addEventListener('yt-navigate-start', addThumbnailButton);
  15.  
  16. addThumbnailButton();
  17.  
  18. const sizes = ['/maxresdefault.jpg', '/hqdefault.jpg', '/mqdefault.jpg', '/sddefault.jpg'];
  19. var vidId;
  20.  
  21. function tryLoad(index) {
  22. var image = new Image();
  23. image.onload = function(img) {
  24. if (img.path[0].naturalWidth > 120) {
  25. spinner.querySelector('#spinnerContainer').classList.remove('active');
  26. window.open(img.path[0].src);
  27. }
  28. else if (index < sizes.length - 1) {
  29. tryLoad(index + 1);
  30. }
  31. };
  32. image.src = 'https://img.youtube.com/vi/'+ vidId + sizes[index];
  33. }
  34.  
  35. var interval;
  36. var spinnerTemplate = document.createElement('template');
  37. spinnerTemplate.innerHTML = '<paper-spinner id="thumbnailSpinner" class="style-scope yt-next-continuation"><div id="spinnerContainer" class="style-scope paper-spinner"><div class="spinner-layer layer-1 style-scope paper-spinner"><div class="circle-clipper left style-scope paper-spinner"></div><div class="circle-clipper right style-scope paper-spinner"></div></div><div class="spinner-layer layer-2 style-scope paper-spinner"><div class="circle-clipper left style-scope paper-spinner"></div><div class="circle-clipper right style-scope paper-spinner"></div></div><div class="spinner-layer layer-3 style-scope paper-spinner"><div class="circle-clipper left style-scope paper-spinner"></div><div class="circle-clipper right style-scope paper-spinner"></div></div><div class="spinner-layer layer-4 style-scope paper-spinner"><div class="circle-clipper left style-scope paper-spinner"></div><div class="circle-clipper right style-scope paper-spinner"></div></div></div></paper-spinner>';
  38. var spinner = spinnerTemplate.content.firstChild;
  39.  
  40. function addThumbnailButton() {
  41. var button = document.getElementById('viewThumbnailBtn');
  42. if (button) button.remove();
  43.  
  44. var subscribeButton = document.querySelector('ytd-video-secondary-info-renderer #subscribe-button');
  45. if (subscribeButton) {
  46. button = document.createElement('tp-yt-paper-button');
  47. button.id = 'viewThumbnailBtn';
  48. button.className = 'style-scope ytd-subscribe-button-renderer';
  49. button.style.cssText = 'margin-left: 10px';
  50. button.textContent = 'View Thumbnail';
  51. button.onclick = function() {
  52. spinner.querySelector('#spinnerContainer').classList.add('active');
  53. vidId = document.querySelector('[video-id]').getAttribute('video-id');
  54. tryLoad(0);
  55. };
  56. subscribeButton.parentNode.insertBefore(button, subscribeButton);
  57. subscribeButton.parentNode.insertBefore(spinner, button);
  58.  
  59. clearInterval(interval);
  60. }
  61. else if (~window.location.href.indexOf('v=')) {
  62. clearInterval(interval);
  63. interval = setInterval(addThumbnailButton, 500);
  64. }
  65. }