最近做公司的项目中,有用户上传视频,后台这边接收视频并上传,获取视频第一帧作为视频封面的功能,在网上查找了好多资料,并且安装 了ffmpeg-php的PHP扩展,由于版本问题,安装好几个版本都不成功,最后放弃安装扩展,后来运行代码发现不用安装那个扩展也能实现截图并上传的功能,所以要截取视屏第一帧,只需要安装FFmpeg和yasm即可,建议先安装yasm,再安装FFmpeg,我这边是一边安装一边排错的,所以我先安装的实FFmpeg。截取第一帧的PHP代码会在后面详细列出。
ffmpeg的下载链接 http://ffmpeg.org/download.html
解压安装包
tar -jxvf ffmpeg-x.x.tar.bz2
进入目录
cd ffmpeg-x.x
编译安装
./configure --enable-shared && make && make install
报错:
nasm/yasm not found or too old. Use --disable-x86asm for a crippled build.
If you think configure made a mistake, make sure you are using the latest
version from Git. If the latest version fails, report the problem to the
[email protected] mailing list or IRC #ffmpeg on irc.freenode.net.
Include the log file "ffbuild/config.log" produced by configure as this will help
solve the problem.
报这个错说明没有安装yasm,所以要先去安装yasm
http://yasm.tortall.net/Download.html 下载yasm,上传到服务器的local目录中
解压:
tar -zxvf yasm.tar.gz
进入解压目录安装:
cd yasm-1.3.0/
./configure
make
make install
安装成功以后进入FFmpeg目录进行安装,可能需要3,4分钟时间
如果编译报错,请加选项(报错会提示选项内容)./configure --enable-shared --选项 && make && make install
安装完成之后 执行 ffmpeg -version
如果出现ffmpeg: error while loading shared libraries: libavdevice.so.57: cannot open shared object file: No such file or directory
编辑/etc/ld.so.conf文件中的:include ld.so.conf.d/*.conf 这行下面加入如下内容
/usr/local/ffmpeg-4.0.2
保存退出后执行ldconfig命令
检验安装成功与否,输入 ffmpeg检验,出现如下图内容,即安装成功
cd /usr/local/php/etc
修改完成后保存退出重启服务器
service php-fpm restart
看到如下,说明重启成功
Gracefully shutting down php-fpm .. done
Starting php-fpm done
我用的框架是tp5的框架,代码如下,因为视频和图片一样都是文件,所以接收方式和图片的接收方式一样,上传也是一样,直接调取框架自带的上传类:
$video = request()->file('video');//接收video文件
if(!empty($video)){
$info = $video->move(ROOT_PATH . 'public' . DS . 'uploads');
if($info) {
$videoName = $info->getSaveName();
$source = '/uploads/' .$videoName;//原视频名称
$dir = ROOT_PATH . 'public' . DS . 'uploads/';//上传图片路径
$fileName = str_replace('.mp4','.jpg',$videoName);//图片名称
$video_filePath = $dir.$videoName;//视频路径
//用ffmpeg截取视频第一帧,并上传保存在和视频一样的路径下
//使用-ss参数,可以从指定的时间开始处理转换任务后面是1代表从第一秒开始
//-s参数,后面是图片的宽高,这个可以不用写,因为有横屏的或者竖屏的视频,不能固定
$str = "ffmpeg -i ".$video_filePath." -y -f mjpeg -ss 1 -t 0.001 -s 348*470 ".$dir.$fileName;
exec($str,$out,$status);
$datas['video'] = $source;
$datas['picture'] = '/uploads/' . $fileName;
$image = \think\Image::open('.'.$datas['picture']);
//调用tp5的图片处理类,获取图片宽高,并给封面图片添加播放按钮
$width = $image->width();
// 返回图片的高度
$height = $image->height();
$datas['width'] = $width;
$datas['height'] = $height;
$water = $dir.'water.png';//播放按钮
$image->water($water,\think\Image::WATER_NORTHWEST,50)->save('.'.$datas['picture']);
}
}
或者将截取视频第一帧的功能封装一个方法,可以调用
/**
* 截取视频第一帧
*
* @param $file 视频文件
* @param $time 第几帧
* @param $dir 临时目录
* @param $size 截图尺寸
*/
public function getVideoCover($file,$time,$dir,$size) {
$time = $time ? $time : '1'; //默认截取第一秒第一帧
$size = $size ? $size : '348*470';
$fileName = getImgName();
//临时视频路径,生成截图后删除
$tempfiles = $dir.$fileName.'.mp4';
$bool = move_uploaded_file($file, $tempfiles);
$str = "ffmpeg -i ".$tempfiles." -y -f mjpeg -ss ".$time." -t 0.001 -s $size ".$dir.$fileName.'.jpg';
exec($str,$out,$status);
return $fileName;
}
成功以后进行数据库数据的存储,结束,就是这样喽