laravel项目中使用FFMPeg 剪裁视频

发布于:2025-03-16 ⋅ 阅读:(24) ⋅ 点赞:(0)

# 运行环境需安装的软件
ffmpeg

# 安装的扩展
pbmedia/laravel-ffmpeg: ^8.3

# 扩展文档 https://packagist.org/packages/pbmedia/laravel-ffmpeg

# 引入的类
use FFMpeg\Coordinate\TimeCode;
use FFMpeg\Format\Video\X264;
use FFMpeg\Exception\RuntimeException;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use ProtoneMedia\LaravelFFMpeg\Support\FFMpeg;


# 处理方法
    public function cutUrlVideo($ossVideoPath)
    {

        $maxDuration = env('CLIP_VIDEO_SECONDS'); // 需要的时长

        // 原始视频在 OSS 中的路径
        $ossVideoPath  = 'uploads/resource/2025/02/27/HzFdjwYQwUehk2WChH1DHAroKXMo0EkrG2lh1gQp.mp4';

        // 生成本地临时文件路径
        $tempInputPath = 'temp/input_' . uniqid() . '.mp4';
        $tempOutputPath = 'temp/output_' . uniqid() . '.mp4';

        // 将 OSS 视频下载到本地临时文件
        Storage::disk('public')->put($tempInputPath, Storage::disk('oss')->get($ossVideoPath));

        try {
            // 获取下载到本地的媒体对象
            $media = FFMpeg::fromDisk('public')->open($tempInputPath);

            // 获取视频总时长(秒)
            $duration = $media->getDurationInSeconds();

            // 根据时长判断处理逻辑
            if ($duration > $maxDuration) {
                $start = TimeCode::fromSeconds(0);
                $end = TimeCode::fromSeconds($maxDuration);
                $clipFilter = new \FFMpeg\Filters\Video\ClipFilter($start, $end);

                $media->addFilter($clipFilter)
                    ->export()
                    ->toDisk('public')
                    ->inFormat(new X264)
                    ->save($tempOutputPath);

                // 生成最终要使用的文件路径
                $folderName = "/uploads/resource/" . date("Y/m/d");
                $extension = pathinfo(basename($ossVideoPath), PATHINFO_EXTENSION);
                $newFilename = Str::uuid()->toString() . '.' . $extension;
                // 上传到 OSS
                $ossPath = "{$folderName}/{$newFilename}";
                Storage::disk('oss')->put($ossPath, Storage::disk('public')->get($tempOutputPath));

                return $ossPath;
            } else {
                return $ossVideoPath;
            }

        } finally {
            // 清理临时文件
            Storage::disk('public')->delete([$tempInputPath, $tempOutputPath]);
        }
    }