Get Youtube video thumbnail image
Paste Youtube, Vimeo or Wistia video url to get the thumbnail image and oembed data #
Video thumbnail:
Makes request to:
Result:
How it works #
I often google “get youtube video thumbnail”.
Oembed let’s you get metadata and embed code for a media asset.
If a web page has <link rel="alternate" type="application/json+oembed" href="...">
, it means that the page supports oembed. The href is the oembed url. The first part of the url is the oembed API endpoint.
For example
<link rel="alternate" type="application/json+oembed" href="https://www.youtube.com/oembed?format=json&url=https://www.youtube.com/watch?v=vS-F1PlLyTk" title="Typesense search with Ruby on Rails #225">
means that the Youtube API endpoint is
https://www.youtube.com/oembed?format=json&url=
Vimeo (example url: https://vimeo.com/158115405
)
https://vimeo.com/api/oembed.json?url=
Wistia (example url: https://clickfunnels-28.wistia.com/medias/661x8p4j6u
)
https://fast.wistia.com/oembed?url=
At the end of the API endpoint append the url to the video to get the oembed data.
StimulusJS implementation #
// video_thumbnail_preview_controller.js
import { Controller } from '@hotwired/stimulus'
// <div data-controller="video-thumbnail-preview">
// <input
// data-video-thumbnail-preview-target="input"
// type="text"
// data-action="input->video-thumbnail-preview#fetchThumbnail"
// value="https://www.youtube.com/watch?v=RNaaODDtTLw"
// >
// <div data-video-thumbnail-preview-target="output"></div>
// </div>
// public vimeo video:
// https://vimeo.com/158115405
// https://vimeo.com/api/oembed.json?url=https://vimeo.com/158115405
// public youtube video:
// www.youtube.com/watch?v=944lk4JAdyg
// https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=944lk4JAdyg
// https://docs.wistia.com/docs/wistia-and-oembed
// public wistia video:
// https://clickfunnels-28.wistia.com/medias/661x8p4j6u
// https://fast.wistia.com/oembed?url=https://clickfunnels-28.wistia.com/medias/661x8p4j6u
export default class extends Controller {
static targets = ['input', 'output']
connect() {
this.fetchThumbnail()
}
outputTargetConnected() {
this.fetchThumbnail()
}
inputTargetConnected() {
this.fetchThumbnail()
}
inputTargetChanged() {
this.fetchThumbnail()
}
async fetchThumbnail() {
const url = this.inputTarget.value
if (!url) {
this.clearOutputs()
return
}
const videoProvider = this.detectVideoProvider(url)
if (!videoProvider) {
this.clearOutputs()
return
}
try {
const thumbnailUrl = await this.fetchOembedThumbnail(url, videoProvider)
if (thumbnailUrl) {
this.outputTargets.forEach((target) => {
target.innerHTML = `<img src="${thumbnailUrl}" alt="Video thumbnail">`
})
} else {
this.clearOutputs()
}
} catch (error) {
this.clearOutputs()
}
}
clearOutputs() {
this.outputTargets.forEach((target) => {
target.innerHTML = ''
})
}
detectVideoProvider(url) {
if (url.match(/youtu/)) return 'youtube'
if (url.match(/vimeo/)) return 'vimeo'
if (url.match(/wistia/)) return 'wistia'
return null
}
async fetchOembedThumbnail(url, provider) {
const endpoints = {
youtube: `https://www.youtube.com/oembed?url=${encodeURIComponent(
url
)}&format=json`,
vimeo: `https://vimeo.com/api/oembed.json?url=${encodeURIComponent(url)}`,
wistia: `https://fast.wistia.com/oembed?url=${encodeURIComponent(
url
)}&format=json`
}
const endpoint = endpoints[provider]
if (!endpoint) return null
const response = await fetch(endpoint)
if (!response.ok) return null
const data = await response.json()
return data.thumbnail_url
}
}
That’s it!
Did you like this article? Did it save you some time?