我有一些视频托管在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。
请问有人可以阐明所有这些工作原理,或者如果您可以提出改进建议甚至更好?
答案 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,否则您的方案将无法使用
尝试
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)