2012-09-27 113 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;