首页后端开发其他后端知识php实现ffmpeg处理视频的过程是怎么样的?

php实现ffmpeg处理视频的过程是怎么样的?

时间2024-03-25 13:10:03发布访客分类其他后端知识浏览426
导读:这篇文章给大家分享的是“php实现ffmpeg处理视频的过程是怎么样的?”,文中的讲解内容简单清晰,易于理解,而且实用性强吗,对大家认识和了解“php实现ffmpeg处理视频的过程是怎么样的?”都有一定的帮助,有需要的朋友可以参考了解看看,...
这篇文章给大家分享的是“php实现ffmpeg处理视频的过程是怎么样的?”,文中的讲解内容简单清晰,易于理解,而且实用性强吗,对大家认识和了解“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',//视频
);
    



通过以上内容的阐述,相信大家对“php实现ffmpeg处理视频的过程是怎么样的?”已经有了进一步的了解,更多相关的问题,欢迎关注网络或到官网咨询客服。

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!


若转载请注明出处: php实现ffmpeg处理视频的过程是怎么样的?
本文地址: https://pptw.com/jishu/652800.html
PHP中一维数组怎样转二维,方法是什么? PHP substr怎么去最后一位字符,方法是什么?

游客 回复需填写必要信息