最近有一个项目需要使用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',//视频
);

到此这篇关于php实现ffmpeg处理视频的实践的文章就介绍到这了,更多相关php ffmpeg处理视频内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

php实现ffmpeg处理视频的实践的更多相关文章

  1. HTML5 播放 RTSP 视频的实例代码

    目前大多数网络摄像头都是通过 RTSP 协议传输视频流的,但是 HTML 并不标准支持 RTSP 流。本文重点给大家介绍HTML5 播放 RTSP 视频的实例代码,需要的朋友参考下吧

  2. 从iOS应用程序发送帖子到PHP脚本不工作…简单的解决方案就像

    我之前已经做了好几次了但是由于某些原因我无法通过这个帖子…我尝试了设置为_POST且没有的变量的PHP脚本……当它们未设置为发布时它工作精细.这是我的iOS代码:这里是PHP的一大块,POST变量不在正确的位置?我想这对于更有经验的开发人员来说是一个相当简单的答案,感谢您的帮助!解决方法$_POST是一个数组,而不是一个函数.您需要使用方括号来访问数组索引:

  3. ios – ffmpeg不会在我的项目中构建,在示例应用程序中运行良好

    我已经尝试了几个小时,但我无法弄清楚这一点.我在我的项目中使用KXMOVIE.我按照指示下载并编译了ffmpeg二进制文件.示例应用程序实际上工作正常,但我不能让它在我自己的项目中构建.所有.a文件都在那里,它与示例应用程序中的文件完全相同.当我尝试为模拟器构建时,我收到此错误.我究竟做错了什么?我甚至不知道从哪里开始.解决方法您还需要与libiconv链接.假设你拥有它,请将-liconv作为链接选项.

  4. ios – 如何将YUVJ420P中的FFMPEG AVFrame转换为AVFoundation cVPixelBufferRef?

    我在YUVJ420P中有一个FFMPEGAVFrame,我想用CVPixelBufferCreateWithBytes将它转换为CVPixelBufferRef.我想这样做的原因是使用AVFoundation来显示/编码帧.我选择了kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange并尝试转换它,因为AVFrame有三个平面的数据Y480Cb240Cr24

  5. swift学习2 元组 tuples

    swift中出现了一种新的数据结构,非常牛掰的元组tuples如果懂PHP的猿,会发现这个元组和PHP的数组非常类似,同样是可以默认不指定key,也可以指定key目前的学习疑问是,如何进行元组的遍历?

  6. 尝试使用swift mailer,gmail smtp,php发送邮件

    这里是我的代码:在运行时出现此错误…

  7. android – UnsatisfiedLInkError使用NDK链接到FFMPEG

    我使用bambuser的文件编译了FFMPEGforandroid.编译运行正常.没有错误.我还确保在build.sh中更改包名称.但是,一旦我尝试链接到文件,手机就会抛出UnsatisfiedLinkError.这是Androkd.mk文件:Video.c很简单:相应的Java代码也很简单:但我得到这个错误:我尝试用Java手动加载预构建的共享库(bambuser文件)(使用System.loa

  8. android – 使用FFmpeg检索专辑封面

    我正在开发一个依赖于FFmpeg来检索音频元数据的Android应用程序.我知道可以使用FFMpeg以编程方式检索专辑封面.但是,一旦您解码了艺术,如何生成图像文件以便在应用程序中使用?

  9. 如何从android流式传输到ffserver

    我需要从一个Android摄像头/文件流到一个远程ffserver,它将播放我的视频.我可以通过发出如下命令在ubuntu的桌面上执行此操作:或流式传输这样的文件:所以基本上我希望能够从android做到以上.经过几次搜索,这是我到目前为止所做的–我遇到了这个链接http://bambuser.com/opensource,我从中下载了ffmpeg源并构建了它.构建输出几件事:1.共享库[liba

  10. 如何在Android中下载m3u8格式的媒体文件

    我需要解析m3u8媒体文件,这是一个播放列表,并下载实际的媒体内容.据我了解,以下是涉及的过程:>解析m3u8文件并获取’.TS’块>检索完所有块后,将其合并为单个文件>将合并的TS文件转换为mp4格式.不幸的是,我找不到任何lib/模块来执行上述步骤.任何人都可以提供更好的方法或工作样本来处理和下载m3u8文件吗?

随机推荐

  1. PHP个人网站架设连环讲(一)

    先下一个OmnihttpdProffesinalV2.06,装上就有PHP4beta3可以用了。PHP4给我们带来一个简单的方法,就是使用SESSION(会话)级变量。但是如果不是PHP4又该怎么办?我们可以假设某人在15分钟以内对你的网页的请求都不属于一个新的人次,这样你可以做个计数的过程存在INC里,在每一个页面引用,访客第一次进入时将访问时间送到cookie里。以后每个页面被访问时都检查cookie上次访问时间值。

  2. PHP函数学习之PHP函数点评

    PHP函数使用说明,应用举例,精简点评,希望对您学习php有所帮助

  3. ecshop2.7.3 在php5.4下的各种错误问题处理

    将方法内的函数,分拆为2个部分。这个和gd库没有一点关系,是ecshop程序的问题。会出现这种问题,不外乎就是当前会员的session或者程序对cookie的处理存在漏洞。进过本地测试,includes\modules\integrates\ecshop.php这个整合自身会员的类中没有重写integrate.php中的check_cookie()方法导致,验证cookie时返回的username为空,丢失了登录状态,在ecshop.php中重写了此方法就可以了。把他加到ecshop.php的最后面去就可

  4. NT IIS下用ODBC连接数据库

    $connection=intodbc_connect建立数据库连接,$query_string="查询记录的条件"如:$query_string="select*fromtable"用$cur=intodbc_exec检索数据库,将记录集放入$cur变量中。再用while{$var1=odbc_result;$var2=odbc_result;...}读取odbc_exec()返回的数据集$cur。最后是odbc_close关闭数据库的连接。odbc_result()函数是取当前记录的指定字段值。

  5. PHP使用JpGraph绘制折线图操作示例【附源码下载】

    这篇文章主要介绍了PHP使用JpGraph绘制折线图操作,结合实例形式分析了php使用JpGraph的相关操作技巧与注意事项,并附带源码供读者下载参考,需要的朋友可以参考下

  6. zen_cart实现支付前生成订单的方法

    这篇文章主要介绍了zen_cart实现支付前生成订单的方法,结合实例形式详细分析了zen_cart支付前生成订单的具体步骤与相关实现技巧,需要的朋友可以参考下

  7. Thinkphp5框架实现获取数据库数据到视图的方法

    这篇文章主要介绍了Thinkphp5框架实现获取数据库数据到视图的方法,涉及thinkPHP5数据库配置、读取、模型操作及视图调用相关操作技巧,需要的朋友可以参考下

  8. PHP+jquery+CSS制作头像登录窗(仿QQ登陆)

    本篇文章介绍了PHP结合jQ和CSS制作头像登录窗(仿QQ登陆),实现了类似QQ的登陆界面,很有参考价值,有需要的朋友可以了解一下。

  9. 基于win2003虚拟机中apache服务器的访问

    下面小编就为大家带来一篇基于win2003虚拟机中apache服务器的访问。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  10. Yii2中组件的注册与创建方法

    这篇文章主要介绍了Yii2之组件的注册与创建的实现方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下

返回
顶部