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 非數(shù)組或為空';
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;
}
//執(zhí)行拼接命令
# -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'] = '參數(shù)為空';
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);
//根據(jù)分辨率判斷視頻是否為橫屏
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'] = '參數(shù)為空';
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'] = '參數(shù)為空';
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;
}
設置關鍵幀(主要用于視頻拼接中間有卡頓現(xiàn)象)
/**
* 設置關鍵幀
* @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;
}