下载一定比例的curl视频

时间:2018-09-03 09:23:03

标签: php php-curl php-ffmpeg

我有一些视频托管在S3上(.mp4和.mov),其中一些视频很大(1.2GB以上)。
我想使用FFmpeg的PHP包装器从每个视频中获取第一帧,但我不想先下载完整文件。

我真正想做的是下载一定比例的文件,例如2%,这样我就可以保证获得第一帧。

我找到了一种方法,可以在此处下载文件的1mb:https://code.i-harness.com/en/q/c09357

但是,我不太了解这段代码的以下部分是如何仅下载1mb。

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;
}

对我来说,将大小设置为文件的大小,然后如果大小小于1mb,则返回长度,否则返回0。
现在,我知道它确实可以运行,因为我已经运行了它,但是我不知道它如何运行,因此我可以将其转换为获取文件百分比的方式。

对于较小的文件和mp4文件,下载1或2 MB的文件是可以的,但是如果.mov文件少于20mb,则.mov文件将无法获得第一帧,并且某些帧会抛出division by zero获取框架时出现错误,我想从上面的函数返回0。

请问有人可以阐明所有这些工作原理,或者如果您可以提出改进建议甚至更好?

1 个答案:

答案 0 :(得分:0)

myfunction几乎可以肯定设置为curl_exec的CURLOPT_WRITEFUNCTION回调函数,如果该函数返回0(或$ data大小以外的任何数字),则curl将终止传输,而curl_exec将返回{{1 }} 错误代码。因此,当您下载> = 1 MB后,curl_exec将停止并显示CURLE_ABORTED_BY_CALLBACK错误。

CURLE_ABORTED_BY_CALLBACK-根据影片编码,第一个兆字节可能不够。有一些编码方案(例如,.mpeg电影可以用这种方式编码),您需要从文件末尾开始一些字节来渲染第一帧(.mpeg的iirc,称为What I really want to do is download a certain percentage of the file, something like 2%, so that I can guarantee that I will get the first frame. -在MOOV原子位于文件末尾的mpeg电影中,您需要从文件末尾开始几个字节来呈现第一帧。对于所有流优化的.mpeg电影,MOOV原子位于文件的开头文件而不是结尾,并且您的MOOV Atom方案可以使用,但是如果最后,除非整个影片为<1 MB,否则您的方案将无法使用

  • 更好的方法是让ffmpeg处理它。 ffmpeg将知道要下载多少数据,并且将尝试仅下载所需的部分,而不是整个电影,并且您需要ffmpeg之类的程序来在以后提取第一帧。

尝试

1st mebibyte

它将返回URL中视频的第一帧作为.jpg图像的二进制文件。 (这意味着您可以进行function getFirstFrameAsJpg(string $url):string{ if(file_exists("/dev/null")){ $ret=shell_exec("ffmpeg -i ".escapeshellarg($url)." -f image2pipe -frames 1 -r 1 -c:v:1 jpeg - 2>/dev/null"); }else{ // windows, probably, where /dev/null isn't supported but NUL works the same way. $ret=shell_exec("ffmpeg -i ".escapeshellarg($url)." -f image2pipe -frames 1 -r 1 -c:v:1 jpeg - 2>NUL"); } return $ret; } -有趣的是,如果未安装ffmpeg,则$ ret将为NULL,这意味着如果您使用strict_types = 1,则会得到异常,否则将得到空字符串。) / p>

ps,在您允许潜在的黑客指定此功能的URL之前,请确保确认它确实是http URL,因为我没有考虑让黑客运行file_put_contents('image.jpg',getFirstFrameAsJpg($url));或类似的安全性。 / p>

如果您需要下载大量标题,请考虑为ffmpeg设置代理方案,在该方案中,ffmpeg被告知从唯一的代理URL下载,并且仍然让ffmpeg处理要下载电影的哪些部分,并确保为这样的代理实现http range header,因为ffmpeg在从电影中提取第一帧时需要ffmpeg,而电影的最后一部分需要提取第一帧。

(感谢image2pipe命令的c_14 @ freenode #ffmpeg)