2012-03-30 139 views
1

我想要从与FFMPEG一个视频中提取的缩略图,因此我使用命令行:FFmpeg的视频缩略图帧提取

ffmpeg -i video.mp4 -vframes 1 -an -f image2 -y thumbmail.png 2>&1 

但在大多数情况下,第一帧是全黑。 所以,我在做什么是:

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; 
} 

凡isGoodKeyFrame方法定义为:

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; 
} 

所以基本上我在做什么是捕获1〜MAX_FRAME_CHECKING帧,检查其颜色直方图当我发现颜色比我的最低阈值还要多时,我会打断循环并返回该帧。

有没有办法与ffmpeg本地做到这一点?

谢谢

回答

1

不是我所知道的。我认为最简单的解决方案之一是使用-ss命令来寻找一个提取缩略图的位置。

每ffmpeg的文档:

“-ss位置(输入/输出)” 当作为(前-I)的输入选项一起使用,寻求在该输入文件到位置。当用作输出选项时(在输出文件名之前),解码但丢弃输入,直到时间戳到达位置。这比较慢,但更准确。

位置可以是在几秒钟内或在HH:MM:SS [.XXX]形式。

+0

好吧,我不能肯定,在位置X有一个非黑帧,所以我想我的解决方案是更好的现在:( – 2012-03-30 13:26:09

+0

除非你提取框架,你可以使用一个库,以检查在像素图像来查看它是否全黑,然后如果是,则选择不同的帧号,否则使用该帧。 – SB2017 2012-07-01 11:41:00