ffmpeg公用方法封装-PHP
拼接视频
/**
* 拼接视频
* 视频地址为 url
* @param $url
* @param string $object_name
* @return array
* @author: xiao
* @Date: 2021/4/15 14:04
*/
public function videoConcatUrl($url,$object_name = '')
{
if (!is_array($url) || empty($url)){
$this->data['code'] = -1;
$this->data['msg'] = 'url 非数组或为空';
return $this->data;
}
$str = '';
foreach ($url as $key => $val){
$str .= "file '".$val."' \r\n";
}
//写入文件
$temp_txt_name = 'temp_video_file_'.rand(1000,9999).'.txt';
$fp = @fopen($this->video_path.$temp_txt_name,"w+");
@fputs($fp,$str);
@fclose();
if (!file_exists($this->video_path.$temp_txt_name)){
$this->data['code'] = -1;
$this->data['msg'] = 'url文件写入失败';
return $this->data;
}
//执行拼接命令
# -safe 0 -protocol_whitelist "file,http,https,rtp,udp,tcp,tls"
$ffmpeg_exec = '/usr/local/ffmpeg/bin/ffmpeg -f concat -safe 0 -i '.$this->video_path.$temp_txt_name.' -c copy '.$this->video_path.$object_name.'';
exec($ffmpeg_exec,$output,$code);
if ($code != 0){
$this->data['code'] = -1;
$this->data['msg'] = '视频拼接失败';
return $this->data;
}
//删除临时文件
if (file_exists($this->video_path.$temp_txt_name)){
@unlink($this->video_path.$temp_txt_name);
}
$this->data['data'] = [
'video_url' => $this->video_path.$object_name
];
return $this->data;
}
添加字幕(硬压字幕)
//主要颜色
private $primaryColour = ['FFFFFF'];
//边框颜色
private $OutlineColour = '000000';
//字体
private $fontName = ["Muyao\-Softbrush","YRDZST"];
/**
* 字幕添加
* @param $video_url
* @param $video_srt_url
* @param $object_name
* @param string $ratio 分辨率
* @return array
* @author: xiao
* @Date: 2021/4/15 14:41
*/
public function videoSubtitles($video_url,$video_srt_url,$object_name,$ratio='720x1280')
{
if (empty($video_url) || empty($video_srt_url) || empty($object_name)){
$this->data['code'] = -1;
$this->data['msg'] = '参数为空';
return $this->data;
}
//下载字幕文件到本地
$file = file_get_contents($video_srt_url);
$srt_name = date('YmdHis').'_'.rand(1000,9999).'_'.'srt'.'.srt';
$srt_path = $this->video_path.$srt_name;
file_put_contents($srt_path,$file);
/**
* 设置字幕样式
*/
//字体
$font_name = $this->fontName[rand(0,(count($this->fontName)-1))];
$out_line_color = $this->OutlineColour;
//主要颜色
$primary_color = $this->primaryColour[rand(0,count($this->primaryColour)-1)];
$primary_color = '&H'.$primary_color;
$out_line_color = '&H'.$out_line_color;
$margin_v = rand(70,85);
$font_size = rand(12,13);
//根据分辨率判断视频是否为横屏
if ($ratio == '1280x720' || $ratio == '1920x1080'){
\Log::error('come in ratio');
$font_size = rand(18,21);
$margin_v = rand(5,15);
}
$force_style='Fontname='.$font_name.'\,Fontsize='.$font_size.'\,MarginV='.$margin_v.'\,PrimaryColour='.$primary_color.'\,OutlineColour='.$out_line_color.'\,Alignment=2';
$ffmpeg_exec = "/usr/local/ffmpeg/bin/ffmpeg -i ".$video_url." -threads 5 -preset ultrafast -vf subtitles=".$srt_path.":force_style='".$force_style."' -y ".$this->video_path.$object_name." ";
exec($ffmpeg_exec,$output,$code);
if ($code != 0){
$this->data['code'] = -1;
$this->data['msg'] = '字幕插入失败';
return $this->data;
}
$this->data['data'] = [
'video_url' => $this->video_path.$object_name
];
if (file_exists($srt_path)){
@unlink($srt_path);
}
return $this->data;
}
音频插入
/**
* 音频插入
* @param $video_url
* @param $audio_url
* @param $object_name
* @return array
* @author: xiao
* @Date: 2021/4/15 16:11
*/
public function audioInsert($video_url,$audio_url,$object_name)
{
if (empty($video_url) || empty($audio_url) || empty($object_name)){
$this->data['code'] = -1;
$this->data['msg'] = '参数为空';
return $this->data;
}
//消除原有视频的音频
$temp_name = 'temp_'.rand(1000,9999).'.mp4';
//临时文件
$temp_path = public_path() . '/upload/' . $temp_name;
$clear_audio_exec = '/usr/local/ffmpeg/bin/ffmpeg -i '.$video_url.' -vcodec copy -an '.$temp_path.'';
exec($clear_audio_exec,$out,$audio_code);
if ($audio_code != 0 ){
$this->data['code'] = -1;
$this->data['msg'] = '消除音频失败';
return $this->data;
}
# -safe 0 -protocol_whitelist
$merge_video_exec = '/usr/local/ffmpeg/bin/ffmpeg -i '.$temp_path.' -i '.$audio_url.' -vcodec copy -acodec copy '.$this->video_path.$object_name.' ';
exec($merge_video_exec,$o,$merge_code);
if ($merge_code != 0){
$this->data['code'] = -1;
$this->data['msg'] = '音频插入失败';
return $this->data;
}
$this->data['data'] = [
'video_url' => $this->video_path.$object_name
];
return $this->data;
}
压缩视频
/**
* 压缩视频
* @param $video_url
* @param string $object_name
* @param string $code_rate
* @param string $ratio 码率
* @return array
* @author: xiao
* @Date: 2021/4/27 14:49
*/
public function videoCompress($video_url,$object_name = '',$code_rate = '500k',$ratio='1280x720' )
{
if (empty($video_url)){
$this->data['code'] = -1;
$this->data['msg'] = '参数为空';
return $this->data;
}
// $ffmpeg_exec = '/usr/local/ffmpeg/bin/ffmpeg -i '.$video_url.' -threads 2 -preset ultrafast -b:v '.$code_rate.' -s '.$width.'x'.$height.' '.$this->video_path.$object_name.' ';
$ffmpeg_exec = '/usr/local/ffmpeg/bin/ffmpeg -i '.$video_url.' -threads 2 -preset ultrafast -b:v '.$code_rate.' '.$this->video_path.$object_name.' ';
exec($ffmpeg_exec,$o,$code);
if ($code != 0){
$this->data['code'] = -1;
$this->data['msg'] = '视频压缩失败';
return $this->data;
}
$this->data['data'] = [
'video_url' => $this->video_path.$object_name
];
return $this->data;
}
设置关键帧(主要用于视频拼接中间有卡顿现象)
/**
* 设置关键帧
* @param $video_url
* @param $object_name
* @return array
* @author: xiao
* @Date: 2021/4/27 17:05
*/
public function videoSetKey($video_url, $object_name)
{
$ffmpeg_exec = '/usr/local/ffmpeg/bin/ffmpeg -i '.$video_url.' -threads 2 -preset ultrafast -g 1 -keyint_min 2 '.$this->video_path.$object_name.' ';
exec($ffmpeg_exec,$o,$code);
if ($code != 0){
$this->data['code'] = -1;
$this->data['msg'] = '关键帧设置失败';
return $this->data;
}
$this->data['data'] = [
'video_url' => $this->video_path.$object_name
];
return $this->data;
}
获取视频信息
/**
* 获取视频信息
* @param $video_url
* @return array|string[]
* @author: xiao
* @Date: 2021/6/10 15:54
*/
public function getVideoInfo($video_url)
{
$arr = [];
$ffmpeg_exec = '/usr/local/ffmpeg/bin/ffprobe -i '.$video_url.' -preset ultrafast 2>&1';
// $video_info = shell_exec($ffmpeg_exec);
exec($ffmpeg_exec,$info,$code);
if (empty($info)){
$this->data['code'] = -1;
$this->data['msg'] = '获取视频信息失败';
return $this->data;
}
/**
* 获取视频信息开始
*/
//分辨率
if (isset($info[18])){
$temp_ratio = explode(',',$info[18]);
$arr['ratio'] = isset($temp_ratio[2])?trim($temp_ratio[2]):'1280x720';
}
return $arr;
}