There are times when I want to include a YouTube video in a post, but
I’m not content with a regular link. YouTube provides embeds for this
purpose, but they use <iframe> and come with a hefty
JavaScript payload. Among other things, this payload tracks visitors on
my site if they play a video embedded in one of my posts. I don’t
particularly like the idea of Google tracking people visitingmy
website; if I wanted Google to have any information about my visitors
I’d run Google Analytics.
yttget: An
Alternative to YouTube Embeds
If I don’t want embeds because of JavaScript and analytics, but plain links are too bland, what can I do? I can wrap a thumbnail inside a link with a tooltip and caption advising visitors to click the image to watch the video, and have the link open in a new tab.
Every video has an unique identifier, such as “o0W91FrTlYk”. This
identifier represents the official video for “End of the Beginning” by Black
Sabbath. You can get the ID out of the URL for a particular video,
which in this case
ishttps://www.youtube.com/watch?v=o0W91FrTlYk. Once you
have the ID, you can retrieve its associated thumbnail, which currently
lives at
http://i3.ytimg.com/vi/o0W91FrTlYk/hqdefault.jpg
If you’re on a Unix-like machine1, you can automate the
process of extracting the ID from a given YouTube URL and fetching its
thumbnail with a reasonably small shell script. You can even have this
script create HTML for displaying the thumbnail and pipe it to your
clipboard. I did that myself with a little script I
callyttget, for “YouTube Thumbnail GET”2.
Here’s the code, sans license text.
#!/bin/sh -e
URL="$1"
ID=$(echo $URL | cut -d = -f 2)
FILENAME="youtube-${ID}"
CWD=$(pwd)
JPG="${CWD}/${FILENAME}.jpg"
THUMB_URL="http://i3.ytimg.com/vi/${ID}/hqdefault.jpg"
CAPTION="click to view"
curl ${THUMB_URL} --output ${JPG}
echo "<figure>
<a href=\"https://www.youtube.com/watch?v=${ID}\"
title=\"${CAPTION}\"
target=\"_blank\"
rel=\"noreferrer noopener nofollow\">
<picture>
<source srcset=\"/media/${FILENAME}.avif\" type=\"image/avif\">
<source srcset=\"/media/${FILENAME}.webp\" type=\"image/webp\">
<source srcset=\"/media/${FILENAME}.jpg\" type=\"image/jpeg\">
<img src=\"media/${FILENAME}.jpg\"
alt=\"preview image for YouTube video ID ${ID}\"
width=\"480\"
loading=\"lazy\">
</picture>
</a>
<figcaption>(${CAPTION})</figcaption>
</figure>" | pbcopy
yttget
It should run on any system that provides a POSIX-compliant shell,
and requires curl. Since I’m on a Mac I use
pbcopy to pipe standard output into the system’s clipboard,
but people using GNU/Linux or BSD can easily replace it with xclip or
xsel. Hell, you could probably replace
curl with wget if you wanted to, but I
couldn’t be bothered.
Using yttget
Here’s how you use yttget. (Don’t forget to replace the
URL unless you really like Black Sabbath.)
- Navigate to the directory in which you want to place the thumbnail.
- Type
yttget "https://www.youtube.com/watch?v=o0W91FrTlYk"3 - Paste the resulting HTML into your editor.
The script generates HTML, particularly a
<picture> element wrapped inside a
<figure>. You should edit this to taste, especially
if you don’t want to deal with generating WEBP and AVIF files from JPEG
images. You can paste it directly into a HTML or Markdown file. You can
also use this with Org mode in GNU Emacs, but you’ll need to
wrap it in a #+BEGIN_EXPORT html block. You should also add
text inside the <figcaption> for your readers’
benefit.
Once you do, it should look like something like this when rendered.
The link has rel="noreferrer noopener nofollow" for security and SEO reasons.
The first two, noreferrer and noopener,
mitigate exploits involving the JavaScipt function
window.open(). The use of nofollow means that
I’m not giving YouTube any “link juice”, which it shouldn’t need anyway
because it’s user-generated content and Google owns it.
Getting yttget
You can grab a copy here. It’s available under the zero-clase BSD license.
Tools Used in yttget
curl(tutorial)cut(manual page)echo(manual page)
Extra: Generating Alternate Image Formats
If you want to use the <picture> element to serve
more modern image formats like WEBP and AVIF, you’ll need to generate
these formats from the JPEG you downloaded from YouTube. You can do this
with ImageMagick, which provides a suite of
command-line image processing tools. The patch looks something like
this:
diff --git a/media/yttget.sh b/Users/starbreaker/bin/yttget
index a692369..beb2458 100755
--- a/media/yttget.sh
+++ b/Users/starbreaker/bin/yttget
@@ -21,11 +21,16 @@ ID=$(echo $URL | cut -d = -f 2)
FILENAME="youtube-${ID}"
CWD=$(pwd)
JPG="${CWD}/${FILENAME}.jpg"
+WEBP="${CWD}/${FILENAME}.webp"
+AVIF="${CWD}/${FILENAME}.avif"
THUMB_URL="http://i3.ytimg.com/vi/${ID}/hqdefault.jpg"
CAPTION="click to view"
curl ${THUMB_URL} --output ${JPG}
+magick -quality 80 ${JPG} ${WEBP}
+magick -quality 80 ${JPG} ${AVIF}
+
echo "<figure>
<a href=\"https://www.youtube.com/watch?v=${ID}\"
title=\"${CAPTION}\"
yttget for image conversion
You need not do your image conversion piecemeal, of course. If you have some experience in writing and editing makefiles and you’re using one to build and deploy your website, it’s easy to implement batch conversion. I did it myself when customizing the makefile in my copy of pblog.
This includes GNU/Linux, the various BSD operating systems, and macOS↩︎
It might not be the best name for a shell script in history, but it made sense to me at the time. You can name your copy whatever you want.↩︎
I have the URL in quotes because the invocation without quotes doesn’t work in my Mac’s version of
zsh. Other shells may not require this.↩︎