您的当前位置:首页>全部文章>文章详情

php调用ffmpeg视频分段

发表于:2024-07-02 10:49:48浏览:153次TAG: #PHP #ThinkPHP #视频分段 #ffmpeg

引言

由于H5中的video标签加载MP4大视频的时候经常会黑屏,而且在ios无法兼容的,所以我们需要对MP4大视频进行分段加载。我们这里采用php调用ffmpeg来对视频分段

FFmpeg安装和使用:https://blog.dazijie.com/article/142

getID3插件:https://www.getid3.org/

<?php
namespace app\common\utils;
require_once ROOT_PATH.'extend/getID3/getid3/getid3.php';

/**
 * 视频操作类
 $video = new \app\common\utils\Video();
 $video->section(getcwd().'/upload/20240611/xxxxx.mp4');
 * Class Video
 * @package app\common\utils
 * linux需安装:ffmpeg 这个软件
 * php下载getID3插件,并放置在extend目录下面(TP5)
 */
class Video {

    private $info;
    private $video_file;
    private $error;

    public function __construct()
    {

    }

    /**
     * 视频分段
     * @param string $video_file 视频文件,使用绝对路径
     * @param string $output_dir 输出的路径,最后面以/结尾,示例:/path/to/your/video/
     * @param int $duration 每间隔几秒分段
     * @return array
     */
    public function section($video_file,$output_dir = '',$duration = 30)
    {
        $this->video_file = $video_file;
        $basic_info = pathinfo($this->video_file);
        // $basic_info 值为
        //array(4) {
        //    ["dirname"] => string(56) "/www/wwwroot/xxxx.xxxx.com/public/uploads/20240611"  // 文件夹路径
        //    ["basename"] => string(36) "c22375f4bfd86c3d8bf807b218fc023d.mp4" // 文件名(带后缀)
        //    ["extension"] => string(3) "mp4" // 后缀
        //    ["filename"] => string(32) "c22375f4bfd86c3d8bf807b218fc023d" // 文件名(不带后缀)
        //}
        $filename = $basic_info['filename'];
        $extension = $basic_info['extension'];
        if (!$output_dir) {
            $output_dir = $basic_info['dirname']."/";
        }
        $this->checkDir($output_dir);
        $total_sec = $this->getSec();
        $data = [];
        // 计算每个视频的起始时间和结束时间
        for ($i = 0; $i < $total_sec; $i += $duration) {
            $startTime = $i;
            $endTime = $startTime + $duration - 1;

            // 构建FFmpeg命令
            $output_file = "{$output_dir}{$filename}_{$i}.{$extension}";
            $ffmpegCommand = "ffmpeg -i {$this->video_file} -ss {$startTime} -to {$endTime} -c copy {$output_file}";

            // 执行FFmpeg命令
            exec($ffmpegCommand, $output, $returnVar);

            // 检查命令执行是否成功
            if ($returnVar === 0) {
                array_push($data,str_replace(getcwd(),'',$output_file));
            } else {
                $this->setError("视频分割失败,时间段:{$startTime} 至 {$endTime},文件:{$output_file}");
            }
        }
        return $data;
    }

    /**
     * 检测文件夹,不存在则创建
     * @param $dir
     * @return bool
     */
    public function checkDir($dir)
    {
        if (!is_dir($dir)) {
            mkdir($dir, 0777, true);
        }
        return true;
    }
    /**
     * 使用getID3获取视频信息
     * @return array|false|float|int
     */
    public function getInfo()
    {
        $video_path = $this->video_file;
        if ($this->info) {
            return $this->info;
        }
        $getid3 = new \getID3;
        $this->info = $getid3->analyze($video_path);
        return $this->info;
    }

    /**
     * 获取视频时长(秒数)
     * @return false|float|int
     */
    public function getSec()
    {
        $info = $this->getInfo();
        if (isset($info['playtime_seconds'])) {
            $sec = ceil($info['playtime_seconds']);
        } else {
            $sec = 0;
        }
        return $sec;
    }

    /**
     * 获取异常信息
     * @return mixed
     */
    public function getError()
    {
        return $this->error;
    }

    /**
     * 设置异常
     * @param $value
     * @return bool
     */
    private function setError($value)
    {
        $this->error = $value;
        return false;
    }
}