Responsive Vimeo and Youtube embed in WordPress

By kristoffer,

  Filed under: Code, Wordpress
  Comments: Comments Off on Responsive Vimeo and Youtube embed in WordPress

A couple of days ago, i published a post on how to do responsive video embeds in a WordPress loaded with Bootstrap. This post is a continuation of that process. If you read the other post you might remember that getting the aspect ratio of the video is what I didn’t do. So, that is what I’ll do today – and it will lead to the best practice way to properly responsively embed videos in WordPress. The code relies on the CSS from the Bootstrap-component Responsive Embed – if you are not using Bootstrap, simply include that code in your CSS.

Starting with oEmbed

WordPress relies on oEmbed when embedding external video content onto your site.

oEmbed is a format for allowing an embedded representation of a URL on third party sites. The simple API allows a website to display embedded content (such as photos or videos) when a user posts a link to that resource, without having to parse the resource directly.

That’s pretty neat. The oEmbed code is contained within the file class-oembed.php. It handles oEmbed recognition, calls, processing and more. And within it is what we need to make the best responsive video embed for WordPress. On line 501 there is a function data2html that turns oEmbed data into html code. And the best part is that it applies a filter hook at the end,  apply_filters( 'oembed_dataparse', $return, $data, $url ). And it passes the oEmbed data to the filter – and that is what we need.

oEmbed data

So, what does this oEmbed data look like? Lets look at a couple of sample results from YouTube and Vimeo (click the links to see what the oEmbed call receives).

From Vimeo:

{
    "type": "video",
    "version": "1.0",
    "provider_name": "Vimeo",
    "provider_url": "https://vimeo.com/",
    "title": "Michael Jackson - Thriller",
    "author_name": "Michael Jackson",
    "author_url": "http://vimeo.com/user2691078",
    "is_plus": "0",
    "html": "<iframe src=\"\/\/player.vimeo.com\/video\/7806742\" width=\"624\" height=\"448\" frameborder=\"0\" title=\"Michael Jackson - Thriller\" webkitallowfullscreen mozallowfullscreen allowfullscreen><\/iframe>",
    "width": 624,
    "height": 448,
    "duration": 822,
    "description": "",
    "thumbnail_url": "http://i.vimeocdn.com/video/34694433_295x166.jpg",
    "thumbnail_width": 295,
    "thumbnail_height": 212,
    "video_id": 7806742,
    "uri": "/videos/7806742"
}

From YouTube:

{

    "provider_url": "http://www.youtube.com/",
    "title": "Ylvis - The Fox (What Does The Fox Say?) [Official music video HD]",
    "thumbnail_url": "http://i.ytimg.com/vi/jofNR_WkoCE/hqdefault.jpg",
    "thumbnail_width": 480,
    "author_name": "TVNorge",
    "height": 270,
    "version": "1.0",
    "thumbnail_height": 360,
    "width": 480,
    "author_url": "http://www.youtube.com/user/tvnorge",
    "provider_name": "YouTube",
    "html": "<iframe width=\"480\" height=\"270\" src=\"http://www.youtube.com/embed/jofNR_WkoCE?feature=oembed\" frameborder=\"0\" allowfullscreen><\/iframe>",
    "type": "video"
}

As seen, the response is pretty much the same. The important parts are the typewidth and height data. We can then calculate the aspect ratios, and they turn out to be 1.78:1 (or better known as 16:9) for the Vimeo video and 1.39:1 (close to either 7:5 ratio or the ISO paper size ratio sqrt(2):1 ) for the Youtube video.

WordPress filter for responsive embed

This is what we are going to do:

  1. Hook onto the oembed_dataparse filter hook.
  2. Verify that there are oEmbed data
  3. Decide on aspect ratio modifier
  4. Add a data attribute for the aspect ratio
  5. Return the code wrapped in the needed divs (as done in the previous post)

Please remember that we are still using the Bootstrap component Responsive Embed. Here goes the code (it belongs in functions.php. Follow the comments to see what happens.

// Hook onto 'oembed_dataparse' and get 2 parameters
add_filter( 'oembed_dataparse','responsive_wrap_oembed_dataparse',10,2);

function responsive_wrap_oembed_dataparse( $html, $data ) {
 // Verify oembed data (as done in the oEmbed data2html code)
 if ( ! is_object( $data ) || empty( $data->type ) )
 return $html;

 // Verify that it is a video
 if ( !($data->type == 'video') )
 return $html;

 // Calculate aspect ratio
 $ar = $data->width / $data->height;

 // Set the aspect ratio modifier
 $ar_mod = ( abs($ar-(4/3)) < abs($ar-(16/9)) ? 'embed-responsive-4by3' : 'embed-responsive-16by9');

 // Strip width and height from html
 $html = preg_replace( '/(width|height)="\d*"\s/', "", $html );

 // Return code
 return '<div class="embed-responsive '.$ar_mod.'" data-aspectratio="'.number_format($ar, 5, '.').'">'.$html.'</div>';
}

NOTE: Cached embeds

So, turns out that the oEmbed html is cached by WP. This makes sense – we don’t want to ask for and process oEmbed data for every page call. So, for now, you have to update all posts/pages that has oEmbed to cache the new data.

A little jQuery magic

Since I’ve passed the aspect ratio as a data-attribute to the wrapping div, we can use jQuery to set the aspect ratio to match perfectly. Use this little jQuery snippet.

$( function() {
 // Run code for each element
 $('.embed-responsive').each( function (){

 // Get ar
 var ar = $(this).attr('data-aspectratio');

 // Check for existance and set padding-bottom
 if (typeof ar !== typeof undefined && ar !== false ) {
   $(this).css('padding-bottom', (1/ar)*100+'%');
 }

 });
});

Results

Here is the result from Youtube.

And Vimeo

https://vimeo.com/7806742

Pretty neat, huh?