PHP自动获取视频时长的方法

摘要

最近在给客户开发短视频项目模块中遇到自动获取上传视频的时长并用于外部展示的需求。

刚开始想到用比较笨的方法,就是上传之前手动写入视频文件的大小,无奈嫌麻烦,寻求其它方法。

也是一个比较笨的方法------ ffmpeg

通过下载 ffmpeg,在面板中安装 PHP 5.6,并放开 exec 函数。在建立的新站点中,使用 PHP5.6 版本。

为了安全 PHP 5.6 允许执行外部程序,且其他站点不使用 PHP 5.6 版本,由 PHP 程序执行 ffmpeg,获取时间时长并存储到数据库中。

1、下载 ffmpeg

打开 https://www.gyan.dev/ffmpeg/builds/

点击左侧导航菜单中的 release builds,在右侧,找到,ffmpeg-release-essentials.zip ,点击以下载。

根据需要下载工具,点击左侧导航菜单中的 tools,在右侧,找到,ffmpeg-tools.zip ,点击以下载。

包含的工具有:

aviocat crypto_bench cws2fws ffescape ffeval ffhash fourcc2pixfmt graph2dot ismindex pktdumper probetest qt-faststart seek_print sidxindex venc_data_dump zmqsend

将压缩包中的 bin 目录解压,如存放在 d:\ffmpeg\bin 中。

2、设置环境变量

在"此电脑"中,点击右键,选择"属性",之后选择"高级系统设置"。

在"高级选择卡"中点击"环境变量",在"系统变量"中,找到"Path",双击编辑后,添加新的环境变量值,如 d:\ffmpeg\bin。

3、创建站点

绑定的域名,填写,127.0.0.2(只用于内部访问),PHP 版本设置为 5.6,且在禁用函数中,移除 exec。

编辑 .user.ini,增加站点目录,ffmpeg 程序目录

powershell 复制代码
open_basedir="d:/wwwroot/syncvideoinfo/;D:/wwwroot/zhandian/;D:/ffmpeg/bin/;C:/Windows/Temp/;C:/Temp/;D:/BtSoft/temp/session/"

4、使用 GetVidoSize.php

因为需要设置 .env 所在目录,及解析视频地址

之后读取数据库中存储的视频地址,并获取时间,然后,写入到数据库中

php 复制代码
<?php
/**
 * 获取视频时间长度
 */

class GetVidoSize
{
    /** @var string 锁文件路径 */
    private $lockFile;
    /** @var string env 配置文件路径 */
    private $dbEnvFile;
    /** @var string env 待解析视频目录 */
    private $parseVideoDir;

    function __construct()
    {
        $this->lockFile      = "./sync.lock";
        $this->dbEnvFile     = "../kaoshi/.env";
        $this->parseVideoDir = "../kaoshi/public";
    }

    public function canSync($write = false, $val = 0)
    {

        if ($write) {
            return file_put_contents($this->lockFile, $val) ? true : false;
        }
        $data = file_get_contents($this->lockFile);
        if ($data) {
            return false;
        } else {
            return true;
        }
    }

    public function getVideoMins($file)
    {
        $command = "ffmpeg -i " . $file . " 2>&1";
        exec($command, $output);
        // 从输出中提取视频信息

        $line = implode('', $output);

        // 提取视频时长
        if (preg_match("/Duration: (.*?), /", $line, $matches)) {
            $time = explode(':', $matches[1]);
            return (intval($time[0]) * 60 * 60) + intval($time[1]) * 60 + intval($time[2]);
        }

        return 0;

    }

    /**
     * @throws Exception
     */
    public function sync()
    {
        $res = [
            'count' => 0,
            'list'  => [],

        ];

        if (!$this->canSync()) {
            throw new Exception("Please hold on ...");
        }
        $this->canSync(true, date('Y-m-d H:i:s'));
        $dbConfig = parse_ini_file($this->dbEnvFile, true);

        try {
            // 创建连接
            $conn = new PDO("mysql:host={$dbConfig['database']['hostname']};dbname={$dbConfig['database']['database']}",
                $dbConfig['database']['username'],
                $dbConfig['database']['password']);
            // 设置 PDO 错误模式为异常
            $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

            $list         = $conn->query("SELECT id,moive_file FROM fa_exam_course_movie where mins=0");
            $res['count'] = count($list->rowCount() > 0 ? $list : []);
            foreach ($list as $row) {
                $t   = time();
                $sec = $this->getVideoMins($this->parseVideoDir . $row['moive_file']);
                // SQL 更新语句
                $sql = "update fa_exam_course_movie set mins=:sec,updatetime=:t where id=:id";

                // 预处理 SQL 语句
                $stmt = $conn->prepare($sql);

                // 绑定参数
                $stmt->bindParam(':sec', $sec);
                $stmt->bindParam(':t', $t);
                $stmt->bindParam(':id', $row['id']);

                // 执行更新操作
                $stmt->execute();
                $res['list'][] = [
                    'id'         => $row['id'],
                    'moive_file' => $row['moive_file'],
                    'length'     => $sec,
                    'status'     => $stmt->rowCount(),

                ];

            }

        } catch (PDOException $e) {
            throw new Exception($e->getMessage());
        }

        // 关闭连接
        $conn = null;
        $this->canSync(true, 0);
        return $res;
    }
}

try {
    $data = (new SyncVideo())->sync();
    echo date('Y-m-d H:i:s'), " count: ", $data['count'], PHP_EOL;
    foreach ($data['list'] as $v) {
        echo $v['id'], "\t", $v['moive_file'], "\t", $v['length'], "\t", $v['status'], PHP_EOL;
    }
} catch (Exception $e) {
    echo $e;
}
// 程序正常退出
exit(0);

5、增加计划任务

任务类型为,访问 URL,每1分钟访问一次,地址为 http://127.0.0.1/GetVidoSize.php

OK 到此就完成了,虽然说方法还是有点笨 但是至少可以实现。

版权声明 草邦软件开发 草邦CMS系统 草邦办公管理系统 草邦媒介资源系统

本软件不提供任何形式的明示或暗示担保,包括但不限于对适销性,特定目的的适用性和非侵权性的担保。无论是由于软件,使用或其他方式产生的,与之有关或与之有关的合同,侵权或其他形式的任何索赔,损害或其他责任,作者或版权所有者概不负责。

相关推荐
青锐CC1 小时前
webman使用中间件验证指定的控制器及方法[青锐CC]
中间件·前端框架·php
安步当歌1 小时前
【WebRTC】视频发送链路中类的简单分析(下)
网络·音视频·webrtc·视频编解码·video-codec
lqj_本人2 小时前
鸿蒙next版开发:音频并发策略扩展(ArkTS)
音视频
heilai43 小时前
workerman的安装与使用
c++·websocket·http·php·phpstorm·visual studio code
烬奇小云3 小时前
认识一下Unicorn
android·python·安全·系统安全
编码小袁6 小时前
PHP:通往动态Web开发世界的桥梁
开发语言·前端·php
liuxin334455667 小时前
高效编程训练:Spring Boot系统设计与实践
数据库·spring boot·php
Wx-bishekaifayuan8 小时前
PHP动物收容所管理系统-计算机设计毕业源码94164
java·css·spring boot·spring·spring cloud·servlet·php
翔云API9 小时前
PHP开发示例-vin码识别接口-引领汽车行业数字化新风向
开发语言·php
ac-er88889 小时前
如何对PHP的API接口权限认证
开发语言·php