UX: Fetch higher-resolution youtube thumbnails where available

UX: Fetch higher-resolution youtube thumbnails where available

We have been using YouTube’s ‘hqdefault.jpg’ image which works consistently to provide a 480x360 thumbnail. YouTube does provide larger thumbnails, but not consistently for every video. By using og:image, we will fetch the best resolution YouTube can provide for each video.

This commit also refactors lazy-yt to re-use the thumbnail already existing in the cooked content. This means we get lazy-loading for free, and avoid hotlinking images to YouTube (when download remote images is enabled on the site).

diff --git a/plugins/lazy-yt/assets/javascripts/lazyYT.js b/plugins/lazy-yt/assets/javascripts/lazyYT.js
index 651ea9d..92a3542 100644
--- a/plugins/lazy-yt/assets/javascripts/lazyYT.js
+++ b/plugins/lazy-yt/assets/javascripts/lazyYT.js
@@ -87,6 +87,8 @@
     innerHtml.push("</div>"); // .html5-title-text-wrapper
     innerHtml.push("</div>"); // end of Video title .html5-info-bar
 
+    const prefetchedThumbnail = $el[0].querySelector(".ytp-thumbnail-image");
+
     $el
       .css({
         "padding-bottom": padding_bottom
@@ -108,17 +110,27 @@
       thumb_img = "default.jpg";
     }
 
+    if (prefetchedThumbnail) {
+      $el.find(".ytp-thumbnail").append(prefetchedThumbnail);
+    } else {
+      // Fallback for old posts which were baked before the lazy-yt onebox prefetched a thumbnail
+      $el
+        .find(".ytp-thumbnail")
+        .append(
+          $(
+            [
+              '<img class="ytp-thumbnail-image" src="https://img.youtube.com/vi/',
+              id,
+              "/",
+              thumb_img,
+              '">'
+            ].join("")
+          )
+        );
+    }
+
     $thumb = $el
       .find(".ytp-thumbnail")
-      .css({
-        "background-image": [
-          "url(https://img.youtube.com/vi/",
-          id,
-          "/",
-          thumb_img,
-          ")"
-        ].join("")
-      })
       .addClass("lazyYT-image-loaded")
       .on("click", function(e) {
         e.preventDefault();
diff --git a/plugins/lazy-yt/assets/stylesheets/lazyYT.css b/plugins/lazy-yt/assets/stylesheets/lazyYT.css
index 134a535..233c342 100644
--- a/plugins/lazy-yt/assets/stylesheets/lazyYT.css
+++ b/plugins/lazy-yt/assets/stylesheets/lazyYT.css
@@ -103,11 +103,12 @@
   font-size: normal !important;
   font-weight: normal !important;
   line-height: 1 !important;
-  opacity: .9;
+  opacity: 0.9;
+  z-index: 935;
 }
 
 .ytp-large-play-button-svg {
-  opacity: .9;
+  opacity: 0.9;
   fill: #1f1f1f;
 }
 
@@ -116,3 +117,10 @@
   opacity: 1;
   fill: #cc181e;
 }
+
+.ytp-thumbnail-image {
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+}
diff --git a/plugins/lazy-yt/plugin.rb b/plugins/lazy-yt/plugin.rb
index 3665244..4f5517c 100644
--- a/plugins/lazy-yt/plugin.rb
+++ b/plugins/lazy-yt/plugin.rb
@@ -25,6 +25,9 @@ class Onebox::Engine::YoutubeOnebox
       video_width = (params['width'] && params['width'].to_i <= 695) ? params['width'] : 480 # embed width
       video_height = (params['height'] && params['height'].to_i <= 500) ? params['height'] : 270 # embed height
 
+      og = get_opengraph.data
+      thumbnail_url = og[:image] || "https://img.youtube.com/vi/#{video_id}/hqdefault.jpg"
+
       # Put in the LazyYT div instead of the iframe
       escaped_title = ERB::Util.html_escape(video_title)
 
@@ -36,7 +39,7 @@ class Onebox::Engine::YoutubeOnebox
            data-height="#{video_height}"
            data-parameters="#{embed_params}">
         <a href="https://www.youtube.com/watch?v=#{video_id}" target="_blank">
-          <img src="https://img.youtube.com/vi/#{video_id}/hqdefault.jpg" width="#{video_width}" height="#{video_height}" title="#{escaped_title}">
+          <img class="ytp-thumbnail-image" src="#{thumbnail_url}" width="#{video_width}" height="#{video_height}" title="#{escaped_title}">
         </a>
       </div>
       EOF

GitHub sha: ac042c2b

1 Like