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

PHP 整合 FFmpeg 擷取影片縮圖與取得總長度

     編輯:PHP 綜合知識

前置需求

  • 伺服器已安裝 ffmpeg 並加入系統 PATH
  • PHP 可執行 exec()、system() 等指令函數(未被 disable_functions 限制)
  • Web 使用者對影片檔案具讀取權限,對輸出目錄具寫入權限

功能一:擷取影片縮圖

<?php
/**
 * 擷取影片指定時間點的縮圖
 *
 * @param string $videoPath 影片檔案完整路徑
 * @param string $outputPath 輸出圖片完整路徑
 * @param float $timePoint 擷取時間點(秒),預設第 1 秒
 * @param int $width 縮圖寬度,預設 320
 * @param int $height 縮圖高度,預設 240
 * @return bool 是否成功
 */
function getVideoThumbnail($videoPath, $outputPath, $timePoint = 1, $width = 320, $height = 240)
{
    if (!file_exists($videoPath)) {
        trigger_error("影片檔案不存在: $videoPath", E_USER_WARNING);
        return false;
    }

    // 確保輸出目錄存在
    $dir = dirname($outputPath);
    if (!is_dir($dir)) {
        mkdir($dir, 0755, true);
    }

    // 建構 ffmpeg 指令
    // -ss 指定時間點(輸入前較快、輸出後較精準),此處放輸入前
    // -vframes 1 僅擷取 1 幀
    // -f image2 強制圖片格式
    $cmd = sprintf(
        'ffmpeg -y -ss %.3f -i %s -vframes 1 -s %dx%d %s 2>&1',
        $timePoint,
        escapeshellarg($videoPath),
        $width,
        $height,
        escapeshellarg($outputPath)
    );

    $output = [];
    $returnVar = 0;
    exec($cmd, $output, $returnVar);

    if ($returnVar !== 0) {
        error_log("FFmpeg 縮圖失敗: " . implode("\n", $output));
        return false;
    }

    return file_exists($outputPath) && filesize($outputPath) > 0;
}

// 使用範例
getVideoThumbnail('/var/www/videos/demo.mp4', '/var/www/thumbs/demo_1s.jpg', 3);
?>

功能二:取得影片總長度與建立時間

<?php
/**
 * 取得影片總長度(秒)與檔案建立時間
 *
 * @param string $videoPath 影片檔案路徑
 * @return array|false ['duration' => 秒數, 'created_at' => 'Y-m-d H:i:s'] 或 false
 */
function getVideoInfo($videoPath)
{
    if (!file_exists($videoPath)) {
        return false;
    }

    // 使用 ffprobe 更精準、輸出格式固定 (JSON)
    $cmd = sprintf(
        'ffprobe -v error -show_entries format=duration -of json %s 2>&1',
        escapeshellarg($videoPath)
    );

    $output = [];
    $returnVar = 0;
    exec($cmd, $output, $returnVar);

    if ($returnVar !== 0) {
        error_log("ffprobe 失敗: " . implode("\n", $output));
        return false;
    }

    $json = json_decode(implode('', $output), true);
    $duration = isset($json['format']['duration']) ? (float)$json['format']['duration'] : 0;
    $createdAt = date('Y-m-d H:i:s', filectime($videoPath));

    return [
        'duration' => $duration,          // 總秒數 (浮點數)
        'duration_formatted' => gmdate('H:i:s', $duration), // 格式化 HH:MM:SS
        'created_at' => $createdAt,
    ];
}

// 使用範例
$info = getVideoInfo('/var/www/videos/demo.mp4');
if ($info) {
    echo "長度: {$info['duration_formatted']} ({$info['duration']} 秒)\n";
    echo "建立時間: {$info['created_at']}\n";
}
?>

常見問題排查

症狀可能原因解決方向
exec() 回傳 127找不到 ffmpeg 指令確認 ffmpeg 在 PATH 中,或使用絕對路徑 /usr/bin/ffmpeg
輸出檔案 0 bytes權限不足 / 參數錯誤檢查 Web 使用者對輸出目錄寫入權限;加 2>&1 捕獲錯誤訊息
縮圖時間點不準-ss 放在 -i 之後快速模式:-ss 放在 -i 前;精準模式:放在後但較慢
中文路徑失敗Shell 轉義問題一律使用 escapeshellarg() 包裹路徑

效能建議

  • 大量影片處理請使用**佇列系統**(如 Laravel Queue、Redis + Worker)非同步執行,避免阻塞 Web 程序。
  • 縮圖尺寸建議固定幾組規格(如 320x180, 640x360),避免任意尺寸造成儲存浪費。
  • 若僅需影片長度,ffprobe 比 ffmpeg -i 解析快得多且輸出穩定。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved