Automatic video thumbnail creation (Requires ffmpeg) Automatic video thumbnail creation (Requires ffmpeg)
 

News:

cpg1.5.48 Security release - upgrade mandatory!
The Coppermine development team is releasing a security update for Coppermine in order to counter a recently discovered vulnerability. It is important that all users who run version cpg1.5.46 or older update to this latest version as soon as possible.
[more]

Main Menu

Automatic video thumbnail creation (Requires ffmpeg)

Started by Abbas Ali, November 24, 2006, 11:56:30 AM

Previous topic - Next topic

0 Members and 2 Guests are viewing this topic.

Abbas Ali

This mod requires ffmpeg pre-installed and working on your server. Please DO NOT ask for support on installing or configuring ffmpeg. If you don't have ffmpeg or can't install ffmpeg on your server then this mod is not meant for you.

What will this mod do?
This mod will create thumbnail from the uploaded video file automatically on the fly. Thumbnails will be placed in the directory where the videos are uploaded/batch added. Though ffmpeg supports many video formats but i am unsure about wmv. File formats which i tested were avi, mpg, asf, flv.

Edit include/picmgmt.inc.php

Add


/**
* Function to create video thumbnail using ffmpeg
*/
function create_movie_thumb($src_file)
{
    global $CONFIG, $ERROR;

    $CONFIG['ffmpeg_path'] = '/usr/local/bin/'; // Change the path according to your server.

    $src_file = $src_file;
    $dest_file = $CONFIG['fullpath']."edit/".md5(uniqid(time()))."%d.jpg";

    if (preg_match("#[A-Z]:|\\\\#Ai", __FILE__)) {
        // get the basedir, remove '/include'
        $cur_dir = substr(dirname(__FILE__), 0, -8);
        $src_file = '"' . $cur_dir . '\\' . strtr($src_file, '/', '\\') . '"';
        $ff_dest_file = '"' . $cur_dir . '\\' . strtr($dest_file, '/', '\\') . '"';
    } else {
        $src_file = escapeshellarg($src_file);
        $ff_dest_file = escapeshellarg($dest_file);
    }

    $output = array();

    if (eregi("win",$_ENV['OS'])) {
        // Command to create video thumb
        $cmd = "\"".str_replace("\\","/", $CONFIG['ffmpeg_path'])."ffmpeg\" -i ".str_replace("\\","/" ,$src_file )." -an -ss 00:00:05 -r 1 -vframes 1 -y ".str_replace("\\","/" ,$ff_dest_file);
        exec ("\"$cmd\"", $output, $retval);
    } else {
        // Command to create video thumb
        $cmd = "{$CONFIG['ffmpeg_path']}ffmpeg -i $src_file -an -ss 00:00:05 -r 1 -vframes 1 -y $ff_dest_file";
        exec ($cmd, $output, $retval);
    }


    if ($retval) {
        $ERROR = "Error executing FFmpeg - Return value: $retval";
        if ($CONFIG['debug_mode']) {
            // Re-execute the command with the backtick operator in order to get all outputs
            // will not work if safe mode is enabled
            $output = `$cmd 2>&1`;
            $ERROR .= "<br /><br /><div align=\"left\">Cmd line : <br /><span style=\"font-size:120%\">" . nl2br(htmlspecialchars($cmd)) . "</span></div>";
            $ERROR .= "<br /><br /><div align=\"left\">The ffmpeg program said:<br /><span style=\"font-size:120%\">";
            $ERROR .= nl2br(htmlspecialchars($output));
            $ERROR .= "</span></div>";
        }
        @unlink($dest_file);
        return false;
    }

    $return = str_replace("%d", "1", $dest_file);
    @chmod($return, octdec($CONFIG['default_file_mode'])); //silence the output in case chmod is disabled
    return $return;
}


just before


// Add a picture to an album
function add_picture($aid, $filepath, $filename, $position = 0, $title = '', $caption = '', $keywords = '', $user1 = '', $user2 = '', $user3 = '', $user4 = '', $category = 0, $raw_ip = '', $hdr_ip = '', $iwidth = 0, $iheight = 0)


