5

For Wordpress, I want to auto generate thumb of the video embedded on a page using oembed? And then save it as a featured image of the post.

Any idea how to do this?

1
  • 3
    oEmbed of what? YouTube?
    – kaiser
    Commented Oct 28, 2012 at 19:38

2 Answers 2

9
+50

I needed just this for a recent project, so here's my plugin! The code should be self-explanatory, but if there are any questions ask away.

<?php

/**
 * Plugin Name: oEmbed Featured Image
 * Plugin URI: http://wordpress.stackexchange.com/q/70752/1685
 * Description: Automatically set the featured image if an oEmbed-compatible embed is found in the post content.
 * Version: 1.0
 * Author: TheDeadMedic
 * Author URI: http://wordpress.stackexchange.com/users/1685/thedeadmedic
 *
 * @package oEmbed_Featured_Image
 */

add_action( 'wp_insert_post', array( 'ofi', 'init' ) );

/**
 * @package oEmbed_Featured_Image
 */
class ofi
{
    /**
     * The post thumbnail ID
     *
     * @var int
     */
    private $_thumb_id;

    /**
     * The post ID
     *
     * @var int
     */
    private $_post_id;

    /**
     * Sets up an instance if called statically, and attempts to set the featured
     * image from an embed in the post content (if one has not already been set).
     *
     * @param  int $post_id
     * @return object|null
     */
    public function init( $post_id )
    {
        if ( ! isset( $this ) )
            return new ofi( $post_id );

        global $wp_embed;

        $this->_post_id = absint( $post_id );

        if ( ! $this->_thumb_id = get_post_meta( $this->_post_id, '_thumbnail_id', true ) ) {
            if ( $content = get_post_field( 'post_content', $this->_post_id, 'raw' ) ) {

                add_filter( 'oembed_dataparse', array( $this, 'oembed_dataparse' ), 10, 3 );
                $wp_embed->autoembed( $content );
                remove_filter( 'oembed_dataparse', array( $this, 'oembed_dataparse' ), 10, 3 );

            }
        }
    }

    /**
     * @see init()
     */
    public function __construct( $post_id )
    {
        $this->init( $post_id );
    }

    /**
     * Callback for the "oembed_dataparse" hook, which will fire on a successful
     * response from the oEmbed provider.
     *
     * @see WP_oEmbed::data2html()
     *
     * @param string $return The embed HTML
     * @param object $data   The oEmbed response
     * @param string $url    The oEmbed content URL
     */
    public function oembed_dataparse( $return, $data, $url )
    {
        if ( ! empty( $data->thumbnail_url ) && ! $this->_thumb_id ) {
            // if ( in_array( @ $data->type, array( 'video' ) ) ) // Only set for video embeds
                $this->set_thumb_by_url( $data->thumbnail_url, @ $data->title );
        }
    }

    /**
     * Attempt to download the image from the URL, add it to the media library,
     * and set as the featured image.
     *
     * @see media_sideload_image()
     *
     * @param string $url
     * @param string $title Optionally set attachment title
     */
    public function set_thumb_by_url( $url, $title = null )
    {
        /* Following assets will already be loaded if in admin */
        require_once ABSPATH . 'wp-admin/includes/file.php';
        require_once ABSPATH . 'wp-admin/includes/media.php';
        require_once ABSPATH . 'wp-admin/includes/image.php';

        $temp = download_url( $url );

        if ( ! is_wp_error( $temp ) && $info = @ getimagesize( $temp ) ) {
            if ( ! strlen( $title ) )
                $title = null;

            if ( ! $ext = image_type_to_extension( $info[2] ) )
                $ext = '.jpg';

            $data = array(
                'name'     => md5( $url ) . $ext,
                'tmp_name' => $temp,
            );

            $id = media_handle_sideload( $data, $this->_post_id, $title );
            if ( ! is_wp_error( $id ) )
                return update_post_meta( $this->_post_id, '_thumbnail_id', $this->_thumb_id = $id );
        }

        if ( ! is_wp_error( $temp ) )
            @ unlink( $temp );
    }
}

?>

Caveat: This will only work for registered oEmbed providers, and only if no embed handler is registered for the provider (otherwise WP never makes a call to its oEmbed service).

If there are multiple embeds in a post, the first successful thumbnail grab is used.

3
  • Awesome, works a treat! Cool filter as well, oembed_dataparse :)
    – brasofilo
    Commented Nov 5, 2012 at 18:21
  • Awesome, this worked great. Thanks. Is there any way to assign same post a tag of video upon saving using the same? All though this answers my question, and works best.. why don't you publish this as plugin?
    – Krunal
    Commented Nov 6, 2012 at 16:01
  • Tags aren't part of the oEmbed spec, so 'fraid not. I don't have the time to officially publish it, but anyone else is free to do so (under the CC BY-SA 3.0 & GPL). Commented Nov 6, 2012 at 17:02
2

Interesting Question, but quoting Mike Schinkel answering a similar Q:

You could hook the save_post action, use WP_Http class to download it and then insert it as an attachment using wp_insert_attachment and wp_update_attachment_metadata(). It's not trivial but shouldn't be that hard.

My emphasis.

In another Q, Milo and Chris_O posted some useful info to deal with extracting an image URL from the content, attaching it to the post and setting it as Featured Image.

Which brings us to Kaiser's comment: what oEmbed is this?

If it is YouTube, this would be the full size thumbnail URL:
http://i3.ytimg.com/vi/YOUTUBE-VIDEO-ID/0.jpg

If Vimeo: https://stackoverflow.com/q/1361149/1287812


Instead of searching the post content each time it's updated/saved, I'd follow this approach:

Create a Metabox with an Input Field for the Video ID

Maybe, one input field per video hosting site. And a correspondent button "Grab thumbnail".

So, the user enters the YouTube/Vimeo video ID, press the button and we execute the side loading, attaching and featuring functions through Ajax.

In this Question ( Unattaching images from a post ), I wrote a plugin that creates a metabox where an Ajax function manipulates the attachments of a post.


Well, this is a roadmap, feel free to expand into working code :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.