当前位置:首页 > PHP教程 > php应用 > 列表

php实现ffmpeg处理视频的实践

发布:smiling 来源: PHP粉丝网  添加日期:2022-05-20 11:10:26 浏览: 评论:0 

本文主要介绍了php实现ffmpeg处理视频的实践,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。

最近有一个项目需要使用ffmpeg处理视频,这里我写了一个demo,方便我们来实现视频操作

ffmpeg操作demo

  1. <?php 
  2.  
  3. namespace common\helpers; 
  4.  
  5. use common\models\Config; 
  6. use common\models\VideoApiLog; 
  7. use Yii; 
  8. use yii\helpers\ArrayHelper; 
  9. use common\helpers\Universal; 
  10. use yii\helpers\FileHelper; 
  11. use yii\httpclient\Client; 
  12. use yii\web\ServerErrorHttpException; 
  13.  
  14. /** 
  15.  * ffmpeg视频处理 
  16.  * 
  17.  * @author wangjian 
  18.  * @since 0.1 
  19.  */ 
  20. class FfmpegVideo 
  21.  
  22.     public $ffmpeg = 'ffmpeg'
  23.  
  24.  
  25.     public function __construct($ffmpeg = null) 
  26.     { 
  27.         if ($ffmpeg) { 
  28.             $this->ffmpeg = $ffmpeg
  29.         } 
  30.     } 
  31.  
  32.  
  33.     /** 
  34.      * 添加视频文字滚动 
  35.      * @param $source string 视频 
  36.      * @param $saveFile string 保存文件 
  37.      * @param $text string 水印文字 
  38.      * @param array $options 水印样式 
  39.      * @param int $step 每秒步长 
  40.      * @param int $star 出现时间 
  41.      */ 
  42.     public function titleMod($source$saveFile$text$options = [], $step = 20, $star = 0) 
  43.     { 
  44.         $command = $this->ffmpeg .' -y -i '$source .' -async 1 -metadata:s:v:0 start_time=0 -vf '
  45.  
  46.         $fonts = Yii::getAlias('@webroot') . "/fonts/simsun.ttc"
  47.         $fonts = str_replace('\\', '/', $fonts); 
  48.         $fonts = str_replace(':''\\:'$fonts); 
  49.         $command .= '"drawtext=fontfile=\''$fonts .'\': text=\''$text .'\''
  50.  
  51.         foreach ($options as $key => $value) { 
  52.             $command .= ':' . $key . '=' . $value
  53.         } 
  54.  
  55.         $command .= ':x=\'if(gte(t,'$star .'),((t-'$star .') * '$step .'),NAN)\''
  56.  
  57.         $command .= '" '
  58.         $command .= $saveFile
  59.         exec($command$output$result_code); 
  60.         if ($result_code == 0) { 
  61.             return true; 
  62.         } 
  63.         return  false; 
  64.     } 
  65.  
  66.  
  67.     /** 
  68.      * 图片水印 
  69.      * @param $source string 视频 
  70.      * @param $saveFile string 保存文件 
  71.      * @param $waterImage string 水印图片 
  72.      * @param $left integer 水印水平位置 
  73.      * @param $top integer 水印垂直位置 
  74.      * @param null $star 水印开始时间 
  75.      * @param null $duration 水印时长 
  76.      */ 
  77.     public function imageWater($source$saveFile$waterImage$left$top$star = null, $duration = null) 
  78.     { 
  79.         $waterImage = str_replace('\\', '/', $waterImage); 
  80.         $waterImage = str_replace(':''\\:'$waterImage); 
  81.         $command = $this->ffmpeg . ' -y -i '$source .' -vf "movie=\''$waterImage .'\'[watermark];'
  82.         $command .= '[in][watermark] overlay='$left .':'$top
  83.         if ($star) { 
  84.             $end = ($duration) ? $star + $duration : $star
  85.             $command .= ':enable=\'between(t,'$star .','$end .')\''
  86.         } 
  87.         $command .= '[out] " ' . $saveFile
  88.         exec($command$output$result_code); 
  89.         if ($result_code == 0) { 
  90.             return true; 
  91.         } 
  92.         return  false; 
  93.     } 
  94.  
  95.  
  96.     /** 
  97.      * 给视频添加文字水印 
  98.      * @param $source string 视频 
  99.      * @param $saveFile string 保存文件 
  100.      * @param $text string 水印文字 
  101.      * @param array $options 水印样式 
  102.      * @param null $star 水印开始时间 
  103.      * @param null $duration 水印时长 
  104.      */ 
  105.     public function titleWater($source$saveFile$text$options = [], $star = null, $duration = null) 
  106.     { 
  107.         $command = $this->ffmpeg .' -y -i '$source .' -vf '
  108.         $fonts = Yii::getAlias('@webroot') . "/fonts/STZHONGS.TTF"
  109.         $fonts = str_replace('\\', '/', $fonts); 
  110.         $fonts = str_replace(':''\\:'$fonts); 
  111.         $command .= '"drawtext=fontfile=\''$fonts .'\': text=\''$text .'\''
  112.  
  113.         foreach ($options as $key => $value) { 
  114.             $command .= ':' . $key . '=' . $value
  115.         } 
  116.         if ($star) { 
  117.             $end = ($duration) ? $star + $duration : $star
  118.             $command .= ':enable=\'between(t,'$star .','$end .')\''
  119.         } 
  120.         $command .= '" '
  121.         $command .= $saveFile
  122.  
  123.         exec($command$output$result_code); 
  124.         if ($result_code == 0) { 
  125.             return true; 
  126.         } 
  127.         return  false; 
  128.     } 
  129.  
  130.     /** 
  131.      * 将音频合并到视频中 
  132.      * @param $videoFile string 视频文件 
  133.      * @param $audioFile string 音频文件 
  134.      * @param $saveFile string 保存文件 
  135.      * @param $delay integer 声音插入延时秒数 
  136.      */ 
  137.     public function mergeVideoAudio($videoFile$audioFile$saveFile$delay = null) 
  138.     { 
  139.         $delayTime = 0; 
  140.         if ($delay) { 
  141.             $delayTime = $delay * 1000; 
  142.         } 
  143.         $command =  $this->ffmpeg . ' -y -i '$audioFile .' -i '$videoFile .' -c:v copy -c:a aac -strict experimental -filter_complex "[0]adelay='$delayTime .'|'$delayTime .'[del1],[1][del1]amix" ' . $saveFile
  144.         exec($command$output$result_code); 
  145.         if ($result_code == 0) { 
  146.             return true; 
  147.         } 
  148.         return  false; 
  149.     } 
  150.  
  151.  
  152.     /** 
  153.      * 静音 
  154.      */ 
  155.     public function audioMute($source$saveFile
  156.     { 
  157.         $command =  $this->ffmpeg . ' -y -i '$source .' -filter:a "volume=0" ' . $saveFile
  158.         exec($command$output$result_code); 
  159.         if ($result_code == 0) { 
  160.             return true; 
  161.         } 
  162.         return  false; 
  163.     } 
  164.  
  165.  
  166.     /** 
  167.      * 提取视频的音频 
  168.      * @param $source string 需要提取声音的视频 
  169.      * @param $saveFile string 提取声音后保存的音频 
  170.      * @return bool 
  171.      */ 
  172.     public function collectAudio($source$saveFile
  173.     { 
  174.         $command =  $this->ffmpeg . ' -y -i '$source .' -vn -acodec copy ' . $saveFile
  175.         exec($command$output$result_code); 
  176.         if ($result_code == 0) { 
  177.             return true; 
  178.         } 
  179.         return  false; 
  180.     } 
  181.  
  182.     /** 
  183.      * 去除视频声音 
  184.      * @param $source string 需要去除声音的视频 
  185.      * @param $saveFile string 去除声音后保存的视频 
  186.      */ 
  187.     public function removeAudio($source$saveFile
  188.     { 
  189.         $command =  $this->ffmpeg . ' -y -i '$source .' -an ' . $saveFile
  190.  
  191.         exec($command$output$result_code); 
  192.         if ($result_code == 0) { 
  193.             return true; 
  194.         } 
  195.         return  false; 
  196.     } 
  197.  
  198.     /** 
  199.      * 视频拼接 
  200.      * @param $sources array 需要拼接的视频/音频 
  201.      * @param $saveFile string 拼接后的视频/音频 
  202.      */ 
  203.     public function spliceVideo($sources$saveFile
  204.     { 
  205.         $commands = []; 
  206.         $temporaryFile = []; 
  207.         $basePath = sys_get_temp_dir(); 
  208.         $index = 0; 
  209.         foreach ($sources as $i => $source) { 
  210.             $file = $basePath . '/' . $i . '.ts'
  211.             $commands[$index] = $this->ffmpeg . ' -y -i '$source .' -vcodec copy -acodec copy -vbsf h264_mp4toannexb ' . $file
  212.             $temporaryFile[] = $file
  213.             $index++; 
  214.         } 
  215.         $commands[$index] = $this->ffmpeg . ' -y -i "concat:'. implode('|'$temporaryFile) .'"  -acodec copy -vcodec copy -absf aac_adtstoasc ' . $saveFile
  216.         foreach ($commands as $command) { 
  217.             exec($command$output$result_code); 
  218.         } 
  219.  
  220.         foreach ($temporaryFile as $file) { 
  221.             @unlink($file); 
  222.         } 
  223.         return true; 
  224.  
  225.     } 
  226.  
  227.  
  228.     /** 
  229.      * 视频剪切 
  230.      * @param $source string 需要剪切视频/音频 
  231.      * @param $saveFile string 剪切后保存视频/音频 
  232.      * @param $star string 剪切开始时间 
  233.      * @param null $duration string 剪切时长 
  234.      */ 
  235.     public function clipVideo($source$saveFile$star$duration = null) 
  236.     { 
  237.         $command = $this->ffmpeg . ' -y -ss '$star
  238.         if ($duration) { 
  239.             $command .= ' -t '$duration
  240.         } 
  241.         $command .= ' -i '$source .' -acodec copy ' . $saveFile
  242.         exec($command$output$result_code); 
  243.         if ($result_code == 0) { 
  244.             return true; 
  245.         } 
  246.         return  false; 
  247.     } 
  248.  
  249.     const ROTATE_90 = 'transpose=1'
  250.     const ROTATE_180 = 'hflip,vflip'
  251.     const ROTATE_270 = 'transpose=2'
  252.  
  253.     /** 
  254.      * 视频旋转 
  255.      * @param $source string 需要旋转的视频 
  256.      * @param $saveFile string 旋转后视频 
  257.      * @param $rotate string 旋转角度 
  258.      */ 
  259.     public function transposeVideo($source$saveFile$rotate
  260.     { 
  261.  
  262.         $command = $this->ffmpeg . ' -y -i ' . $source . ' -vf ""transpose=1"" ' . $saveFile
  263.         exec($command$output$result_code); 
  264.         if ($result_code == 0) { 
  265.             return true; 
  266.         } 
  267.         return  false; 
  268.     } 
  269.  
  270.     /** 
  271.      * 视频转码 
  272.      * @param $source string 需要转码的视频/音频 
  273.      * @param $saveFile string 转码后的视频/音频 
  274.      */ 
  275.     public function acodecVideo($source$saveFile
  276.     { 
  277.         $command = $this->ffmpeg . ' -y -i '$source .' -acodec copy -vcodec copy -f mp4 ' . $saveFile
  278.         exec($command$output$result_code); 
  279.         if ($result_code == 0) { 
  280.             return true; 
  281.         } 
  282.         return  false; 
  283.     } 
  284.  
  285.     /** 
  286.      * 视频拼接 
  287.      * @param $sources array 需要拼接的视频/音频 
  288.      * @param $saveFile string 拼接后的视频/音频 
  289.      */ 
  290.     public function concatVideo($sources$saveFile
  291.     { 
  292.         $file = $this->createTemporaryFile(); 
  293.         $fileStream = @fopen($file'w'); 
  294.         if($fileStream === false) { 
  295.             throw new ServerErrorHttpException('Cannot open the temporary file.'); 
  296.         } 
  297.  
  298.         $count_videos = 0; 
  299.         if(is_array($sources) && (count($sources) > 0)) { 
  300.             foreach ($sources as $videoPath) { 
  301.                 $line = ""
  302.                 if($count_videos != 0) 
  303.                     $line .= "\n"
  304.                 $line .= "file '"str_replace('\\','/',$videoPath) ."'"; 
  305.  
  306.                 fwrite($fileStream$line); 
  307.                 $count_videos++; 
  308.             } 
  309.         } 
  310.         else { 
  311.             throw new ServerErrorHttpException('The list of videos is not a valid array.'); 
  312.         } 
  313.  
  314.         $command = $this->ffmpeg .' -y -f concat -safe 0 -i '$file . ' -c copy ' . $saveFile
  315.         exec($command$output$result_code); 
  316.         fclose($fileStream); 
  317.         @unlink($file);//删除文件 
  318.         if ($result_code == 0) { 
  319.             return true; 
  320.         } 
  321.         return  false; 
  322.     } 
  323.  
  324.     /** 
  325.      * 创建一个临时文件 
  326.      */ 
  327.     public function createTemporaryFile() 
  328.     { 
  329.         $basePath = sys_get_temp_dir(); 
  330.         if (false === $file = @tempnam($basePath, null)) { 
  331.             throw new ServerErrorHttpException('Unable to generate a temporary filename'); 
  332.         } 
  333.         return $file
  334.     } 
  335.  
  336.     /** 
  337.      * 获取视频信息 
  338.      * @param $source string 需要获取时长的资源 
  339.      */ 
  340.     public function getAttributes($source
  341.     { 
  342.         ob_start(); 
  343.         $command = $this->ffmpeg . ' -i "'$source .'" 2>&1'
  344.         passthru($command); 
  345.         $getContent = ob_get_contents(); 
  346.         ob_end_clean(); 
  347.         $duration = 0; 
  348.         $widht = 0; 
  349.         $height = 0; 
  350.         if (preg_match("/Duration: (.*?), start: (.*?), bitrate: (\d*) kb\/s/"$getContent$match)) { 
  351.             $matchs = explode(':'$match[1]); 
  352.             $duration = $matchs[0] * 3600 + $matchs[1] * 60 + $matchs[2]; //转换播放时间为秒数 
  353.         } 
  354.  
  355.         if (preg_match("/Video: (.*?), (.*?), (.*?)[,\s]/"$getContent$match)) { 
  356.             $matchs = explode('x'$match[3]); 
  357.             $widht = $matchs[0]; 
  358.             $height = $matchs[1]; 
  359.         } 
  360.  
  361.         return [ 
  362.             'duration' => intval($duration), 
  363.             'widht' => intval($widht), 
  364.             'height' => intval($height), 
  365.         ]; 
  366.     } 

使用简单示例

这里注意如果无法执行ffmpeg,实例化时需要传入ffmpeg的安装地址,例如linux下ffmpeg安装地址为/usr/local/ffmepg,那么实例化时需要传入/usr/local/ffmpeg/bin/ffmpeg

1:给视频添加文字

  1. $ffmpeg = new FfmpegVideo(); 
  2. $ffmpeg ->titleWater( 
  3.     'XXX',//原视频 
  4.     'XXX',//处理后保存视频 
  5.     'XXX',//文字 
  6.     [ 
  7.         'x' => 30,//水平距离 
  8.         'y' => 30,//垂直距离 
  9.         'fontsize' => 20,//文字大小 
  10.         'fontcolor' => 'red',//文字颜色 
  11.         'shadowy' => 2,//文字阴影 
  12.     ], 
  13.     200,//每秒移动步长 
  14.     2//文字出现时间(秒) 
  15. ); 

2:将视频设为静音

  1. $ffmpeg = new FfmpegVideo(); 
  2. $ffmpeg->audioMute( 
  3.     'XXX',//原视频 
  4.     'XXX',//处理后保存视频 
  5. ); 

3:视频裁剪

  1. $ffmpeg = new FfmpegVideo(); 
  2. $ffmpeg->clipVideo( 
  3.     'XXX',//原视频 
  4.     'XXX',//处理后保存视频 
  5.     0,//裁剪开始时间 
  6.     10//裁剪时长 
  7. ); 

4:视频拼接

  1. $ffmpeg = new FfmpegVideo(); 
  2. $ffmpeg->concatVideo( 
  3.     ['XXX''XXX'],//需要拼接的视频 
  4.     'XXX',//处理后保存视频 
  5. ); 

5:将音频合并到视频中

  1. $ffmpeg = new FfmpegVideo(); 
  2. $ffmpeg->mergeVideoAudio( 
  3.     'XXX',//视频 
  4.     'XXX',//音频 
  5.     'XXX',//处理后保存视频 
  6.     0//音频插入视频延时时间(秒) 
  7. ); 

6:获取视频信息(长,宽,时长)

  1. $ffmpeg = new FfmpegVideo(); 
  2. $ffmpeg->getAttributes( 
  3.     'XXX',//视频 
  4. );

Tags: ffmpeg

分享到: