PHP实现视频转换

2025-01-07 48℃

使用此插件需要注意:

1.服务器必须安装FFmpeg

需要正确配置FFmpeg路径

3.PHP需要有执行shell命令的权限

4.转换大文件可能需要较长时间,建议配置适当的PHP执行时间

限制

建议在使用前测试FFmpeg是否正确安装并可用。

<?php
class videotowebm {
    /**
     * 插件配置方法
     * @return array 配置数组
     */
    function config() {
        $configs = array();
        $configs[] = array(
            'configname' => '启用转换',
            'hash' => 'enabled',
            'inputhash' => 'switch',
            'tips' => '开启后将自动转换上传的视频为WebM格式',
            'defaultvalue' => '1'
        );
        $configs[] = array(
            'configname' => '视频质量',
            'hash' => 'quality',
            'inputhash' => 'number',
            'tips' => 'WebM视频质量(1-51,数值越小质量越高)',
            'defaultvalue' => '51'
        );
        $configs[] = array(
            'configname' => '删除原视频',
            'hash' => 'delete_original',
            'inputhash' => 'switch',
            'tips' => '转换完成后是否删除原始视频文件',
            'defaultvalue' => '1'
        );
        $configs[] = array(
            'configname' => 'FFmpeg路径',
            'hash' => 'ffmpeg_path',
            'inputhash' => 'text',
            'tips' => 'FFmpeg可执行文件的完整路径,如:/usr/bin/ffmpeg',
            'defaultvalue' => '/usr/bin/ffmpeg'
        );
        return $configs;
    }

    /**
     * 钩子定义
     * @return array 钩子数组
     */
    function hook() {
        $hooks = array();
        $hooks[] = array(
            'hookname' => 'upload_convert_video',
            'hookedfunction' => 'cms:common:upload:=',
            'enabled' => 1
        );
        return $hooks;
    }

    /**
     * 监听上传钩子方法
     * @param string $class 被监听的方法名
     * @param array $args 原方法的参数数组
     * @param mixed $return 原方法的返回值
     * @return mixed 处理后的返回值
     */
    function upload_convert_video($class, $args, $return) {
        if(!$return || !isset($return['url']) || empty($return['url']) || $return['error']) return $return;

        // 检查是否启用转换
        if(!config('enabled')) return $return;

        // 获取视频质量设置
        $quality = intval(config('quality'));
        if($quality < 1) $quality = 1;
        if($quality > 51) $quality = 51;

        // 获取FFmpeg路径
        $ffmpeg = config('ffmpeg_path');

        // 获取实际文件路径
        $file_path = rtrim(dirname(dirname(dirname(__FILE__))), DIRECTORY_SEPARATOR) . str_replace('/', DIRECTORY_SEPARATOR, $return['url'][0]);

        // 检查文件是否为视频
        $video_extensions = array('mp4', 'avi', 'mov', 'wmv', 'flv', 'mkv', '3gp');
        $file_extension = strtolower(pathinfo($file_path, PATHINFO_EXTENSION));
        if(!in_array($file_extension, $video_extensions)) {
            return $return;
        }

        // 检查ffmpeg是否可用
        exec("{$ffmpeg} -version", $output, $return_var);
        if($return_var !== 0) {
            error_log('FFmpeg not available at path: ' . $ffmpeg);
            return $return;
        }

        // 生成新的WebM文件名
        $webm_file = substr($file_path, 0, strrpos($file_path, '.')) . '.webm';

        // 构建FFmpeg命令
        $cmd = sprintf(
            '%s -i %s -c:v libvpx-vp9 -crf %d -b:v 0 -c:a libopus %s 2>&1',
            escapeshellarg($ffmpeg),
            escapeshellarg($file_path),
            $quality,
            escapeshellarg($webm_file)
        );

        // 执行转换
        exec($cmd, $output, $return_var);

        if($return_var === 0 && file_exists($webm_file)) {
            // 更新返回的URL为WebM文件
            $return['url'][0] = '/' . substr($webm_file, strlen(dirname(dirname(dirname(__FILE__)))) + 1);

            // 检查是否需要删除原视频文件
            if(config('delete_original')) {
                unlink($file_path);
            }

            return $return;
        }

        error_log('Video conversion failed. Command output: ' . implode("\n", $output));
        return $return;
    }
}
标签: 代码

非特殊说明,本博所有文章均为博主原创。