thinkphp5 获取视频gif,视频封面,视频帧数,视频信息
/** * 替换视频地址 * @param $VideoUrl * @return mixed * @param * @author huangpeng * @Time 2018/11/27 19:55 */ function changeVideoURL($VideoUrl){ $videoUrl1=str_replace("%2F","/",$VideoUrl); //视频路径 $videoUrl=str_replace("https://bucket.oss-cn-shenzhen.aliyuncs.com","http://video.***.com",$videoUrl1); return $videoUrl; } /** * @param $playTime * @return string * 简介: 把视频播放时长格式由“01:20:15”改为“90:00”格式 * @param: * User: huangpeng * Date: 2019/1/10 * Time: 17:09 */ function video_play_time($playTime){ $times=strtotime($playTime); $hour=date("H",$times); //获取小时 $minute=date("i",$times);//分钟 $second=date('s',$times); //秒 $minute=$minute+$hour*60; if(strlen($minute)==1){ $minutes="0".$minute; }else{ $minutes=$minute; } $res=$minutes.":".$second; return $res; } /** * 使用ffmpeg获取视频信息 (无法获取视频是否是竖屏还是横屏) * @param String $file 视频文件 * @return Array */ function getVideoInfo($file){ ob_start(); passthru(sprintf(config('FFmpeg'), $file)); $video_info = ob_get_contents(); ob_end_clean(); // 使用输出缓冲,获取ffmpeg所有输出内容 $ret = array(); // Duration: 00:33:42.64, start: 0.000000, bitrate: 152 kb/s if (preg_match("/Duration: (.*?), start: (.*?), bitrate: (\d*) kb\/s/", $video_info, $matches)){ $ret['duration'] = $matches[1]; // 视频长度 $duration = explode(':', $matches[1]); $ret['seconds'] = $duration[0]*3600 + $duration[1]*60 + $duration[2]; // 转为秒数 $ret['start'] = $matches[2]; // 开始时间 $ret['bitrate'] = $matches[3]; // bitrate 码率 单位kb } // Stream #0:1(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, bt709), 568x320, 747 kb/s, 29.98 fps, 29.97 tbr, 600 tbn, 1200 tbc (default) if(preg_match("/Video: (.*?), (.*?),(.*?), (.*?)[,\s]/", $video_info, $matches)){ $ret['vcodec'] = $matches[1]; // 编码格式 $ret['vformat'] = $matches[2]; // 视频格式 // dump($ret);dump($matches['4']); $n= list($width, $height) = explode('x', $matches[4]); if(isset($n)){ $ret['resolution'] = $matches[4]; // 网页上传视频分辨率 $ret['width'] = $width; $ret['height'] = $height; }else{ $ret['resolution'] = $matches[4]; // 手机上传视频分辨率 $ret['width'] = $width; $ret['height'] = $height; } } // // // Stream #0:0: Audio: cook (cook / 0x6B6F6F63), 22050 Hz, stereo, fltp, 32 kb/s if(preg_match("/Audio: (.*), (\d*) Hz/", $video_info, $matches)){ $ret['acodec'] = $matches[1]; // 音频编码 $ret['asamplerate'] = $matches[2]; // 音频采样频率 } if(isset($ret['seconds']) && isset($ret['start'])){ $ret['play_time'] = $ret['seconds'] + $ret['start']; // 实际播放时间 } // $ret['size'] = filesize($file); // 视频文件大小 $ret['rotate']=system("ffmpeg -show_streams | grep rotate"); //获取视频截图 $ret['thumbImg']=getVideoCover($file, "",$ret['width'],$ret['height']); $video_info = iconv('gbk','utf8', $video_info); return array($ret, $video_info); } /** * ffmpeg直接获取视频信息 全 * @param $video_file 视频地址 * @return array * @param * @author huangpeng * @Time 2018/11/14 15:03 * # ffmpeg -i test.asf -vframes 30 -y -f gif a.gif #把视频的前30帧转换成一个Gif */ //获取视频信息 function get_videoInfo($video_file){ ob_start(); // 使用输出缓冲,获取ffmpeg所有输出内容 $str="ffprobe -v quiet -print_format json -show_format -show_streams -select_streams v ".$video_file; system($str); $jsonData=json_decode(ob_get_contents(),true); ob_end_clean(); // 使用输出缓冲,清除ffmpeg所有输出内容 $res=[]; if($jsonData) { $streams = $jsonData['streams'][0]; $res['width'] = $streams['width']; //宽度 $res['height'] = $streams['height']; //长度 $res['duration'] = gmstrftime('%H:%M:%S', $streams['duration']); //获取视频长度 $res['tagsCount'] = count($streams['tags']); //获取数量 $format = $jsonData['format']; if ($res['tagsCount'] == 4) { $res['rotate'] = $streams['tags']['rotate']; $res['imgUrl'] = getVideoCover($video_file, '', $res['width'], $res['height']); //获取视频截图 } else { $res['rotate'] = ""; $res['imgUrl'] = getVideoCover($video_file, '', $res['height'], $res['width']);//获取视频截图 } $res['videoSize'] = sprintf("%.1f ", ($format['size'] / 1024 / 1000)) . "MB"; //获取视频大小 //获取gif $res['videoGif'] = get_video_gif($video_file); //获取webp格式动图 // $res['videoWebp']= get_videoWebp($video_file,""); return $res; }else{ return false; } } /* * 获得视频文件的缩略图 * @file 视频地址 * ,url 缩略图地址 * */ function getVideoCover($file, $time,$width=0,$height=0) { $sveFile=ROOT_PATH . 'public' . DS . 'uploads'. DS.'videoImg/' ; $name=time().mt_rand().".png"; $time=$time?$time:'2';//默认截取第一秒第一帧 // $str=exec("/usr/local/ffmpeg/bin/ffmpeg -ss 10 -i ".$file." 2>&1 -y -f mjpeg -vframes 1 -s 352x240 ".$_SERVER['DOCUMENT_ROOT']."/MVC/include/img/b-%03d.jpg",$out,$status); // ffmpeg -ss 5 -i http://face.***.com/test/mp4/2018-01-08-56.mp4 -vf rotate=0 -y -f mjpeg -vframes 1 -s 1242*699 /home/test/你的项目/public/uploads/videoImg/%3d.png // $str= "ffmpeg -ss ".$time." -i ".$file." -y -f mjpeg -vframes 1 -s ".$width."*".$height.$sveFile.$name; $str= "ffmpeg -ss ".$time." -i ".$file." -y -f mjpeg -vframes 1 -s ".$height."*".$width." ".$sveFile.$name; $result = system($str); $saveUrl=$sveFile.$name; if(Request::instance()->domain()=="https://www.***.com"){ $fileUrl="Img/videoImg/"; //正式地址图片路径 }else{ $fileUrl="test/videoImg/"; //测试地址路径 } vendor('aliyun.autoload'); $accessKeyId = "***";//去阿里云后台获取秘钥 $accessKeySecret = "***";//去阿里云后台获取秘钥 $endpoint = "oss-cn-shenzhen.aliyuncs.com";//你的阿里云OSS地址 $ossClient = new \OSS\OssClient($accessKeyId, $accessKeySecret, $endpoint); $bucket = "***";//oss中的文件上传空间 $object = $fileUrl . $name;//想要保存文件的名称 $fname = 'http://face.***.com/' . ltrim($object, './'); try { $ossClient->uploadFile($bucket, $object, $saveUrl); if(file_exists($saveUrl)){ unlink($saveUrl); } } catch (OssException $e) { printf($e->getMessage() . "\n"); return; } return $fname; } /** * @param $videoUrl 视频地址 * @param $time gif截图 * @return string|void * @throws \OSS\Core\OssException * @param 制作调色板 根据调色板制作gif * @author huangpeng * @Time 2018/11/14 17:17 */ function get_videoGif($videoUrl,$time='',$rotate=''){ $sveFile=ROOT_PATH . 'public' . DS . 'uploads'. DS.'videoGif/' ; $gif=time().mt_rand().".gif"; $saveUrl=$sveFile.$gif; $time=$time?$time:'3';//默认截取前3s //ffmpeg -ss 5 -t 5 -i http://image.***.com/feiyiproject/mp4/2018-02-22/5a8e2f70a7df0.mp4 -f gif C:\Users\Alvin\Desktop\imags\4444.gif //-s用于设定分辨率,-b:v设定视频比特率来压缩大小 //-ss 5 -t 3,从第2秒的地方开始,往后截取5秒钟, -r 用于设定帧数. 通常Gif有15帧左右就比较流畅了 // $str= "ffmpeg -i ".$videoUrl." -vframes ".$time." -y -f gif ".$sveFile.$name; //使用filter实现宽高减半显示: -vf scale=iw/2:ih/2 //-filter_complex 或 -lavfi //先制作调色板: $png=time().mt_rand().".png"; $savePng=$sveFile.$png; $filters = 'fps=15,scale=-1:281:flags=lanczos'; $colorBlockPng="ffmpeg -v warning -ss 5 -t 3 -i ".$videoUrl." -vf ".$filters.",palettegen -b:v 1300k -bufsize 1300k -maxrate 1500k -r 15 -y ".$savePng; $resPng=system($colorBlockPng,$status); if($status==0){ if($_SERVER['HTTP_HOST'] !="www.api.com"){ $str="ffmpeg -v warning -ss 5 -t 3 -i ".$videoUrl." -i ".$savePng." -filter_complex 'fps=15,scale=-1:281:flags=lanczos[x];[x][1:v]paletteuse' -b:v 1300k -bufsize 1300k -maxrate 1500k -r 15 -y ".$saveUrl; }else{ $str="ffmpeg -v warning -ss 5 -t 3 -i ".$videoUrl." -i ".$savePng." -filter_complex fps=15,scale=-1:281:flags=lanczos[x];[x][1:v]paletteuse -b:v 1300k -bufsize 1300k -maxrate 1500k -r 15 -y ".$saveUrl; } $result = system($str." 2>&1",$resStatus); if($resStatus==0){ if(Request::instance()->domain()=="https://www.***.com"){ $fileUrl="gif/videoGif/"; //正式地址图片路径 }else{ $fileUrl="test/videoGif/"; //测试地址路径 } vendor('aliyun.autoload'); $accessKeyId = "***";//去阿里云后台获取秘钥 $accessKeySecret = "***";//去阿里云后台获取秘钥 $endpoint = "oss-cn-shenzhen.aliyuncs.com";//你的阿里云OSS地址 $ossClient = new \OSS\OssClient($accessKeyId, $accessKeySecret, $endpoint); $bucket = "***";//oss中的文件上传空间 $object = $fileUrl . $gif;//想要保存文件的名称 $fname = 'http://image.***.com/' . ltrim($object, './'); try { if(file_exists($saveUrl) && file_exists($savePng)){ $ossClient->uploadFile($bucket, $object, $saveUrl); unlink($saveUrl); unlink($savePng); } } catch (OssException $e) { printf($e->getMessage() . "\n"); return; } return $fname; } } // if($rotate==90){ // $str="ffmpeg -ss 5 -t 3 -i ".$videoUrl." -vf fps=15,scale=-1:281 -b:v 1000k -bufsize 1000k -maxrate 1500k -r 15 -y -f gif ".$sveFile.$name ; // }elseif($rotate==180){ // //hflip 水平翻转 // //vflip 垂直翻转 // $str="ffmpeg -ss 5 -t ".$time." -i ".$videoUrl." -vf vflip,hflip -s 499x281 -b:v 1000k -bufsize 1000k -maxrate 1500k -r 15 -y -f gif ".$sveFile.$name ; // }elseif($rotate==270) { // $str="ffmpeg -ss 5 -t ".$time." -i ".$videoUrl." -vf transpose=1 -s 499x281 -b:v 1000k -bufsize 1000k -maxrate 1500k -r 15 -y -f gif ".$sveFile.$name ; // }else { // $str="ffmpeg -ss 5 -t ".$time." -i ".$videoUrl." -s 499x281 -b:v 1000k -bufsize 1000k -maxrate 1500k -r 15 -y -f gif ".$sveFile.$name ; // } } /** * @param $videoUrl * @return string|void * @简介: 省略调色板制作gif * @param * @param * @author huangpeng * @Time 2018/12/19 10:54 */ function get_video_gif($videoUrl){ $sveFile=ROOT_PATH . 'public' . DS . 'uploads'. DS.'videoGif/' ; $gif=time().mt_rand().".gif"; $saveUrl=$sveFile.$gif; $time=3;//默认截取前3s //ffmpeg -ss 5 -t 5 -i http://image.***.com/feiyiproject/mp4/2018-02-22/5a8e2f70a7df0.mp4 -f gif C:\Users\Alvin\Desktop\imags\4444.gif //-s用于设定分辨率,-b:v设定视频比特率来压缩大小 //-ss 5 -t 3,从第2秒的地方开始,往后截取5秒钟, -r 用于设定帧数. 通常Gif有15帧左右就比较流畅了 // $str= "ffmpeg -i ".$videoUrl." -vframes ".$time." -y -f gif ".$sveFile.$name; //使用filter实现宽高减半显示: -vf scale=iw/2:ih/2 //-filter_complex 或 -lavfi //system($str." 2>&1",$Status);查看信息 if($_SERVER['HTTP_HOST'] !="www.api.com"){ $str='ffmpeg -y -ss 5 -t 3 -i '.$videoUrl.' -filter_complex "fps=10,scale=-1:281:flags=lanczos[x];[x]split[x1][x2];[x1]palettegen[p];[x2][p]paletteuse=dither=none" '.$saveUrl; }else{ $str='ffmpeg -y -ss 5 -t 3 -i '.$videoUrl.' -filter_complex "fps=10,scale=-1:281:flags=lanczos[x];[x]split[x1][x2];[x1]palettegen[p];[x2][p]paletteuse=dither=none" '.$saveUrl; } $result = system($str,$Status); if($Status==0){ if(Request::instance()->domain()=="https://www.***.com"){ $fileUrl="gif/videoGif/"; //正式地址图片路径 }else{ $fileUrl="test/videoGif/"; //测试地址路径 } vendor('aliyun.autoload'); $accessKeyId = "***";//去阿里云后台获取秘钥 $accessKeySecret = "***";//去阿里云后台获取秘钥 $endpoint = "oss-cn-shenzhen.aliyuncs.com";//你的阿里云OSS地址 $ossClient = new \OSS\OssClient($accessKeyId, $accessKeySecret, $endpoint); $bucket = "9doke";//oss中的文件上传空间 $object = $fileUrl . $gif;//想要保存文件的名称 $fname = 'http://image.***.com/' . ltrim($object, './'); try { if(file_exists($saveUrl)){ $ossClient->uploadFile($bucket, $object, $saveUrl); unlink($saveUrl); } } catch (OssException $e) { printf($e->getMessage() . "\n"); return; } return $fname; } } /** * 制作webp格式动图 * @param $videoUrl * @param $time * @return string|void * @throws \OSS\Core\OssException * @param * @author huangpeng * @Time 2018/11/15 10:24 */ function get_videoWebp($videoUrl,$time){ $sveFile=ROOT_PATH . 'public' . DS . 'uploads'. DS.'videoGif/' ; $name=time().mt_rand(0,99).".webp"; $time=$time?:0; //开始时间 $str= "ffmpeg -i ".$videoUrl." -ss ".$time." -t 3 -vcodec libwebp -lossless 0 -q:v 20 -vf scale=iw/2:ih/2 -preset default -loop 0 -an -vsync 0 ".$sveFile.$name; // $str="ffmpeg -i".$videoUrl."-vf scale=240:-1 -r 10 -lossless 1 -loop 0 -y ".$sveFile.$name; $result = system($str); $saveUrl=$sveFile.$name; if(Request::instance()->domain()=="https://www.***.com"){ $fileUrl="gif/videoGif/"; //正式地址图片路径 }else{ $fileUrl="test/videoGif/"; //测试地址路径 } vendor('aliyun.autoload'); $accessKeyId = "***";//去阿里云后台获取秘钥 $accessKeySecret = "***";//去阿里云后台获取秘钥 $endpoint = "oss-cn-shenzhen.aliyuncs.com";//你的阿里云OSS地址 $ossClient = new \OSS\OssClient($accessKeyId, $accessKeySecret, $endpoint); $bucket = "***";//oss中的文件上传空间 $object = $fileUrl . $name;//想要保存文件的名称 $fname = 'http://image.***.com/' . ltrim($object, './'); try { $ossClient->uploadFile($bucket, $object, $saveUrl); if(file_exists($saveUrl)){ unlink($saveUrl); } } catch (OssException $e) { printf($e->getMessage() . "\n"); return; } return $fname; } //获取视频大小 function getVideoSize($video){ $size=sprintf( "%.1f ",($video['size']/1024/1000))."MB"; return $size; } //获得视频文件的总长度时间和创建时间 function getVideoTime($file) { $vtime = exec("ffmpeg -i " . $file . " 2>&1 | grep 'Duration' | cut -d ' ' -f 4 | sed s/,//");//CuPlayer.com 总长度 // $ctime = date("Y-m-d H:i:s",filectime($file));//创建时间 //$duration = explode(":",$time); // $duration_in_seconds = $duration[0]*3600 + $duration[1]*60+ round($duration[2]);//CuPlayer.com 转化为秒 return $vtime; }