How to Download a Video Thumbnail and Set as the Featured Image

One feature that hasn’t made it into WordPress yet, is the ability to use external images as a Featured Image. I don’t know if it will ever become a feature, so in the mean time, I wrote this plugin. There are certainly other plugins that are more robust, like Video Thumbnails — I am making this code available simply because I found it useful and I’m hoping someone else will find it useful as well.

There are a few plugins out there that manage to do the same thing, but I had a particular need. Wistia.

So when I set out to write this code, I had one process goal in mind: Embed a video, download the thumbnail, associate that thumbnail with said post, and finally set it as the featured image.

Let’s dive into the code and look at some example inputs.

The Code

<?php
/*
Plugin Name: Video Thumbnail Auto-Feature
Plugin URI: http://wpforce.com
Description: Little 'o plugin I wrote
Version: 1.0
Author: Jonathan Dingman
Author URI: http://wpforce.com
License: GPLv2 or later
*/
	
function autoThumb( $post_id ) {
global $post;
if ( !$post ) { $post = get_post($post_id); }
if ( get_post_meta( $post_id, 'no_thumb', 1 ) ) return; // Don't set the thumbnail? check.


	if ($post) {
	
		$post_id = $post->ID; 

		if ( !has_post_thumbnail($post_id) ) {

			// Run match checks for specific video sources
			if ( preg_match("/youtube\.com\/(v\/|watch\?v=)([\w\-]+)/", $post->post_content) ) {
				preg_match("/youtube\.com\/(v\/|watch\?v=)([\w\-]+)/", $post->post_content, $match_id);
				$youtubeCheck = TRUE;
			}
			elseif ( preg_match("/stillUrl=(.*?)\.bin/", $post->post_content) ) {
				preg_match("/stillUrl=(.*?)\.bin/", $post->post_content, $match_id);
				$wistiaCheck = TRUE;
			}
            elseif ( preg_match('/guid=(.*?)(&amp;|")/', $post->post_content) ) {
	            preg_match('/guid=(.*?)(&amp;|")/', $post->post_content, $match_id);
	            $wptvCheck = TRUE;
            }

		if  ( $match_id ) {
		
			// Ensure the specific URL is in the $match_id array so it can be used later
	
			if ($youtubeCheck) {
				$yt_id = $match_id[2];
				$match_id = array (1 => "http://img.youtube.com/vi/" . $yt_id . "/0.jpg");
			}
			elseif ($wistiaCheck) {
				$rename_id = $match_id[1];
				$match_id = array (1 => $rename_id . ".jpg");
			}
			elseif ($wptvCheck) {
				$url = "http://wordpress.tv/?feed=rss2&s=".$match_id[1];
				$urlResults = file_get_contents($url);
				preg_match('/<media:thumbnail url="(.*?)"/', $urlResults, $match_id);
			}
	
			// Setup the paths for the thumbnail
			$match_file_path = $match_id[1];
			$results = attach_image_url($match_file_path, $post_id, $post->post_name);

			} // end $match_id 
		}// end !has_post_thumbnail()
	} // end if $post		
} // end function autoThumb()

function attach_image_url($file, $post_id, $desc = null) {
    require_once(ABSPATH . "wp-admin" . '/includes/image.php');
    require_once(ABSPATH . "wp-admin" . '/includes/file.php');
    require_once(ABSPATH . "wp-admin" . '/includes/media.php');
    if ( ! empty($file) ) {
        // Download file to temp location
        $tmp = download_url( $file );
        // Set variables for storage
        // fix file filename for query strings
        preg_match('/[^\?]+\.(jpg|JPG|jpe|JPE|jpeg|JPEG|gif|GIF|png|PNG)/', $file, $matches);
		$file_array['name'] = basename($matches[0]);        
		$file_array['tmp_name'] = $tmp;
        // If error storing temporarily, unlink
        if ( is_wp_error( $tmp ) ) {
            @unlink($file_array['tmp_name']);
            $file_array['tmp_name'] = '';
        }
        // do the validation and storage stuff
        $id = media_handle_sideload( $file_array, $post_id, $desc );
        // If error storing permanently, unlink
        if ( is_wp_error($id) ) {@unlink($file_array['tmp_name']);}
        add_post_meta($post_id, '_thumbnail_id', $id, true);
    }
}

add_action('save_post', 'autoThumb');
add_action('draft_to_publish', 'autoThumb');
add_action('new_to_publish', 'autoThumb');
add_action('pending_to_publish', 'autoThumb');
add_action('future_to_publish', 'autoThumb');

Example Usage

The above code works with YouTube, WordPress.TV, and Wistia (full embeds — not the iFrame embed).

First example, Wistia:

