手机应用上面显示GIF图片的情况越来越多,但是GIF图片相对文件非常大,故我们希望能有更好的方式来代替GIF,比如说转成MP4。
目前twitter已经实现了该功能:GIF动图时代的结束? Twitter将用户上传的GIF动图转换成mp4格式
以下是最近琢磨出来的PHP代码:(已经在线上跑了)
<?php
// 输入的gif图片
$gif_file = "in.gif";
// 输出的mp4文件
$mp4_file = "out.mp4";
try{
$image = new Imagick($gif_file);
}catch (Exception $e) {
$image = false;
}
if(false != $image && "GIF" == $image->getImageFormat()){
$image = $image->coalesceimages();
$width = $image->getImageWidth();
$height = $image->getImageHeight();
foreach($image as $gif){
$width = max($gif->getImageWidth(), $width);
$height = max($gif->getImageHeight(), $height);
}
if($height % 2 == 1)$height = $height - 1;
if($width % 2 == 1)$width = $width - 1;
$command = "ffmpeg -i ".$gif_file." -s ".$width.":".$height;
$command .= " -r 24 -c:v libx264 -c:a copy -pix_fmt yuv420p -f mp4 ";
$command .= $mp4_file." 2>&1";
exec($command, $output);
echo print_r($output, true);
}else{
echo "Not gif image!";
}
1. 环境要安装好php的imagick,和ffmpeg。
2. 首先要探测图片是否GIF,非GIF的话是转不成功的。这里通过两道检测来实现:new Imagick看是否图片、getImageFormat()看是否GIF。
3. 然后获取到图片的长宽,毕竟在ffmpeg里面需要设置长宽的参数,不然会转出来直接黑屏。获取图片长宽时,要用$image的迭代器(GIF的特性),探测里面某一帧的长宽。
4. 取得长宽后,需要取一下余,h264编码器要求必须长或宽是可以整除2的数值。
5. 执行ffmpeg的命令,-s加入长宽,-r是帧率,一般要设置到24,否则手机上的播放速度变慢了或者快了,-c:v 是h264,-c:a 直接copy就行。
6. ffmpeg必须加入-pix_fmt yuv420p 设置了点阵像素模式,-f是输出格式
7. ffmpeg命令的最后是“2>&1”,因为php的exec必须在命令行上面加上这个结束,才能输出$output内容。