首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 使用 FFmpeg 獲取視頻時長、碼率、分辨率、編碼等元信息完整實現

     編輯:PHP 綜合知識

前置條件

  • 服務器安裝 FFmpeg:ffmpeg -version 可見版本信息
  • PHP 配置允許 passthru/exec(部分虛擬主機禁用)
  • 知曉 FFmpeg 可執行文件路徑(如 /usr/bin/ffmpeg)

核心解析函數

function getVideoInfo($filePath) {
    if (!file_exists($filePath)) {
        return ['error' => '文件不存在'];
    }
    
    // 定義 ffmpeg 探測命令
    $cmd = sprintf('ffmpeg -i "%s" 2>&1', $filePath);
    
    // 執行並捕獲輸出(stderr 包含元信息)
    ob_start();
    passthru($cmd);
    $output = ob_get_clean();
    
    $info = [
        'file' => $filePath,
        'size' => filesize($filePath),
    ];
    
    // 1. 解析時長、碼率
    if (preg_match('/Duration: ([\d:]+), start: ([\d.]+), bitrate: (\d+) kb\/s/', $output, $m)) {
        $info['duration'] = $m[1];           // HH:MM:SS.xx
        $info['start'] = (float)$m[2];       // 秒
        $info['bitrate'] = (int)$m[3];       // kbps
        
        // 轉換為總秒數
        $parts = explode(':', $m[1]);
        $info['duration_seconds'] = $parts[0]*3600 + $parts[1]*60 + $parts[2];
        $info['play_time'] = $info['duration_seconds'] + $info['start'];
    }
    
    // 2. 解析視頻流信息
    if (preg_match('/Video: (\w+), ([^,]+), ([^,]+)/', $output, $m)) {
        $info['vcodec'] = $m[1];             // h264, hevc, vp9...
        $info['vformat'] = $m[2];            // yuv420p 等
        $info['resolution'] = $m[3];         // 1920x1080
        
        if (preg_match('/(\d+)x(\d+)/', $m[3], $rm)) {
            $info['width'] = (int)$rm[1];
            $info['height'] = (int)$rm[2];
        }
    }
    
    // 3. 解析音頻流信息
    if (preg_match('/Audio: (\w+), (\d+) Hz/', $output, $m)) {
        $info['acodec'] = $m[1];             // aac, mp3, opus...
        $info['asamplerate'] = (int)$m[2];   // 44100, 48000...
    }
    
    return $info;
}

// 使用示例
$videoInfo = getVideoInfo('/var/www/videos/demo.mp4');
print_r($videoInfo);

輸出示例

Array
(
    [file] => /var/www/videos/demo.mp4
    [size] => 15728640
    [duration] => 00:01:30.45
    [start] => 0.000000
    [bitrate] => 1250
    [duration_seconds] => 90
    [play_time] => 90
    [vcodec] => h264
    [vformat] => yuv420p
    [resolution] => 1920x1080
    [width] => 1920
    [height] => 1080
    [acodec] => aac
    [asamplerate] => 44100
)

進階:使用 ffprobe 獲取結構化 JSON(推薦)

function getVideoInfoJson($filePath) {
    $cmd = sprintf(
        'ffprobe -v quiet -print_format json -show_format -show_streams "%s" 2>&1',
        $filePath
    );
    ob_start();
    passthru($cmd);
    $json = ob_get_clean();
    
    $data = json_decode($json, true);
    if (json_last_error() !== JSON_ERROR_NONE) {
        return ['error' => 'ffprobe 輸出解析失敗'];
    }
    
    $result = ['file' => $filePath, 'size' => filesize($filePath)];
    
    // Format 信息
    if (isset($data['format'])) {
        $f = $data['format'];
        $result['duration'] = (float)$f['duration'];
        $result['bitrate'] = (int)$f['bit_rate'];
        $result['format_name'] = $f['format_name'];
    }
    
    // Streams 信息
    foreach ($data['streams'] ?? [] as $stream) {
        if ($stream['codec_type'] === 'video') {
            $result['video'] = [
                'codec' => $stream['codec_name'],
                'width' => $stream['width'],
                'height' => $stream['height'],
                'pix_fmt' => $stream['pix_fmt'],
                'r_frame_rate' => $stream['r_frame_rate'],
                'avg_frame_rate' => $stream['avg_frame_rate'],
            ];
        } elseif ($stream['codec_type'] === 'audio') {
            $result['audio'] = [
                'codec' => $stream['codec_name'],
                'sample_rate' => $stream['sample_rate'],
                'channels' => $stream['channels'],
                'channel_layout' => $stream['channel_layout'],
            ];
        }
    }
    
    return $result;
}

ffprobe JSON 輸出優勢

  • 結構化、可擴展、無需正則解析
  • 包含幀率、編碼配置文件、色彩空間等豐富信息
  • 官方推薦的程序化調用方式

常見問題與解決

問題原因解決
passthru 被禁用虛擬主機安全策略遷移至 VPS/雲服務器,或使用 PHP-FFMpeg 库(純 PHP 解析容器格式)
執行超時大文件探測耗時設置 set_time_limit(0),或異步隊列處理
路徑含空格/特殊字符命令注入風險使用 escapeshellarg() 包裹路徑
權限不足PHP 進程無法讀取文件確保文件可讀,或將視頻存儲在 PHP 可訪問目錄

生產環境建議

  1. 使用 PHP-FFMpeg (composer require php-ffmpeg/php-ffmpeg) 面向對象封裝,避免直接調用命令
  2. 視頻上傳後異步提取元信息,存入數據庫,前端直接讀取
  3. 建立視頻處理管道:上傳 → 轉碼/截圖/元信息提取 → CDN 分發
  4. 監控 FFmpeg 進程資源佔用,防止佔滿 CPU/內存
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved