由于楼主公司生产的设备性能不足,在进行播放高质量的MP4视频或者其他格式的视频时,会导致设备黑屏。所以必须由后端来解决视频转码的问题。通过搜索,可以通过FFmpeg来实现视频压缩的功能。当实现视频压缩功能的时候,又出现了一个问题,那就是每次上传视频时,单个视频处理很快,多个视频同时上传时就会出现同时启动多个FFmpeg进程,导致cpu性能被沾满如图所示
可以看出 多个进程同时启动会导致服务器性能急剧下降,为了解决这个问题,可以通过Redis来实现一个队列功能。当我们每次上传一个文件时把文件信息存储到一个列表中,然后通过redis队列的特性,左进右出来实现,我们可以监听redis队列中是否有值。从而实现我们要实现的任务。
ignore_user_abort(true); // 忽略客户端断开
set_time_limit(0); // 设置执行不超时
$interval = 50; //毫秒值
while (true){ //死循环,实现数据实时获取
$idle = 1;
if($redis->LLen("video")!=0){ //如果有值的话把里面的值取出来
$value = $redis->rpop('video');//
if($value){
$values = explode(',',$value);
mp4($values);
//可以传递其他数据实现业务
}
}
usleep($interval * ($idle % 10)); //延迟代码执行若干微秒
$idle++;
}
function mp4($data){
usleep(50000); //这个操作是为了防止视频上传后还没有移动到指定上传的目录中而找不到文件
$file= substr($data[1],1,strlen($data[1]));
while(true){
if(!is_file($file)){
break;
}
}
$dir = substr($data[2],1,strlen($data[2]));
if($data[0]==22){
$cmd = "ffmpeg -i $file -s hd1080 -b:v 4000k $dir";//这段代码是为了把分辨率超过1080p的转成1080p
}else{
$cmd = "ffmpeg -i $file -b:v 4000k $dir";
}
$res = true;
do{
if(system($cmd)==0){ //使用system()执行shell命令,执行成功的话返回值为0
$res = false; //退出循环
}
}while($res);
return 1;
}
为了能够实现每次用户上传的视频文件都能够进行队列处理,所以不能够通过请求的方式来实现,不能通过TP框架或者laravel框架来进行,因为执行压缩命令往往耗时,而通过请求会往往会出现代码执行一半就会报错的问题,比如Tp框架会出现找不到URL
的错误。所以我们得通过 使用sell命令来执行我们的代码,如我的文件名为video.php 在Linux下可以通过执行
php video.php 来执行。但是这个操作是终端不能再进行其他操作,在我们关闭终端时,这个进程也关闭了。所以我们可以把这个设置为守护进程,在后台一直执行,php video.php & 回车后再执行 jobs -l 就可以了
无论多少个用户上传都是按先后顺序一个一个来压缩视频,不会出现同时执行的情况。