我正在尝试使用FFMPEG和FFMPEG-PHP扩展从电影中的随机点生成缩略图。
我的脚本运行正常..但是只需要20分钟就可以生成5-10个缩略图!!
该脚本的工作原理是生成随机数,以后用作帧数。生成的所有数字都在电影帧数内。
你能弄清楚为什么这个剧本需要20分钟才能完成吗? 如果没有,更好的解决方案?
<?php
//Dont' timeout
set_time_limit(0);
//Load the file (This can be any file - still takes ages)
$mov = new ffmpeg_movie('1486460.mp4');
//Get the total frames within the movie
$total_frames = $mov->getFrameCount();
//Loop 5-10 times to generate random frames 5-10 times
for ($i = 1; $i <= 5; ) {
// Generate a number within 200 and the total number of frames.
$frame = mt_rand(200,$total_frames);
$getframe = $mov->getFrame($frame);
// Check if the frame exists within the movie
// If it does, place the frame number inside an array and break the current loop
if($getframe){
$frames[$frame] = $getframe ;
$i++;
}
}
//For each frame found generate a thumbnail
foreach ($frames as $key => $getframe) {
$gd_image = $getframe->toGDImage();
imagejpeg($gd_image, "images/shot_".$key.'.jpeg');
imagedestroy($gd_image);
echo $key.'<br/>';
}
?>
脚本应该生成有效的帧号吗? START - END中的任何内容都应该是有效的帧编号?然而,循环需要很长时间!
答案 0 :(得分:4)
您可以从命令行调用ffmpeg,使用-ss
开关寻找适当的起点(及时,而不是帧数)和-vframes 1
告诉它准确提取一帧,例如:
ffmpeg -i 1486460.mp4 -ss 10 -vframes 1 images/shot_10.jpg
将从10秒内提取一帧,并将其称为images/shot_10.jpg
答案 1 :(得分:1)
这里的问题是随机这个词。我成功获得了视频的持续时间,然后尝试使用该随机持续时间获得一帧。可以轻松修改更多帧:
$cmd = "ffmpeg -i {$src} 2>&1 |grep Duration";
$output = array ();
exec($cmd, $output);
if(count($output)) {
$duration = explode(':', trim(str_replace('Duration:', NULL, current(explode(',', current($output))))));
list($hour, $min, $sec) = $duration;
$sec = sprintf("%02d:%02d:%02d", rand(0, $hour), rand(0, $min), rand(0, $sec));
} else {
$sec = "00:00:12"; //12sec it's ok :)
}
$cmd = "ffmpeg -ss {$sec} -i {$src} -s {$w}x{$h} -f image2 -vframes 1 {$destination}";
$output = array ();
exec($cmd, $output);
答案 2 :(得分:0)
我对电影格式知之甚少,但由于压缩可能依赖于带参考帧的单通道增量压缩,如果没有定义参考帧的位置,这意味着系统必须播放获得特定偏移量的完整电影。通过总是加载来检查这一点很容易,比如,在偏移量20和帧数除以某个值之间寻找一个帧。
假设是这种情况,您还有一个问题,就是您设计算法的方式,您需要回退到开始并向前搜索5帧中的每一帧 - 如果您提前生成了偏移量,然后对列表进行排序,ffmpeg可以一次性获取帧。
HTH
下进行。
答案 3 :(得分:-5)
你在循环中写错了。
if($getframe) {
$frames[$frame] = $getframe;
$i++;
}
让我们说for循环无限运行直到它被破坏。如果第一次if语句为false,则无法访问$i++
,循环就无止境。
您需要将$i++
放在for循环的底部,然后执行将是2秒而不是20分钟。