【问题标题】:FFmpegPHP get thumbnail from external URLFFmpeg PHP 从外部 URL 获取缩略图
【发布时间】:2012-09-19 04:40:26
【问题描述】:

我正在尝试从外部视频(主要是 MP4 和 FLV)创建缩略图。我正在使用FFmpegPHP。我已经使缩略图生成工作正常,但是,我需要先将视频完全加载到我的服务器上。是否可以只流式传输一小部分视频,然后从中提取缩略图?

这是我目前的代码:

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');

有人有什么建议吗?

编辑

正如 Brad 所建议的,这是更新后的代码:

$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);

【问题讨论】:

    标签: php http ffmpeg video-thumbnails


    【解决方案1】:

    FFMPEG 非常适合处理损坏的流。因此,我认为您应该尝试下载该远程媒体的前几兆,并尝试从不完整的文件中获取缩略图。

    首先,删除 file_get_contents() 并使用 cURL。您可以将CURLOPT_WRITEFUNCTION 选项设置为您的自定义函数,该函数逐块写入磁盘上的临时文件。当您收到足够的数据时,从您的函数中返回0,cURL 将停止下载。您将不得不进行试验以查看最佳尺寸。如果您获得的数据太少,您将只能使用最早的帧,或者根本没有帧。太晚了,你在浪费带宽。

    对于某些容器类型,文件信息位于文件末尾。对于那些,我没有给你的建议。缺少编写自己的解码器并从头开始拼接信息,我不知道在不下载整个文件的情况下如何做到这一点。

    【讨论】:

    • 到目前为止,我可以提取缩略图而无需下载整个内容。但是,如果可能的话,我希望获得中间(ish)框架。我可以以某种方式推进我的流然后写 0 直到我到达流的中间,然后获取有关它的信息。另外,有什么方法可以计算我需要多长时间下载文件才能从中获取信息?
    • @jValdron,对于 MPEG 流,您通常可以直接跳到中间。许多其他编解码器和容器也允许这样做。您可以使用范围请求来指定您想要的字节数。另请参阅:stackoverflow.com/a/8507991/362536 大多数服务器都支持它。要获取长度,您可以执行HEAD 请求(如果支持),或GET,然后在收到长度标头后取消。
    • 感谢您与这位布拉德相处。现在,我只需要弄清楚如何获得中间框架:)
    • @jValdron,使用范围请求并从文件中间获取一大块数据。希望你会得到一个容器/格式,FFMPEG 可以用这样的随机针滴来解析。
    【解决方案2】:

    使用基于类结构的 PHP 5、ffmpeg 和 CURL 运行代码如下:

    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;
    

    【讨论】:

      猜你喜欢
      • 2015-09-05
      • 2020-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-25
      • 2015-05-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多