[英]php video upload and ffmpeg won't create a thumbnail
我正在尝试为我的项目制作视频上传功能。 但是我对ffmpeg部分有问题。 ffmpeg已经安装在我的服务器上。 但我无法获得任何缩略图。 我尝试使用以下代码创建缩略图:
$videoa = exec("/usr/bin/ffmpeg -i $videoUrlp.flv -f flv -s 650x390 $videoUrlp.mp4 2>&1");
$videob = exec("/usr/bin/ffmpeg -i $videoUrlp.mp4 -vcodec png -ss 00:00:5 -s 650x390 -vframes 1 -an -f rawvideo $videoUrlp.png");
但是当我使用var_dump();
对于var_dump($videoa);
和var_dump($videob);
string(74) " https://mywebsite.com/uploads/video/ey1kXNew_video.flv : 输入/输出错误" string(0) ""
另外,如果我像这样使用shell_exec
:
$videoa = shell_exec("/usr/bin/ffmpeg -i $videoUrlp.flv -f flv -s 650x390 $videoUrlp.mp4");
$videob = shell_exec("/usr/bin/ffmpeg -i $videoUrlp.mp4 -vcodec png -ss 00:00:5 -s 650x390 -vframes 1 -an -f rawvideo $videoUrlp.png");
和var_dumps()
给我NULL
NULL
。
请帮助我我错在哪里。
这是我的完整视频上传代码:
$valid_formats = array("mp4","MP4","flv");
if(isset($_POST) and $_SERVER['REQUEST_METHOD'] == "POST") {
$name = $_FILES['uploading']['name'];
$size = $_FILES['uploading']['size'];
if(strlen($name)) {
$ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
$name = alphaID(microtime(true) * 10000).'_video';
if(in_array($ext,$valid_formats)) {
if($size<(50024*50024)) {
$GetVideoName = $name;
$video_ext=$ext;
$tmp = $_FILES['uploading']['tmp_name'];
if(move_uploaded_file($tmp, $videoPath.$GetVideoName.'.'.$video_ext)) {
$videoUrlp = $base_url.'uploads/video/'.$GetVideoName;
$videoa = exec("/usr/bin/ffmpeg -i $videoUrlp.flv -f flv -s 650x390 $videoUrlp.mp4 2>&1");
$videob = exec("/usr/bin/ffmpeg -i $videoUrlp.mp4 -vcodec png -ss 00:00:5 -s 650x390 -vframes 1 -an -f rawvideo $videoUrlp.png");
echo var_dump($videoa);
echo var_dump($videob);
} else {
echo "Fail upload folder with read access.";
}
} else
echo "Image file size max 1 MB";
} else
echo "invalidvieo";
} else
echo "Please select image..!";
exit;
}
我也这样测试过:
echo exec("/usr/bin/ffmpeg -i $videoUrlp.flv -ar 22050 -ab 32 -f flv -s 780x400 $videoUrlp.$video_ext");
echo exec("/usr/bin/ffmpeg -i $videoUrlp.$video_ext -deinterlace -an -ss 1 -t 00:00:05 -r 1 -y -vcodec mjpeg -f mjpeg $videoUrlp.png 2>&1");
我看到以下回声
video:71kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.000000%
再试一次,我得到了这个注释: https : //mywebsite.com/uploads/video/1547892356_video.flv :连接被拒绝
echo exec("/usr/bin/ffmpeg -i $videoUrlp.flv -ar 22050 -ab 32 -f flv -s 780x400 $videoUrlp.$video_ext");
echo exec("/usr/bin/ffmpeg -i $videoUrlp.$video_ext -deinterlace -an -ss 1 -t 00:00:05 -r 1 -y -vcodec mjpeg -f mjpeg $videoUrlp.png 2>&1");
这是最后一个 shell_exec 输出:
$local = 'https://website.com/uploads/video/'.$GetVideoName.'.'.$video_ext;
$localTumb = 'https://website.com/uploads/video/'.$GetVideoName.'.png';
echo shell_exec("/usr/bin/ffmpeg -i $local -deinterlace -an -ss 1 -t 00:00:05 -r 1 -y -vcodec mjpeg -f mjpeg $localTumb 2>&1");
ffmpeg 版本 2.8.15 版权所有 (c) 2000-2018 FFmpeg 开发人员使用 gcc 4.8.5 (GCC) 20150623 (Red Hat 4.8.5-36) 配置:--prefix=/usr --bindir=/usr/bin
--datadir=/usr/share/ffmpeg --incdir=/usr/include/ffmpeg --libdir=/usr/lib64 --mandir=/usr/share/man --arch=x86_64 --optflags='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic' --extra-ldflags ='-Wl,-z,relro' --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libvo-amrwbenc --enable-version3 --enable-bzlib --disable-crystalhd --enable- gnutls --enable-ladspa --enable-libass --enable-libcdio --enable-libdc1394 --enable-libfdk-aac --enable-nonfree --disable-indev=jack --enable-libfreetype --enable-libgsm --enable-libmp3lame --enable-openal --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-libschroedinger --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libvorbis --enable-libv4l2 --enable-libx264 --enable-libx265 --enable-libxvid --enable-x11grab --enable-avfilter --enable-avresample --enable-postproc --enable-pthreads --disable-static --启用共享--enable-gpl --disable-debug --disable-stripping --shlibdir=/usr/lib64 --enable-runtime-cpudetect libavutil 54. 31.100 / 54. 31.100 libavcodec 56. 60.100 / 56. 60.100. libav40.16 / 56 40.101 libavdevice 56. 4.100 / 4.100 56 5 libavfilter 40.101 / 5. 40.101 libavresample 2. 1. 0/2 1 0 libswscale 3. 1.101 / 1.101 3 1 libswresample 2.101 / 1 2.101 libpostproc 53 . 3.100 / 53. 3.100 输入 #0, mov,mp4,m4a,3gp,3g2,mj2, from ' https://website.com/uploads/video/e0J6HwtK_video.mp4 ': 元数据: major_brand : mp42 minor_brand : 0 compatible : isomp42 creation_time : 2018-01-01 12:09:49 持续时间: 00:00:41.49, 开始: 0.000000, 比特率: 230 kb/s Stream #0:0(und): Video: h264 (Constrained1 Baseline) / 0x31637661), yuv420p, 240x360 [SAR 1:1 DAR 2:3], 158 kb/s, 9.73 fps, 9.73 tbr, 19462 tbn, 19.46 tbc (default) 元数据: 视频处理程序 (默认): 0 :音频:aac (LC) (mp4a / 0x6134706D),44100 Hz,单声道,fltp,71 kb/s(默认)元数据:creation_time: 2018-01-01 12:09:49 handler_name:IsoMedia 文件由 Google 制作,5-11-2011 [swscaler @ 0xc8c580] 已弃用像素格式,请确保您已正确设置范围输出 #0、mjpeg 到 ' https: //website.com/uploads/video/e0J6HwtK_video.png ':元数据:major_brand:mp42 minor_version:0 compatible_brands:isommp42 编码器:Lavf56.40.101 Stream #0:0(und):视频:mjpeg,yuvj43602p [SAR 1:1 DAR 2:3], q=2-31, 200 kb/s, 1 fps, 1 tbn, 1 tbc(默认)元数据:handler_name:VideoHandler 编码器:Lavc56.60.100 mjpeg 流映射:Stream #0 :0 -> #0:0 (h264 (native) -> mjpeg (native)) 按 [q] 停止,[?] 帮助帧= 5 fps=0.0 q=1.6 Lsize= 100kB time=00:00: 05.00 比特率= 163.9kbits/s dup=0 drop=32 视频:100kB 音频:0kB 字幕:0kB 其他流:0kB 全局头:0kB 复用开销:0.000000%
如果您使用的是 https,则您的 ffmpeg 必须配置 ssl 支持( https 上的 ffmpeg 失败)。
参数必须被转义,你不能只是将变量作为参数转储在那里,网址包含像&
东西&
它在 shell 中具有特殊含义......例如这个
exec("/usr/bin/ffmpeg -i $videoUrlp.flv -f flv -s 650x390 $videoUrlp.mp4 2>&1");
应该是这样的:
exec("/usr/bin/ffmpeg -i ".escapeshellarg($videoUrlp.flv)." -f flv -s 650x390 ".escapeshellarg($videoUrlp.mp4)." 2>&1");
但..
请有人可以帮助我吗?
这里有 2 个获取缩略图的函数,getThumbPng2() 将首先使用 curl 下载整个视频,将其保存到一个临时文件中,然后使用 ffmpeg 提取 url(如果 ffmpeg 不是使用 http/https/ 构建的,这会更安全)任何支持,或者 ffmpeg 是否被防火墙或其他任何东西阻止,但缺点是它可能会慢得多)
并且第一个函数从 ffmpeg 获取缩略图而不先获取视频(这可能要快得多,因为 ffmpeg 只会读取所需的部分而不是下载整个视频,但由于上述原因可能无法正常工作)
function getThumbPng2(string $uri, string &$imageBinary=NULL, string &$stderr=NULL):bool{
$ch=curl_init($uri);
if(!$ch){
$imageBinary=$stderr="curl_init() failed";
return false;
}
$tmph=tmpfile();
curl_setopt_array($ch,array(
CURLOPT_SSL_VERIFYPEER=>false,
CURLOPT_SSL_VERIFYHOST=>false,
CURLOPT_FILE=>$tmph
));
if(!curl_exec($ch)){
$imageBinary=$stderr="curl error: ".curl_errno($ch).": ".curl_error($ch);
curl_close($ch);
fclose($tmph);
return false;
}
curl_close($ch);
$ret=getThumbPng(stream_get_meta_data($tmph)['uri'],$imageBinary,$stderr);
fclose($tmph);
return $ret;
}
function getThumbPng(string $uri,string &$imageBinary=NULL, string &$stderr=NULL):bool{
$imageBinary="";
$stderr="";
$descriptorspec = array(
0 => array("pipe", "rb"), // stdin
1 => array("pipe", "wb"), // stdout
2 => array("pipe","wb") // stderr
);
$cmd="ffmpeg -i ".escapeshellarg($uri)." -ss 00:00:3 -s 650x390 -vframes 1 -c:v png -f image2pipe -";
// var_dump($cmd);
$proc = proc_open($cmd, $descriptorspec, $pipes);
if(!$proc){
$stderr="failed to start ffmpeg, proc_open(\"ffmpeg\",...) failed. (why? don't know, and PHP has no way of telling us either, afaik.)";
return false;
}
fclose($pipes[0]);// by default stdin is *inherited*, which is not what we want,
// so to avoid the default behaviour, we explicitly create a stdin pipe and close it.
$fetch=function()use(&$pipes,&$imageBinary,&$stderr){
$tmp=stream_get_contents($pipes[1]);
if(is_string($tmp)){
$imageBinary.=$tmp;
}
$tmp=stream_get_contents($pipes[2]);
if(is_string($tmp)){
$stderr.=$tmp;
}
};
while(($status=proc_get_status($proc))['running']){
usleep(10*1000);
$fetch();
}
$fetch();
fclose($pipes[1]);
fclose($pipes[2]);
$ret=$status['exitcode'];
proc_close($proc);
//var_dump($ret);
return ($ret===0);
}
用法示例:
<?php
if(getThumbPng("http://files.4x4norway.no/2018/vik2.webm",$imageBinary,$stderr)){
echo "got a thumbnail! (the png binary data is in the \$imageBinary variable.)";
}else{
var_dump($imageBinary);
echo "failed to create thumbnail! error: {$stderr}";
}
使用此代码:` //thumb 路径应添加到以下代码中 //test for thumb
$dir_img='uploads/';
$mediapath='123.jpg';
$file_thumb=create_movie_thumb($dir_img.$mediapath,$mediapath,$mediaid);
$name_file=explode(".",$mediapath);
$imgname="thumb_".$name_file[0].".jpg";
/*
Function to create video thumbnail using ffmpeg
*/
function create_movie_thumb($src_file,$mediapath,$mediaid)
{
global $CONFIG, $ERROR;
$CONFIG['ffmpeg_path'] = '/usr/local/bin/'; // Change the path according to your server.
$dir_img='uploads/';
$CONFIG['fullpath'] = $dir_img."thumbs/";
$src_file = $src_file;
$name_file=explode(".",$mediapath);
$imgname="thumb_".$name_file[0].".jpg";
$dest_file = $CONFIG['fullpath'].$imgname;
if (preg_match("#[A-Z]:|\\\\#Ai", __FILE__)) {
// get the basedir, remove '/include'
$cur_dir = substr(dirname(__FILE__), 0, -8);
$src_file = '"' . $cur_dir . '\\' . strtr($src_file, '/', '\\') . '"';
$ff_dest_file = '"' . $cur_dir . '\\' . strtr($dest_file, '/', '\\') . '"';
} else {
$src_file = escapeshellarg($src_file);
$ff_dest_file = escapeshellarg($dest_file);
}
$output = array();
if (eregi("win",$_ENV['OS'])) {
// Command to create video thumb
$cmd = "\"".str_replace("\\","/", $CONFIG['ffmpeg_path'])."ffmpeg\" -i ".str_replace("\\","/" ,$src_file )." -an -ss 00:00:05 -r 1 -vframes 1 -y ".str_replace("\\","/" ,$ff_dest_file);
exec ("\"$cmd\"", $output, $retval);
} else {
// Command to create video thumb
$cmd = "{$CONFIG['ffmpeg_path']}ffmpeg -i $src_file -an -ss 00:00:05 -r 1 -vframes 1 -y $ff_dest_file";
exec ($cmd, $output, $retval);
}
if ($retval) {
$ERROR = "Error executing FFmpeg - Return value: $retval";
if ($CONFIG['debug_mode']) {
// Re-execute the command with the backtick operator in order to get all outputs
// will not work if safe mode is enabled
$output = `$cmd 2>&1`;
$ERROR .= "<br /><br /><div align=\"left\">Cmd line : <br /><span style=\"font-size:120%\">" . nl2br(htmlspecialchars($cmd)) . "</span></div>";
$ERROR .= "<br /><br /><div align=\"left\">The ffmpeg program said:<br /><span style=\"font-size:120%\">";
$ERROR .= nl2br(htmlspecialchars($output));
$ERROR .= "</span></div>";
}
@unlink($dest_file);
return false;
}
$return = $dest_file;
//@chmod($return, octdec($CONFIG['default_file_mode'])); //silence the output in case chmod is disabled
return $return;
}`
我认为您可以检查服务器上的 ffmpeg 安装文件。
$ffmpeg = trim(shell_exec('whereis ffmpeg')); // This will show you which path FFMPEG
if (empty($ffmpeg))
{
die('ffmpeg not available');
}else{
echo $ffmpeg;
}
然后试试这个:
$cmd = shell_exec("$ffmpeg -i $videoUrlp.mp4 -ss 00:00:02.000 -vframes 1 $videoUrlp.png");
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.