2012-09-27 151 views
6

我試圖從外部視頻創建縮略圖,主要是MP4和FLV。我正在使用FFmpegPHP。我已經有縮略圖生成工作正常,但是,我需要首先在我的服務器上完全加載視頻。是否有可能僅流式傳輸視頻的一小部分,然後從中提取縮略圖?FFmpegPHP從外部URL獲取縮略圖

下面的代碼我到目前爲止:

require_once PRIV . 'Vendor/FFmpegPHP/FFmpegAutoloader.php'; 

// Download the whole video. 
$video = file_get_contents($_PUT['video']); 
$file = 'path_to_cache'; 
file_put_contents($file, $video); 

$movie = new FFmpegMovie($file); 

// Generate the thumbnail. 
$thumb = $movie->getFrame($movie->getFrameCount()/2); 
$thumb->resize(320, 240); 
imagejpeg($thumb->toGDImage(), 'path_to_thumb'); 

任何人有一個建議?

編輯

布拉德建議,這裏是更新後的代碼:

$file = CACHE . 'moodboard_video_' . rand(); 
$fh = fopen($file, 'w'); 
$size = 0; 

curl_setopt($ch, CURLOPT_URL, $_PUT['video']); 
curl_setopt($ch, CURLOPT_HEADER, 0); 
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($ch, $data) use($fh, &$size){ 
    $length = fwrite($fh, $data); 

    if($length === FALSE) { 
     return 0; 
    } else { 
     $size += $length; 
    } 

    // Downloads 1MB. 
    return $size < 1024 * 1024 * XXXXXX ? $length : 0; 
}); 

curl_exec($ch); 

fclose($fh); 
curl_close($ch); 

// Create the thumbnail. 
$thumb = $movie->getFrame(XXXXXX); 
$thumb->resize(static::DEFAULT_THUMBNAIL_WIDTH, $thumb->getHeight()/$thumb->getWidth() * static::DEFAULT_THUMBNAIL_WIDTH); 
$image = $thumb->toGDImage(); 
imagejpeg($image, PRIV . static::THUMBNAILS_PATH . $item->getLastInsertIdentifier() . '_' . static::DEFAULT_THUMBNAIL_WIDTH); 

回答

3

FFMPEG大約用碎流的工作非常好。因此,我認爲你應該嘗試下載該遠程媒體的前幾個兆字節,並嘗試從不完整的文件中獲取縮略圖。

首先,放下file_get_contents()並使用cURL。您可以將CURLOPT_WRITEFUNCTION選項設置爲您的自定義函數,該函數按塊寫入磁盤上的臨時文件。當您收到足夠的數據時,請從您的功能中返回0,cURL將停止下載。你將不得不嘗試看看最佳尺寸是多少。如果數據太少,則只能使用最早的幀,或者根本沒有幀。太晚了,你正在浪費帶寬。

對於某些容器類型,文件信息位於文件末尾。對於那些,我沒有給你一個建議。由於沒有編寫自己的解碼器和最終的信息拼接在一起,我不知道如何下載整個文件。

+0

到目前爲止,我可以提取的縮略圖,而無需下載整個事情。但是,如果可能的話,我希望能夠獲得中間(ish)幀。我可以以某種方式推進我的流,然後寫0直到我到達流的中間,只是獲得有關信息。另外,有什麼方法可以計算我需要下載文件以從中獲取信息的時間? – jValdron

+0

@jValdron,對於MPEG流,你可以經常跳到中間。許多其他編解碼器和容器也允許相同。你可以使用範圍請求來指定你想要的字節。另請參閱:http://stackoverflow.com/a/8507991/362536大多數服務器都支持它。爲了獲得長度,你可以做'HEAD'請求(如果支持的話)或'GET',然後在你收到長度標題後取消。 – Brad

+0

感謝您與布拉德共度時光。現在,我只需要弄清楚如何獲得中間框架:) – jValdron

0

運行的代碼與PHP 5,ffmpeg的和捲曲與基於類的結構如下:

require_once 'PHP_CURFN/ffmpeg-php-master/FFmpegFrame.php'; 
    require_once 'PHP_CURFN/ffmpeg-php-master/FFmpegAutoloader.php'; 

class MyVideoTest{ 

private $fh=""; 
private $size=0; 
private $ch=""; 

public function __construct(){ 

       $video = 'http://[hosturl]/video/41a669911fd635167475d7530bffcc9f.mp4'; 
       $file = 'PHP_CURFN/cache/tmp_video_' . rand(); 


       $this->ch = curl_init(); 
       $this->fh = fopen ($file, 'w+'); 
       $this->ch = curl_init($video); 

       $this->size = 0; 
       curl_setopt($this->ch, CURLOPT_URL, $video); 
       curl_setopt($this->ch, CURLOPT_HEADER, 0); 


       curl_setopt($this->ch, CURLOPT_WRITEFUNCTION, array($this, "myfunction")); 

       curl_exec($this->ch); 

       fclose($this->fh); 
       curl_close($this->ch); 
       $movie = new FFmpegMovie($file); 
       // Create the thumbnail. 

       $thumb = $movie->getFrame(2); 
       $thumb->resize(320, 240); 
       $image = $thumb->toGDImage(); 
       imagejpeg($image, 'PHP_CURFN/cache' . $item->getLastInsertIdentifier() . '_' . 320); 

} 
function myfunction($ch, $data)  { 
     $length = fwrite($this->fh, $data); 
     $size=&$this->size; 

     if($length === FALSE) { 
      return 0; 
     } else { 
      $size += $length; 
     } 

     // Downloads 1MB. 

     return $size < 1024 * 1024 *1 ? $length : 0; 
} } 


$MyVideoTest= new MyVideoTest(); 
pr($MyVideoTest); 
exit;