<div id="wistia_be01c648af" style="width:640px;height:360px;" data-video-width="640" data-video-height="360"><object id="wistia_be01c648af_seo" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" style="display:block;height:100%;position:relative;width:100%;"><param name="movie" value="http://seomoz-cdn.wistia.com/flash/embed_player_v2.0.swf"></param><param name="allowfullscreen" value="true"></param><param name="allowscriptaccess" value="always"></param><param name="wmode" value="opaque"></param><param name="flashvars" value="videoUrl=http://seomoz-cdn.wistia.com/deliveries/97153182143cfa631408718f1b8d92aebdcdbf29.bin&&hdUrl=http://seomoz-cdn.wistia.com/deliveries/f93e23c2ade525b80323ac1797e9f62291187400.bin&stillUrl=http://seomoz-cdn.wistia.com/deliveries/36fd6b8358a8bf65a2a34e8026be42bf81034a8a.bin"></param><embed src="http://seomoz-cdn.wistia.com/flash/embed_player_v2.0.swf" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" wmode="opaque" flashvars="videoUrl=http://seomoz-cdn.wistia.com/deliveries/97153182143cfa631408718f1b8d92aebdcdbf29.bin&hdUrl=http://seomoz-cdn.wistia.com/deliveries/f93e23c2ade525b80323ac1797e9f62291187400.bin&stillUrl=http://seomoz-cdn.wistia.com/deliveries/36fd6b8358a8bf65a2a34e8026be42bf81034a8a.bin" style="display:block;height:100%;position:relative;width:100%;"></embed></object></div>
<script charset="ISO-8859-1" src="http://fast.wistia.com/static/E-v1.js"></script>
<script>//<![CDATA[
wistiaEmbed = Wistia.embed("be01c648af", {
  videoWidth: "640",
  videoHeight: "360",
  controlsVisibleOnLoad: true
});
//]]</script>

The important part to make sure is in the embed, is the stillUrl code.

Next, YouTube.

http://www.youtube.com/watch?v=k8F3UE9qFsg

Super simple. Just the URL will do because the regex doesn’t all the magic. WordPress will auto-embed it as a video as well, if you have it enabled.

<embed type="application/x-shockwave-flash" src="http://s0.videopress.com/player.swf?v=1.03" width="400" height="224" wmode="direct" seamlesstabbing="true" allowfullscreen="true" allowscriptaccess="always" overstretch="true" flashvars="guid=ZKb6X1Zg&amp;isDynamicSeeking=true"></embed>

This is a straight copy and paste from a WordPress.tv video. It uses the guid= to grab the thumbnail.

Credit and Thanks

Thanks to Michael Beckwith for some feedback and helping debug the code. The attach_image_url() code was borrowed from StackExchange.

I’m always open to suggestions if you know of a better way to write the code. So if you do have something to say, please let me know in the comments. I’ll update the code as necessary.

Comments

  1. By CaMaFiVe on

    hi thanks for the great plugin it works just good, but i have one question.

    i have wordpress youtube lyte in my site and the links to youtube embed videos i have to put them this way

    httpv://youtube.com/asdasdas

    with the “v” after the p, is there a way to make the plugin recognize that “v” to get the featured image?
    because with that v in the youtube link it doesn’t get the featured image.

    i have to write first the normal link without the b to get the featured image and then update with the v

    Reply »

    • By Jonathan Dingman on

      You would need to modify the preg_match for the YouTube check.

      Replace:

      if ( preg_match("/youtube\.com\/(v\/|watch\?v=)([\w\-]+)/", $post->post_content) ) {
      preg_match("/youtube\.com\/(v\/|watch\?v=)([\w\-]+)/", $post->post_content, $match_id);
      $youtubeCheck = TRUE;

      With…

      if ( preg_match("#httpv?://w?w?w?.?youtube.com/watch\?v=([A-Za-z0-9\-_]+)#s", $post->post_content) ) {
      preg_match("#httpv?://w?w?w?.?youtube.com/watch\?v=([A-Za-z0-9\-_]+)#s", $post->post_content, $match_id);
      $youtubeCheck = TRUE;

      That should work, I haven’t thoroughly tested it though.

      There is more information in this support thread about how to match for all Smart Youtube videos.

      Reply »

  2. By george on

    I tried this code and it is not working with me. I tried debugging and I got the following:
    Undefined variable: match_id in ……./public_html/wp-content/plugins/auto-featured-image-for-video-embed/embed-thumbnail.php on line 36
    Any Ideas what should I do?

    Reply »

  3. By nore on

    Hello,
    would it be possible to use this snippet with another VOD platform?
    I’m using VOD from infomaniak

    Reply »

  4. By on

    Hey, this is a great plugin! I’m trying to get it look for video URL in a custom field value, rather than post content. I’m guessing it’s somewhere at line 25-26, instead $post->post_content I should enter “something else”…
    Help is much appreciated!

    Reply »

Trackbacks

  1. […] Grand RapidsbbPress 2.1 RC1Contribute to the WordPress for iOS app/designTony’s pick: Download a video thumbnail and set as post thumbnailDre’s pick: Vote for PixeljarRyan’s pick: P2 Check InGet involved in future showsWe’ll be […]

Leave a Reply

Your email address will not be published. Required fields are marked *