php – 使用curl下载视频的百分比
作者:互联网
我有一些托管在S3(.mp4和.mov)上的视频,其中一些相当大(1.2GB).
我想使用PHP包装器为FFmpeg从每个视频中获取第一帧,但我不想首先下载完整文件.
我真正想要做的是下载一定比例的文件,比如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.
现在,我知道它确实有效,因为我已经运行它,但我不知道它是如何工作的,所以我可以将其转换为获取文件的百分比.
下载1或2 MB的文件适用于较小的文件和mp4文件,但是.mov文件如果小于大约20mb则无法获得第一帧,并且一些帧在获取帧时会抛出除零错误,我猜从上面的函数返回0.
任何人都可以了解所有这些是如何工作的,或者甚至更好,如果你可以建议改进?
解决方法:
myfunction几乎肯定被设置为curl_exec的CURLOPT_WRITEFUNCTION回调函数,如果该函数返回0(或者除$data之外的任何数字),则curl将终止传输,curl_exec将返回CURLE_ABORTED_BY_CALLBACK错误代码.因此,在您下载> = 1 mebibyte后,curl_exec将因CURLE_ABORTED_BY_CALLBACK错误而停止.
我真正想要做的是下载一定比例的文件,比如2%,这样我就可以保证我会得到第一帧. – 根据电影编码,第一个mebibyte可能还不够.有一些编码方案(作为一个具体的例子,.mpeg电影可以这种方式编码),你需要从文件的末尾几个字节来渲染第一帧(iirc for .mpeg它叫做MOOV Atom – on mpeg MOOV原子位于文件末尾的电影,您需要从文件末尾开始几个字节来渲染第一帧.对于所有流优化的.mpeg电影,MOOV原子位于文件的开头,不是结束,你的第一个mebibyte计划会起作用,但是如果它最终你的计划将不起作用,除非整部电影是<1 mebibyte)
>更好的方法是让ffmpeg处理它. ffmpeg将知道要下载多少数据,并且将尝试仅下载所需的部分而不是整个电影,并且您需要像ffmpeg这样的程序来提取第一帧.
尝试
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;
}
它将在url中返回视频的第一帧作为.jpg图像的二进制. (意思是你可以做file_put_contents(‘image.jpg’,getFirstFrameAsJpg($url)); – 有趣的是,如果没有安装ffmpeg,$ret将为NULL,这意味着如果你使用strict_types = 1,你会得到一个异常,否则你会得到一个空字符串.)
ps允许潜在的黑客为此函数指定url之前,请确保验证它确实是一个http url,因为我没有考虑让黑客运行getFirstFrameAsJpg(“/ etc / passwd”)或类似的安全隐患.
如果您需要下载一堆标题,请考虑为ffmpeg设置一个代理方案,其中ffmpeg被告知从一个独特的proxy-url下载,并且仍然让ffmpeg处理要下载的电影的哪些部分,并确保为这样的代理实现http range header,因为如果从需要提取第一帧的电影的最后部分的电影中提取第一帧,ffmpeg将需要它.
(感谢c_14 @ freenode #ffmpeg for image2pipe命令)
标签:php,php-curl,php-ffmpeg 来源: https://codeday.me/bug/20190710/1425046.html