Reputation: 4733
i'm trying to extract a thumbnail from a video with ffmpeg, therefore i'm using the command line:
ffmpeg -i video.mp4 -vframes 1 -an -f image2 -y thumbmail.png 2>&1
But in most cases, the first frame is completely black. So, what i'm doing is :
for( $i = 1; $i < MAX_FRAME_CHECKING; $i++ )
{
$cmd = sprintf( 'ffmpeg -i video.mp4 -vframes 1 -an -vf select="eq(n\,%d)"-f image2 -y thumbmail.png 2>&1', $i );
@exec( $cmd, $aOutput, $iReturnValue );
if( self::isGoodKeyFrame( 'thumbmail.png' ) )
break;
}
Where the isGoodKeyFrame method is defined as:
private static function isGoodKeyFrame( $sImagePath )
{
if( class_exists('Imagick') )
{
$hImagick = new Imagick();
try
{
if ( $hImagick->readImage($sImagePath) && $hImagick->valid() )
{
$hQuantized = @$hImagick->clone( );
$hQuantized->quantizeImage( 255, Imagick::COLORSPACE_RGB, 0, TRUE, FALSE );
return count( $hQuantized->getImageHistogram() ) > self::HISTOGRAM_SIZE_THRESHOLD;
}
else
error_log( "'$sImagePath' is not a valid image." );
}
catch( Exception $e )
{
error_log( $e->getMessage() );
}
$hImagick->clear( );
$hImagick->destroy( );
}
else
error_log( 'Imagick not installed.' );
return TRUE;
}
So basically what i'm doing is capture 1 to MAX_FRAME_CHECKING frames, check their color histogram and when i find something with much colors than my minimum threshold i break the loop and return that frame.
Is there a way to do this natively with ffmpeg ?
Thanks
Upvotes: 1
Views: 2004
Reputation: 589
Not that I'm aware of. I think that one of the easiest solutions would be to use the -ss command to seek to a position to extract the thumbnail.
Per the ffmpeg documentation:
‘-ss position (input/output)’ When used as an input option (before -i), seeks in this input file to position. When used as an output option (before an output filename), decodes but discards input until the timestamps reach position. This is slower, but more accurate.
position may be either in seconds or in hh:mm:ss[.xxx] form.
Upvotes: 2