Laravel 10.x 里如何使用ffmpeg

原理上很简单,就是使用命令行去调用ffmpeg,然后分析一下输出是不是有错误。

安装

首先安装 symfony/process,主要用于包装一下,用来代替 exec, passthru, shell_exec and system 。

composer require symfony/process
composer require symfony/filesystem

要注意 Laravel 10.x 是锁定 symfony 6.4的,所以无法安装最新的 7.0 ,但用起来也没什么问题。

创建服务

照例创建服务,服务类:VideoMakerService,接口类:VideoMakerContract,服务提供类:VideoMakerProvider,快捷名称:videomaker,Facade类:VideoMaker

参考 保姆级教程:Laravel中添加Service

暂时就提供一个服务,把图片生成几秒视频。

    public function imageToBaseVideo(string $imageFile, string $targetFile, float $duration): bool{
        // $workingDir=$this->ffmpegTempDir;
        $params=[
            $this->ffmpegFile,
            '-loop', '1',
            '-framerate', '30',
            '-i', $imageFile,
            '-vf', 'scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2,setsar=1',
            '-c:v', 'libx264',
            '-t', $duration,
            '-y',
            $targetFile,
        ];
        return ExecHelper::run($params);
    }

这里使用了 ExecHelper 来运行,只是对Process做了包装

class ExecHelper{

    public static function run(array $params){
        $success=false;
        $process = new Process($params);
        $code=$process->run(function ($type, $buffer): void {
            if (Process::ERR === $type) {
                Log::debug('ERR > ', $buffer);
            } else {
                Log::debug('OUT > ', $buffer);
            }
        });
        $success=$code===0;

        return $success;
    }
}

创建命令行

命令行类:ProcessVideo

    public function handle(VideoMakerContract $videoMakerContract)
    {
        $imageFile = $this->argument('imageFile');
        $targetFile = $this->argument('targetFile');
        $duration = $this->option('duration');
        // print params
        $this->info('imageFile: '.$imageFile.' , targetFile: '.$targetFile.' , duration: '.$duration);
        // convert to absolute path
        $imageFile=PathHelper::toAbsolutePath($imageFile);
        // validate imageFile
        if(!file_exists($imageFile)){
            $this->error('imageFile not exists');
            return;
        }
        $targetFile=PathHelper::toAbsolutePath($targetFile);
        // validate targetFile
        if(!file_exists($targetFile)){
            $this->error('targetFile not exists');
            return;
        }
        // validate duration
        if(!is_numeric($duration)){
            $this->error('duration must be numeric');
            return;
        }
        $success=$videoMakerContract->imageToBaseVideo($imageFile, $targetFile, $duration);

        $this->info('success: '.$success);
    }

参考:保姆级教程:Laravel里如何创建自己的命令行 

这里面用到PathHelper就是简要地补全一下路径

class PathHelper{
    public static function toAbsolutePath(string $path): string{
        return Path::makeAbsolute($path, self::currentPath());
    }

    public static function currentPath(): string{
        return realpath('.');
    }
}

准备好图片

复制任意一张图片到 storage/app/tmp/t.jpg

运行命令行

./artisan process:video ./storage/app/tmp/t.jpg ./storage/app/tmp/t.mp4 --duration=5

 

轻松生成 t.mp4 ,ffmpeg 的参数可以参考专栏里其他文章

你可能感兴趣的:(ffmpeg,php,laravel,laravel,php)