Thursday, April 21, 2016

Getting thumbnail images for the most popular embedded video providers out there

Various video provider logos During one revamp of the blog I realized that I didn't have images for some of my posts. I had counted pretty much on the Blogger system that provides a post.thumbnailUrl post metadata that I can use in the display of the post, but the url is not always there. Of course if you have a nice image in the post somewhere prominently displayed, the thumbnail URL will be populated, but what if you have a video? Surprisingly, Blogger has a pretty shitty video to thumbnail mechanism that prompted me to build my own.

So the requirements would be: get me the image representing a video embedded in my page, using Javascript only.

Well, first of all, videos can be actual video tags, but most of the time they are iframe elements coming from a reliable global provider like YouTube, Dailymotion, Vimeo, etc, and all the information available is the URL of the display frame. Here is the way to get the thumbnail for these scenarios:

YouTube


Given the iframe src value:

// find youtube.com/embed/[videohash] or youtube.com/embed/video/[videohash]
var m = /youtube\.com\/embed(?:\/video)?\/([^\/\?]+)/.exec(src);
if (m) {
    // the thumbnail url is https://img.youtube.com/vi/[videohash]/0.jpg
    imgSrc = 'https://img.youtube.com/vi/' + m[1] + '/0.jpg';
}

If you have embeds in the old object format, it is best to replace them with the iframe one. If you can't change the content, it remains your job to create the code to give you the thumbnail image.

Dailymotion


Given the iframe src value:

//find dailymotion.com/embed/video/[videohash]
var m=/dailymotion\.com\/embed\/video\/([^\/\?]+)/.exec(src);
if (m) {
    // the thumbnail url is at the same URL with `thumbnail` replacing `embed`
    imgSrc=src.replace('embed','thumbnail');
}

Vimeo


Vimeo doesn't have a one URL thumbnail format that I am aware of, but they have a Javascript accessible API.

// find vimeo.com/video/[videohash]
m=/vimeo\.com\/video\/([^\/\?]+)/.exec(src);
if (m) {
    // set the value to the videohash initially
    imgSrc=m[1];
    $.ajax({
        //call the API video/[videohash].json
        url:'https://vimeo.com/api/v2/video/'+m[1]+'.json',
        method:'GET',
        success: function(data) {
            if (data&&data.length) {
                // and with the data replace the initial value with the thumbnail_medium value
                replaceUrl(data[0].thumbnail_medium,m[1]);
            }
        }
    });
}

In this example, the replaceUrl function would look for img elements to which the videohash value is attached and replace the url with the correct one, asynchronously.

TED


I am proud to announce that I was the one pestering them to make their API available over Javascript.

// find ted.com/talks/[video title].html
m=/ted\.com\/talks\/(.*)\.html/.exec(src);
if (m) {
    // associate the video title with the image element
    imgSrc=m[1];
    $.ajax({
        // call the oembed.json?url=frame_url
        url:'https://www.ted.com/services/v1/oembed.json?url='+encodeURIComponent(src),
        method:'GET',
        success: function(data) {
            // set the value of the image element asynchronously
            replaceUrl(removeSchemeForHttpsEnabledSites(data.thumbnail_url),m[1]);
        }
    });
    return false;
}

video tags


Of course there is no API to get the image from an arbitrary video URL, but the standard for the video tag specifies a poster attribute that can describe the static image associated with a video.

// if the element is a video with a poster value
if ($(this).is('video[poster]')) {
    // use it
    imgSrc=$(this).attr('poster');
}

0 comments: