php实现ffmpeg处理视频的实践
发布:smiling 来源: PHP粉丝网 添加日期:2022-05-20 11:10:26 浏览: 评论:0
本文主要介绍了php实现ffmpeg处理视频的实践,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
最近有一个项目需要使用ffmpeg处理视频,这里我写了一个demo,方便我们来实现视频操作
ffmpeg操作demo
- <?php
- namespace common\helpers;
- use common\models\Config;
- use common\models\VideoApiLog;
- use Yii;
- use yii\helpers\ArrayHelper;
- use common\helpers\Universal;
- use yii\helpers\FileHelper;
- use yii\httpclient\Client;
- use yii\web\ServerErrorHttpException;
- /**
- * ffmpeg视频处理
- *
- * @author wangjian
- * @since 0.1
- */
- class FfmpegVideo
- {
- public $ffmpeg = 'ffmpeg';
- public function __construct($ffmpeg = null)
- {
- if ($ffmpeg) {
- $this->ffmpeg = $ffmpeg;
- }
- }
- /**
- * 添加视频文字滚动
- * @param $source string 视频
- * @param $saveFile string 保存文件
- * @param $text string 水印文字
- * @param array $options 水印样式
- * @param int $step 每秒步长
- * @param int $star 出现时间
- */
- public function titleMod($source, $saveFile, $text, $options = [], $step = 20, $star = 0)
- {
- $command = $this->ffmpeg .' -y -i '. $source .' -async 1 -metadata:s:v:0 start_time=0 -vf ';
- $fonts = Yii::getAlias('@webroot') . "/fonts/simsun.ttc";
- $fonts = str_replace('\\', '/', $fonts);
- $fonts = str_replace(':', '\\:', $fonts);
- $command .= '"drawtext=fontfile=\''. $fonts .'\': text=\''. $text .'\'';
- foreach ($options as $key => $value) {
- $command .= ':' . $key . '=' . $value;
- }
- $command .= ':x=\'if(gte(t,'. $star .'),((t-'. $star .') * '. $step .'),NAN)\'';
- $command .= '" ';
- $command .= $saveFile;
- exec($command, $output, $result_code);
- if ($result_code == 0) {
- return true;
- }
- return false;
- }
- /**
- * 图片水印
- * @param $source string 视频
- * @param $saveFile string 保存文件
- * @param $waterImage string 水印图片
- * @param $left integer 水印水平位置
- * @param $top integer 水印垂直位置
- * @param null $star 水印开始时间
- * @param null $duration 水印时长
- */
- public function imageWater($source, $saveFile, $waterImage, $left, $top, $star = null, $duration = null)
- {
- $waterImage = str_replace('\\', '/', $waterImage);
- $waterImage = str_replace(':', '\\:', $waterImage);
- $command = $this->ffmpeg . ' -y -i '. $source .' -vf "movie=\''. $waterImage .'\'[watermark];';
- $command .= '[in][watermark] overlay='. $left .':'. $top;
- if ($star) {
- $end = ($duration) ? $star + $duration : $star;
- $command .= ':enable=\'between(t,'. $star .','. $end .')\'';
- }
- $command .= '[out] " ' . $saveFile;
- exec($command, $output, $result_code);
- if ($result_code == 0) {
- return true;
- }
- return false;
- }
- /**
- * 给视频添加文字水印
- * @param $source string 视频
- * @param $saveFile string 保存文件
- * @param $text string 水印文字
- * @param array $options 水印样式
- * @param null $star 水印开始时间
- * @param null $duration 水印时长
- */
- public function titleWater($source, $saveFile, $text, $options = [], $star = null, $duration = null)
- {
- $command = $this->ffmpeg .' -y -i '. $source .' -vf ';
- $fonts = Yii::getAlias('@webroot') . "/fonts/STZHONGS.TTF";
- $fonts = str_replace('\\', '/', $fonts);
- $fonts = str_replace(':', '\\:', $fonts);
- $command .= '"drawtext=fontfile=\''. $fonts .'\': text=\''. $text .'\'';
- foreach ($options as $key => $value) {
- $command .= ':' . $key . '=' . $value;
- }
- if ($star) {
- $end = ($duration) ? $star + $duration : $star;
- $command .= ':enable=\'between(t,'. $star .','. $end .')\'';
- }
- $command .= '" ';
- $command .= $saveFile;
- exec($command, $output, $result_code);
- if ($result_code == 0) {
- return true;
- }
- return false;
- }
- /**
- * 将音频合并到视频中
- * @param $videoFile string 视频文件
- * @param $audioFile string 音频文件
- * @param $saveFile string 保存文件
- * @param $delay integer 声音插入延时秒数
- */
- public function mergeVideoAudio($videoFile, $audioFile, $saveFile, $delay = null)
- {
- $delayTime = 0;
- if ($delay) {
- $delayTime = $delay * 1000;
- }
- $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;
- exec($command, $output, $result_code);
- if ($result_code == 0) {
- return true;
- }
- return false;
- }
- /**
- * 静音
- */
- public function audioMute($source, $saveFile)
- {
- $command = $this->ffmpeg . ' -y -i '. $source .' -filter:a "volume=0" ' . $saveFile;
- exec($command, $output, $result_code);
- if ($result_code == 0) {
- return true;
- }
- return false;
- }
- /**
- * 提取视频的音频
- * @param $source string 需要提取声音的视频
- * @param $saveFile string 提取声音后保存的音频
- * @return bool
- */
- public function collectAudio($source, $saveFile)
- {
- $command = $this->ffmpeg . ' -y -i '. $source .' -vn -acodec copy ' . $saveFile;
- exec($command, $output, $result_code);
- if ($result_code == 0) {
- return true;
- }
- return false;
- }
- /**
- * 去除视频声音
- * @param $source string 需要去除声音的视频
- * @param $saveFile string 去除声音后保存的视频
- */
- public function removeAudio($source, $saveFile)
- {
- $command = $this->ffmpeg . ' -y -i '. $source .' -an ' . $saveFile;
- exec($command, $output, $result_code);
- if ($result_code == 0) {
- return true;
- }
- return false;
- }
- /**
- * 视频拼接
- * @param $sources array 需要拼接的视频/音频
- * @param $saveFile string 拼接后的视频/音频
- */
- public function spliceVideo($sources, $saveFile)
- {
- $commands = [];
- $temporaryFile = [];
- $basePath = sys_get_temp_dir();
- $index = 0;
- foreach ($sources as $i => $source) {
- $file = $basePath . '/' . $i . '.ts';
- $commands[$index] = $this->ffmpeg . ' -y -i '. $source .' -vcodec copy -acodec copy -vbsf h264_mp4toannexb ' . $file;
- $temporaryFile[] = $file;
- $index++;
- }
- $commands[$index] = $this->ffmpeg . ' -y -i "concat:'. implode('|', $temporaryFile) .'" -acodec copy -vcodec copy -absf aac_adtstoasc ' . $saveFile;
- foreach ($commands as $command) {
- exec($command, $output, $result_code);
- }
- foreach ($temporaryFile as $file) {
- @unlink($file);
- }
- return true;
- }
- /**
- * 视频剪切
- * @param $source string 需要剪切视频/音频
- * @param $saveFile string 剪切后保存视频/音频
- * @param $star string 剪切开始时间
- * @param null $duration string 剪切时长
- */
- public function clipVideo($source, $saveFile, $star, $duration = null)
- {
- $command = $this->ffmpeg . ' -y -ss '. $star;
- if ($duration) {
- $command .= ' -t '. $duration;
- }
- $command .= ' -i '. $source .' -acodec copy ' . $saveFile;
- exec($command, $output, $result_code);
- if ($result_code == 0) {
- return true;
- }
- return false;
- }
- const ROTATE_90 = 'transpose=1';
- const ROTATE_180 = 'hflip,vflip';
- const ROTATE_270 = 'transpose=2';
- /**
- * 视频旋转
- * @param $source string 需要旋转的视频
- * @param $saveFile string 旋转后视频
- * @param $rotate string 旋转角度
- */
- public function transposeVideo($source, $saveFile, $rotate)
- {
- $command = $this->ffmpeg . ' -y -i ' . $source . ' -vf ""transpose=1"" ' . $saveFile;
- exec($command, $output, $result_code);
- if ($result_code == 0) {
- return true;
- }
- return false;
- }
- /**
- * 视频转码
- * @param $source string 需要转码的视频/音频
- * @param $saveFile string 转码后的视频/音频
- */
- public function acodecVideo($source, $saveFile)
- {
- $command = $this->ffmpeg . ' -y -i '. $source .' -acodec copy -vcodec copy -f mp4 ' . $saveFile;
- exec($command, $output, $result_code);
- if ($result_code == 0) {
- return true;
- }
- return false;
- }
- /**
- * 视频拼接
- * @param $sources array 需要拼接的视频/音频
- * @param $saveFile string 拼接后的视频/音频
- */
- public function concatVideo($sources, $saveFile)
- {
- $file = $this->createTemporaryFile();
- $fileStream = @fopen($file, 'w');
- if($fileStream === false) {
- throw new ServerErrorHttpException('Cannot open the temporary file.');
- }
- $count_videos = 0;
- if(is_array($sources) && (count($sources) > 0)) {
- foreach ($sources as $videoPath) {
- $line = "";
- if($count_videos != 0)
- $line .= "\n";
- $line .= "file '". str_replace('\\','/',$videoPath) ."'";
- fwrite($fileStream, $line);
- $count_videos++;
- }
- }
- else {
- throw new ServerErrorHttpException('The list of videos is not a valid array.');
- }
- $command = $this->ffmpeg .' -y -f concat -safe 0 -i '. $file . ' -c copy ' . $saveFile;
- exec($command, $output, $result_code);
- fclose($fileStream);
- @unlink($file);//删除文件
- if ($result_code == 0) {
- return true;
- }
- return false;
- }
- /**
- * 创建一个临时文件
- */
- public function createTemporaryFile()
- {
- $basePath = sys_get_temp_dir();
- if (false === $file = @tempnam($basePath, null)) {
- throw new ServerErrorHttpException('Unable to generate a temporary filename');
- }
- return $file;
- }
- /**
- * 获取视频信息
- * @param $source string 需要获取时长的资源
- */
- public function getAttributes($source)
- {
- ob_start();
- $command = $this->ffmpeg . ' -i "'. $source .'" 2>&1';
- passthru($command);
- $getContent = ob_get_contents();
- ob_end_clean();
- $duration = 0;
- $widht = 0;
- $height = 0;
- if (preg_match("/Duration: (.*?), start: (.*?), bitrate: (\d*) kb\/s/", $getContent, $match)) {
- $matchs = explode(':', $match[1]);
- $duration = $matchs[0] * 3600 + $matchs[1] * 60 + $matchs[2]; //转换播放时间为秒数
- }
- if (preg_match("/Video: (.*?), (.*?), (.*?)[,\s]/", $getContent, $match)) {
- $matchs = explode('x', $match[3]);
- $widht = $matchs[0];
- $height = $matchs[1];
- }
- return [
- 'duration' => intval($duration),
- 'widht' => intval($widht),
- 'height' => intval($height),
- ];
- }
- }
使用简单示例
这里注意如果无法执行ffmpeg,实例化时需要传入ffmpeg的安装地址,例如linux下ffmpeg安装地址为/usr/local/ffmepg,那么实例化时需要传入/usr/local/ffmpeg/bin/ffmpeg
1:给视频添加文字
- $ffmpeg = new FfmpegVideo();
- $ffmpeg ->titleWater(
- 'XXX',//原视频
- 'XXX',//处理后保存视频
- 'XXX',//文字
- [
- 'x' => 30,//水平距离
- 'y' => 30,//垂直距离
- 'fontsize' => 20,//文字大小
- 'fontcolor' => 'red',//文字颜色
- 'shadowy' => 2,//文字阴影
- ],
- 200,//每秒移动步长
- 2//文字出现时间(秒)
- );
2:将视频设为静音
- $ffmpeg = new FfmpegVideo();
- $ffmpeg->audioMute(
- 'XXX',//原视频
- 'XXX',//处理后保存视频
- );
3:视频裁剪
- $ffmpeg = new FfmpegVideo();
- $ffmpeg->clipVideo(
- 'XXX',//原视频
- 'XXX',//处理后保存视频
- 0,//裁剪开始时间
- 10//裁剪时长
- );
4:视频拼接
- $ffmpeg = new FfmpegVideo();
- $ffmpeg->concatVideo(
- ['XXX', 'XXX'],//需要拼接的视频
- 'XXX',//处理后保存视频
- );
5:将音频合并到视频中
- $ffmpeg = new FfmpegVideo();
- $ffmpeg->mergeVideoAudio(
- 'XXX',//视频
- 'XXX',//音频
- 'XXX',//处理后保存视频
- 0//音频插入视频延时时间(秒)
- );
6:获取视频信息(长,宽,时长)
- $ffmpeg = new FfmpegVideo();
- $ffmpeg->getAttributes(
- 'XXX',//视频
- );
Tags: ffmpeg
- 上一篇:PHP基础用法讲解及phpinfo();演示
- 下一篇:最后一页
相关文章
- ·PHP利用FFmpeg读取视频播放时长和码率等信息(2016-07-27)
- ·php使用ffmpeg获取视频信息并截图的实现方法(2019-08-12)
- ·PHP中使用FFMPEG获取视频缩略图和视频总时长实例(2020-11-25)
- ·PHP+FFMPEG实现将视频自动转码成H264标准Mp4文件(2021-04-14)
- ·PHP使用ffmpeg给视频增加字幕显示的方法(2021-05-16)
推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)