In above code change $CONFIG['ffmpeg_path'] value to where ffmpeg is installed on your server.

Add


    } elseif (is_movie($image)) {
      preg_match("/(.+)\.(.*?)\Z/", $filename, $matches);
      $thumb = $CONFIG['fullpath'] . $filepath . $CONFIG['thumb_pfx'] . $matches[1].".jpg";
      $videoThumb = create_movie_thumb($image);
      if ($videoThumb) {
        if (!resize_image($videoThumb, $thumb, $CONFIG['thumb_width'], $CONFIG['thumb_method'], $CONFIG['thumb_use'])) {
          return false;
        }
        @unlink($videoThumb);
        $imagesize = getimagesize($thumb);
      } else {
        return false;
      }


just before


    } else {
        $imagesize[0] = $iwidth;
        $imagesize[1] = $iheight;
    }


That's it, only one file to be modified.


Few Notes

  • The mod works best on linux servers
  • If you have Dreamhost as your webhost then this might help you
  • The dreamhost installation way might work on other shared servers too but not sure. Give it a try.
  • If you have a dedicated server then ffmpeg will not be that difficult for your webhost to install
Chief Geek at Ranium Systems

jape

Why not working .flv videos???
Thumnail name is problems...

I trying upload video.FLV

but...

Thumb location is:
/gallery/images/thumb_FLV.jpg


Not Found

The requested URL /galleria/images/thumb_FLV.jpg was not found on this server.


jape


jape

ahaa....  :D
This donĀ“t working thumbnails: video.FLV
This working: video.flv

Abbas Ali

Not sure why that's happening but ffmpeg might not be able to create thumbs with capitalized extension. Better always use lower case extensions.
Chief Geek at Ranium Systems

adrianbj

Hey Abbas,

Fantastic Hack - thanks.

I did notice one thing though. If you want the dimensions of the movie to be properly collected, you need to change

    } elseif (is_movie($image)) {
      preg_match("/(.+)\.(.*?)\Z/", $filename, $matches);
      $thumb = $CONFIG['fullpath'] . $filepath . $CONFIG['thumb_pfx'] . $matches[1].".jpg";
      $videoThumb = create_movie_thumb($image);
      if ($videoThumb) {
        if (!resize_image($videoThumb, $thumb, $CONFIG['thumb_width'], $CONFIG['thumb_method'], $CONFIG['thumb_use'])) {
          return false;
        }
        @unlink($videoThumb);
        $imagesize = getimagesize($thumb);
      } else {
        return false;
      }


to:

    } elseif (is_movie($image)) {
      preg_match("/(.+)\.(.*?)\Z/", $filename, $matches);
      $thumb = $CONFIG['fullpath'] . $filepath . $CONFIG['thumb_pfx'] . $matches[1].".jpg";
      $videoThumb = create_movie_thumb($image);
      $imagesize = getimagesize($videoThumb);
      if ($videoThumb) {
        if (!resize_image($videoThumb, $thumb, $CONFIG['thumb_width'], $CONFIG['thumb_method'], $CONFIG['thumb_use'])) {
          return false;
        }
        @unlink($videoThumb);
        } else {
        return false;
      }


Note that I have removed your getimagesize line and replaced it further up in the code and changed the variable from $thumb to $videoThumb

The way you had it, it always grabbed the dimensions of the thumbnail, rather than the actual fullsize video.

I also commented out these lines in upload.php:

        //Add width and height boxes to the form.
        //$form_array[] = array($lang_admin_php['th_wd'],'movie_wd', 0, 4, 1); //no longer needed since dimensions of movies are grabbed automatically
        //$form_array[] = array($lang_admin_php['th_ht'],'movie_ht', 0, 4, 1); //no longer needed since dimensions of movies are grabbed automatically


because it is no longer necessary for the user to enter the movie dimensions manually.

Thanks again,
Adrian

adrianbj


Abbas Ali

Chief Geek at Ranium Systems

adrianbj

#8
No problem,

Here is another addition to ensure that the thumbnail is deleted along with movie if a delete takes place.

In the file delete.php

Add this:

//Added by AJ to delete thumb and preview versions for movies
$file_normal = $CONFIG['normal_pfx'] . $file;
$file_thumb = $CONFIG['thumb_pfx'] . $file;

if(is_movie($file)){
$path_parts = pathinfo($file);
$file_ext = '.' . $path_parts['extension'];
$file_normal = str_replace($file_ext, ".jpg", $file_normal);
$file_thumb = str_replace($file_ext, ".jpg", $file_thumb);
}
//


directly after these lines:

    $aid = $pic['aid'];
    $dir = $CONFIG['fullpath'] . $pic['filepath'];
    $file = $pic['filename'];



Change this:

$files = array($dir . $file, $dir . $CONFIG['normal_pfx'] . $file, $dir . $CONFIG['thumb_pfx'] . $file);


to this:

$files = array($dir . $file, $dir . $file_normal, $dir . $file_thumb); // Modified by AJ - changed links to normal and thumb version to grab corrected links for movies and special images etc

That's it!

adrianbj

Here's another addition so you get to see the preview thumbnail during the upload process - really useful if you've uploaded several files and you're not sure which is which when you're entering the info about the movie.

In upload.php, add

    // Added by AJ for handling preview thumb for movie images
   } elseif(is_movie($file_set[1])) {
   
   
       $CONFIG['ffmpeg_path'] = '/usr/bin/'; // Change the path according to your server.

        // Create preview image file name.

        do {

            // Create a random seed by taking the first 8 characters of an MD5 hash of a concatenation of the current UNIX epoch time and the current server process ID.
            $seed = substr(md5(uniqid("")), 0, 8);

            // Assemble the file path.
$extension="jpg"; //change temp thumbsized preview file to a JPG
            $path_to_preview = './'.$CONFIG['fullpath'].'edit/preview_' . $seed . '%d.' . $extension;

        } while (file_exists($path_to_preview));

        // Create secure preview path.
        $s_preview_path = 'preview_' . $seed . '.' . $extension;

    $output = array();

        // The file is an image, we must resize it for a preview image.
        $cmd = "{$CONFIG['ffmpeg_path']}ffmpeg -i $path_to_image -an -ss 00:00:05 -r 1 -vframes 1 -s sqcif -y $path_to_preview";
        exec ($cmd, $output, $retval);


    if ($retval) {
        $ERROR = "Error executing FFmpeg - Return value: $retval";
        if ($CONFIG['debug_mode']) {
            // Re-execute the command with the backtick operator in order to get all outputs
            // will not work if safe mode is enabled
            $output = `$cmd 2>&1`;
            $ERROR .= "<br /><br /><div align=\"left\">Cmd line : <br /><span style=\"font-size:120%\">" . nl2br(htmlspecialchars($cmd)) . "</span></div>";
            $ERROR .= "<br /><br /><div align=\"left\">The ffmpeg program said:<br /><span style=\"font-size:120%\">";
            $ERROR .= nl2br(htmlspecialchars($output));
            $ERROR .= "</span></div>";
        }
        @unlink($path_to_preview);
        //return false;
    }
    // Set mode of uploaded picture
$path_to_preview = str_replace("%d", "1", $path_to_preview);
    @chmod($path_to_preview, octdec($CONFIG['default_file_mode'])); //silence the output in case chmod is disabled
    // We check that the image is valid
    $imginfo = getimagesize($path_to_preview);
    if ($imginfo == null) {
        $ERROR = $lang_errors['resize_failed'];
        @unlink($path_to_preview);
        //return false;
    } else {
        //return true;
    }


just before:

} else {

        // The file is not an image, so we will use the non-image thumbs
        // for preview images.

        // We create the path to the preview image.
        $path_to_preview = "images/thumb_{$extension}.jpg";

    }



The -s sqcif does the resizing. Unfortunately I can't work out how to resize proportionally using ffmpeg, so if you have a bunch of videos that are not in the standard aspect ratio, you might want to have ffmpeg create the screenshot at fullsize and then use an imagemagick resize command on it and do -resize 150x which will ensure the aspect ratio is not changed.

oscar_rocha

You can also overlap a "play this movie" image (jpeg,gif or png) to the videothumb (like in youtube) just adding in picmgmt.inc.php:

After:
$return = str_replace("%d", "1", $dest_file);

Add:

   
/**************************************/
  $background = imagecreatefromjpeg($return);
  $insert = imagecreatefromgif($image_path);
  imagecolortransparent($insert,imagecolorat($insert,0,0));
  $insert_x = imagesx($insert);
  $insert_y = imagesy($insert);
  imagecopymerge($background,$insert,45,35,0,0,$insert_x,$insert_y,100);
  imagejpeg($background, $return, 100);
    /***************************************/


Where $image_path is the path to the image you want to overlap.

gldickens3

This is a great thread!

I downloaded ffmpg and got everything listed in this thread working perfectly except for this:

Quote from: oscar_rochaYou can also overlap a "play this movie" image (jpeg,gif or png) to the videothumb (like in youtube) just adding in picmgmt.inc.php:

After:
Code:

$return = str_replace("%d", "1", $dest_file);


Add:

Code:

   
/**************************************/
  $background = imagecreatefromjpeg($return);
  $insert = imagecreatefromgif($image_path);
  imagecolortransparent($insert,imagecolorat($insert,0,0));
  $insert_x = imagesx($insert);
  $insert_y = imagesy($insert);
  imagecopymerge($background,$insert,45,35,0,0,$insert_x,$insert_y,100);
  imagejpeg($background, $return, 100);
    /***************************************/


Where $image_path is the path to the image you want to overlap.

When I put the code into picmgmt.inc.php then I get the following error message when I try to "Batch add files":

Fatal error: Call to undefined function imagecreatefromjpeg() in /home/gajets/public_html/gallery/include/picmgmt.inc.php on line 78

How do I fix this problem so I don't get this undefined function error?  Is there other code that I need to be including?

Thanks,

Gordon Dickens

Nibbler

You need GD with JPEG support enabled. Check your phpinfo page.

gldickens3

Hi Nibbler,

Duh....

You hit the nail right on the head!  I had GD on my system but it wasn't included in my Apache compile so I recompiled Apache including GD which fixed the problem.  Thanks!

Now, the thumbnails are being generated, however, the overlay "play button" is not being included. So, my question is about:

Quote from: oscar_rochaWhere $image_path is the path to the image you want to overlap.

Should the file name path be relative to the root directory of the website or relative to the root directory of the coppermine installation?  That is, I put my overlay image in my themes directory.  So, which of the following paths would be correct for the code line: $insert = imagecreatefromgif($image_path);?

$image_path = gallery/themes/gordon_grey/playbutton.gif
or;
$image_path = themes/gordon_grey/playbutton.gif

Thanks,

Gordon

Abbas Ali

Quote from: gldickens3 on August 04, 2007, 02:51:34 PM
$image_path = gallery/themes/gordon_grey/playbutton.gif
or;
$image_path = themes/gordon_grey/playbutton.gif

Play safe and put the absolute path i.e. something like /home/username/public_html/gallery/themes/.... (if you are on linux server).
Btw: relative path from gallery folder should work
Chief Geek at Ranium Systems

gldickens3

Ali and Nibbler,

I've got it working now. I've just got to figure out how to properly center the overlay on my thumbnails.

Thanks for all your help.

Gordon

lifter

When I try to implement this mod, video uploads seize to work.

When I upload the file it says:

Successful Uploads
1 uploads were successful.

Please click 'Continue' to add the files to albums.

But after continuing and selecting an album and pressing continue again it says

"The previous file could not be placed.

You have successfully placed all the files."

Abbas Ali

First check whether normal video uploading (without the mod) is working or not. If that is working then it means ffmpeg is not working on your server.

Also turn on the debug mode to see the errors (if any).
Chief Geek at Ranium Systems

lifter

Video uploading works without the mod - it may be that ffmpegshow isnt installed - going to have to check with my host

Abbas Ali

Quote from: lifter on September 07, 2007, 06:56:40 AM
it may be that ffmpegshow isnt installed - going to have to check with my host

Thats the first thing to check for as my first post describes.
Chief Geek at Ranium Systems