FLV (Flash Video) 為舊式串流格式,仍有存量資產需處理。本文分析一個完整的 FLV 縮圖擷取腳本,支援時間點、百分比定位、直接輸出或儲存檔案,並修正原碼潛在問題。
<?php
/**
* FLV 影片縮圖擷取器
* 參數:
* file - FLV 檔案路徑 (必要)
* time - 時間點 HH:MM:SS (預設 00:00:01)
* percent - 百分比 0-100 (優先於 time)
* browser - true 輸出圖片串流, false 儲存檔案
*/
$videofile = $_GET['file'] ?? 'video.flv';
$time = $_GET['time'] ?? '00:00:01';
$percent = isset($_GET['percent']) ? (float)$_GET['percent'] : null;
$browser = ($_GET['browser'] ?? 'true') === 'true';
// 安全:限制存取目錄
$allowedDir = '/var/www/videos/';
$realVideo = realpath($videofile);
$realAllowed = realpath($allowedDir);
if (!$realVideo || strpos($realVideo, $realAllowed) !== 0) {
http_response_code(403);
exit('Forbidden');
}
// 百分比轉時間
if ($percent !== null) {
$cmd = sprintf('ffprobe -v error -show_entries format=duration -of csv=p=0 %s', escapeshellarg($realVideo));
$duration = (float) trim(shell_exec($cmd));
if ($duration > 0) {
$seekSec = $duration * $percent / 100;
$time = gmdate('H:i:s', $seekSec);
}
}
// 驗證時間格式
if (!preg_match('/^\d{2}:\d{2}:\d{2}$/', $time)) {
$time = '00:00:01';
}
// 執行擷取
$codec = 'png'; // 或 mjpeg
$format = $browser ? 'image2pipe' : 'image2';
$output = $browser ? '-' : escapeshellarg(dirname($realVideo) . '/thumb_%d.' . $codec);
$cmd = sprintf(
'ffmpeg -v 0 -y -i %s -ss %s -vframes 1 -vcodec %s -f %s %s',
escapeshellarg($realVideo),
escapeshellarg($time),
$codec,
$format,
$output
);
if ($browser) {
header('Content-Type: image/' . $codec);
passthru($cmd);
} else {
shell_exec($cmd);
echo "縮圖已儲存";
}
?>
realpath() 驗證檔案在允許目錄內。ffprobe 專門讀取中繼資料,速度快、輸出穩定。split():原碼使用已移除的 split(),改用 explode() 或 sscanf()。image2pipe 輸出 stdout,image2 輸出檔案序列。ffmpeg -ss 00:00:10 -i input.flv ... 速度極快(關鍵幀定位),但可能不精確。FLV 縮圖擷取核心同一般影片,重點在於參數安全、路徑驗證、ffprobe 取得長度、非同步架構。修正舊碼相容性問題後可穩定運行。希望本文對您的 PHP 程式設計有所幫助。