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

PHP + FFmpeg 實現視頻自動轉碼為 H.264/MP4:環境配置、擴展編譯、轉碼調用與大檔案上傳完整方案

     編輯:PHP 綜合知識

構建視頻上傳轉碼系統需解決:大檔案上傳限制、FFmpeg 靜態編譯支援 H.264、PHP 安全調用外部程式、非同步處理架構。本文提供從環境搭建到生產部署的完整方案。

一、PHP 大檔案上傳配置(突破預設 2MB/8MB 限制)

; php.ini 關鍵參數
file_uploads = On
upload_tmp_dir = /tmp/php_uploads  ; 獨立目錄,權限 700 www-data
upload_max_filesize = 2G           ; 單檔上限
post_max_size = 2G                 ; POST 總上限 > upload_max_filesize
max_execution_time = 7200          ; 2小時,轉碼極耗時
max_input_time = 7200              ; 接收上傳資料時間
memory_limit = 512M                ; PHP 記憶體,轉碼由外部程式處理不佔此限
; 關閉輸出緩衝避免大檔案記憶體暴增
output_buffering = Off

Nginx 同步調整:

# nginx.conf http 區塊
client_max_body_size 2G;
proxy_read_timeout 7200s;
proxy_send_timeout 7200s;

二、FFmpeg + H.264 (libx264) 靜態編譯安裝(CentOS 7/8、Ubuntu 通用)

1. 安裝編譯工具鏈與依賴庫

# CentOS/RHEL
yum install -y gcc gcc-c++ make automake autoconf libtool \
    nasm yasm pkgconfig zlib-devel bzip2-devel \
    libX11-devel freetype-devel fontconfig-devel

# Ubuntu/Debian
apt-get update && apt-get install -y build-essential pkg-config \
    nasm yasm libz-dev libbz2-dev libx11-dev libfreetype6-dev libfontconfig1-dev

2. 編譯安裝 x264 (H.264 編碼器核心庫)

cd /usr/local/src
git clone --branch stable --depth 1 https://code.videolan.org/videolan/x264.git
cd x264
./configure --prefix=/usr/local --enable-shared --enable-pic --disable-cli
make -j$(nproc)
make install
ldconfig

3. 編譯安裝 FFmpeg(啟用 libx264、GPL、非自由編碼器)

cd /usr/local/src
git clone --depth 1 https://git.ffmpeg.org/ffmpeg.git
cd ffmpeg
./configure \
  --prefix=/usr/local \
  --enable-gpl \
  --enable-nonfree \
  --enable-libx264 \
  --enable-shared \
  --disable-static \
  --disable-doc \
  --disable-debug \
  --enable-pthreads \
  --enable-libfreetype \
  --enable-libfontconfig \
  --extra-cflags="-I/usr/local/include" \
  --extra-ldflags="-L/usr/local/lib" \
  --extra-libs="-lpthread -lm -ldl"
make -j$(nproc)
make install
ldconfig

# 驗證
ffmpeg -version
# 輸出應包含 --enable-libx264 --enable-gpl
ffmpeg -encoders | grep libx264
# 應顯示 libx264 可用

三、PHP 安全調用 FFmpeg 轉碼

1. 禁用危險函式,僅開啟 exec 等必要函式

; php.ini
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
; ↑ 生產環境建議全禁用,改用 Symfony Process 或獨立 Worker 進程

更安全架構:PHP 僅寫入任務隊列(Redis/RabbitMQ),獨立 Worker 進程(PHP CLI/Go/Python)消費隊列調用 FFmpeg,完全隔離 Web 進程。

2. 同步阻塞調用(簡單場景/內部工具)

<?php
function transcodeToMp4(string $input, string $output): bool {
    // 輸入驗證:防止命令注入
    $input = escapeshellarg(realpath($input));
    $output = escapeshellarg($output);

    // FFmpeg 參數詳解:
    // -y 覆蓋輸出
    // -i 輸入檔
    // -c:v libx264 視頻編碼 H.264
    // -preset medium 壓縮速度/品質平衡
    // -crf 23 品質常數 (18-28 越小越好)
    // -c:a aac 音頻編碼 AAC
    // -b:a 128k 音頻碼率
    // -movflags +faststart 移動 moov atom 到開頭,支援網頁邊下邊播
    $cmd = "ffmpeg -y -i {$input} -c:v libx264 -preset medium -crf 23 -c:a aac -b:a 128k -movflags +faststart {$output} 2>&1";

    $outputLines = [];
    $returnCode = 0;
    exec($cmd, $outputLines, $returnCode);

    if ($returnCode !== 0) {
        error_log("FFmpeg 轉碼失敗: " . implode("\n", $outputLines));
        return false;
    }
    return true;
}

// 使用
$ok = transcodeToMp4('/uploads/raw/video.mov', '/uploads/mp4/video.mp4');
?>

3. 非同步隊列架構(生產標準)

<?php
// Web 端:接收上傳 → 存檔 → 寫入 Redis 隊列 → 立即返回任務 ID
$taskId = bin2hex(random_bytes(16));
$task = [
    'id' => $taskId,
    'input' => $savedPath,
    'output' => "/processed/{$taskId}.mp4",
    'status' => 'pending',
    'created_at' => time(),
];
$redis->lPush('video_transcode_queue', json_encode($task));
echo json_encode(['task_id' => $taskId, 'status' => 'pending']);

// Worker 端 (cli/worker.php):長期運行進程消費隊列
while (true) {
    $json = $redis->rPop('video_transcode_queue');
    if (!$json) { sleep(1); continue; }
    $task = json_decode($json, true);
    $redis->hSet("task:{$task['id']}", 'status', 'processing');
    $ok = transcodeToMp4($task['input'], $task['output']);
    $redis->hSet("task:{$task['id']}", [
        'status' => $ok ? 'done' : 'failed',
        'finished_at' => time(),
    ]);
    // 可觸發 Webhook/推送通知前端
}
?>

四、上傳組件選型與 Session 保持

  • WebUploader / Uppy / FineUploader:支援分片上傳、斷點續傳、進度條、多檔案。
  • Flash 上傳組件 (Uploadify 等) 已淘汰:Flash 不支援現代瀏覽器,且 Session 傳遞極其麻煩(User-Agent 不一致導致 Session 丟失)。
  • Session 保持方案:若必須舊組件,在上傳請求帶入 PHPSESSID 參數,PHP 端 session_id($_POST['PHPSESSID']); session_start(); 恢復。

五、常見坑點與優化

問題解決
轉碼極慢/CPU 100%調整 -preset ultrafast/superfast 犧牲壓縮率換速度;限制 FFmpeg 執行緒 -threads 2
輸出 MP4 無法邊下邊播必須加 -movflags +faststart 或轉碼後執行 qt-faststart
音視頻不同步加 -async 1 或 -vsync 1;檢查源檔案時間基
大檔案轉碼中斷Worker 進程監控磁碟空間、記憶體;支援斷點續傳需分片轉碼(高階)
權限錯誤 Permission denied確保 www-data 對上傳/輸出目錄有 rwx;FFmpeg 二進制可執行

遵循「大檔上傳配置 → FFmpeg 靜態編譯 H.264 → 隊列非同步轉碼 → 安全調用隔離」四步驟,即可構建穩定、可擴展的視頻轉碼服務。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved