WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

The plugin "Video Embed & Thumbnail Generator" does a great job of generating thumbnails from videos. It saves the thumbnail URL as metadata for the attachment. The thumbnail gets added to the uploads directory. Is there a way to take this image and add it to the media library so i can pass the image through the image_downsize function to create thumbnail of a different size?

wp_insert_attachment looks like it needs a path to a file and not a URL, or am i mistaken? how can i add a URL to the media library?

this is possibly a duplicate of How can I get an image from the uploads dir and enter it in the media library? but that never got any answers.

share|improve this question

If the image is in the content source you can extract it and use media_sideload_image(); to import it into the media library.

This code sample is from my plugin Media Tools. Which has does this via a admin page via ajax. It also sets the extracted image as the featured image for the post. The post id is being passed to this function via ajax. To look at the complete code see: http://plugins.trac.wordpress.org/browser/media-tools/trunk/media-tools.php?rev=581988

   function process_image( $post_id ) {
        $response = '';
        $error = 0;
        $post = get_post( $post_id );
        $img = $this->extract_image( $post );
        if( empty( $img ) ) {
            $response .=  'No images found <br>';
            die( sprintf( $response . '<br>Media tool complete (Post ID %1$s) in %2$s seconds. %3$d errors', esc_html( $post->ID ), timer_stop(), $error = $error  > 0 ? $error : 'no' ) );
        /** @var $file string or WP_Error of image attached to the post  */
        $file = media_sideload_image( $img, (int)$post->ID );
        if ( is_wp_error( $file ) ) {
            $response .= '<span style="color:red">Upload Error: Could not upload image. Check for malformed img src url</span><br>';
        } else {

         $atts = $this->get_attach( $post->ID );
         foreach ( $atts as $a ) {
             $img = set_post_thumbnail( $post->ID, $a['ID'] );
             if ( $img ) {
                  $thumb = wp_get_attachment_thumb_url( $a['ID'] );
                  $response .= '<img src="'.esc_url( $thumb ).'" /><br>';
                  $response .= '<a href="'.wp_nonce_url( get_edit_post_link( $a['ID'], true ) ).'" >'.get_the_title( $a['ID'] ).'</a>  Set as Featured Image</p><br>';
                    unset( $atts );
                    unset( $a );
            die( sprintf( $response.'<br>Media tool complete (Post ID %1$s) in %2$s seconds. %3$d errors', esc_html( $post->ID ), timer_stop(), $error = $error > 0 ? $error : 'no' ) );

     * Extracts the first image in the post content
     * @param object $post the post object
     * @return bool|string false if no images or img src
    function extract_image( $post ) {
        $html = $post->post_content;
        if ( stripos( $html, '<img' ) !== false ) {
            $regex = '#<\s*img [^\>]*src\s*=\s*(["\'])(.*?)\1#im';
            preg_match( $regex, $html, $matches );
            unset( $regex );
            unset( $html );
            if ( is_array( $matches ) && ! empty( $matches ) ) {
                return  $matches[2];

            } else {
                return false;
        } else {
            return false;

     * Queries for attached images
     * @param int $post_id The post id to check if attachments exist
     * @return array|bool The 1st attached on success false if no attachments
    function get_attach( $post_id ) {
        return get_children( array (
                'post_parent'    => $post_id,
                'post_type'      => 'attachment',
                'post_mime_type' => 'image',
                'posts_per_page'  => (int)1
            ), ARRAY_A );
share|improve this answer
media_sideload_image() looks promising, but how do you retrieve the attachment ID for the sideloaded image? – helgatheviking Sep 6 '12 at 18:41
Look at the get_attach function. It runs after media_sideload_image. – Chris_O Sep 6 '12 at 19:00
do you mean get_attachment? that needs the id which i don't yet have. i'm going to take a look at media_handle_sideload() – helgatheviking Sep 6 '12 at 19:32
also media sideload isn't quite right b/c it duplicates images that are already in the wp-uploads folder (where the video embedder plugin is adding them) – helgatheviking Sep 6 '12 at 19:58
Well the video embedder should be adding them to your media library then instead of just dumping them in your uploads dir. – Chris_O Sep 6 '12 at 21:11
up vote 1 down vote accepted

here are the pertinant parts that i changed from the kg_video_attachment_fields_to_save() function which filters attachment_fields_to_save:

    $thumb_url = $attachment['kgflashmediaplayer-poster'];

    //insert the $thumb_url into the media library if it does not already exist
    if ( ! ($thumb_id = get_attachment_id_from_src( $thumb_url ) ) ) {

        $post_id = $post['ID'];
        $desc = $attachment['post_title'] . ' thumbnail';

        //is image in uploads directory?
        $upload_dir = wp_upload_dir();

        if ( FALSE !== strpos( $url, $upload_dir['baseurl'] ) ) {
            $wp_filetype = wp_check_filetype(basename($thumb_url), null );
            $filename = preg_replace('/\.[^.]+$/', '', basename($thumb_url));

            $attachment = array(
               'guid' => $thumb_url, 
               'post_mime_type' => $wp_filetype['type'],
               'post_title' => $desc,
               'post_content' => '',
               'post_status' => 'inherit'
            $thumb_id = wp_insert_attachment( $attachment, basename($thumb_url), $post_id );
            // you must first include the image.php file
            // for the function wp_generate_attachment_metadata() to work
            require_once(ABSPATH . 'wp-admin/includes/image.php');
            $attach_data = wp_generate_attachment_metadata( $thumb_id, basename($thumb_url) );
            wp_update_attachment_metadata( $thumb_id, $attach_data );
        } else { //not in uploads so we'll have to sideload it
            $tmp = download_url( $thumb_url );

            // Set variables for storage
            // fix file filename for query strings
            preg_match('/[^\?]+\.(jpg|JPG|jpe|JPE|jpeg|JPEG|gif|GIF|png|PNG)/', $thumb_url, $matches);
            $file_array['name'] = basename($matches[0]);
            $file_array['tmp_name'] = $tmp;

            // If error storing temporarily, unlink
            if ( is_wp_error( $tmp ) ) {
                $file_array['tmp_name'] = '';

            // do the validation and storage stuff
            $thumb_id = media_handle_sideload( $file_array, $post_id, $desc );

            // If error storing permanently, unlink
            if ( is_wp_error($thumb_id) ) {
                return $thumb_id;

            if ( $local_src = wp_get_attachment_url( $thumb_id ) ) {
                update_post_meta($post['ID'], '_kgflashmediaplayer-poster', $local_src);

        } //end sideload

    } //end get_attachment_id_from_src

    if(!is_wp_error($thumb_id)) {
        $thumb_id = intval( $thumb_id );
        update_post_meta($post['ID'], '_kgflashmediaplayer-poster-id', $thumb_id);

and the video's custom thumbnail ID is now stored in the meta field: _kgflashmediaplayer-poster-id

function get_attachment_id_from_src ($image_src) {
    global $wpdb;

    $query = "SELECT ID FROM {$wpdb->posts} WHERE guid='$image_src'";
    $id = $wpdb->get_var($query);
    return $id;


i do not love the get_attachment_id_from_src() but there is no built-in way to do this. i should add in a check so that if the current src is the same as the old source, this query won't need to run. the embedder plugin creates many potential thumbnails for each video and there is no need to insert them all into the media library.... so this fires whenever a media attachment is saved and should cover images that are already in the media library, images that are in the media directory but not in the library and images on other servers (which get sideloaded in, and the URL is adjusted to the new local url)

share|improve this answer
Wonderfull Function... needed a bit of tweeking but worked gr8 for my needs ;) – Sagive SEO Sep 28 '15 at 23:22
Since this is 3 years old, I'd assume there is a much better way to do this now. – helgatheviking Sep 29 '15 at 9:17
still worked for me - which is all i needed ;) - a fast, ready to go detailed code. thanks. – Sagive SEO Oct 1 '15 at 4:55

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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