我正在尝试为我的项目制作视频上传功能。但是我对ffmpeg部分有问题。 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: 输入/输出错误“字符串(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");
答案 0 :(得分:3)
如果您使用的是https,则必须为ffmpeg配置ssl支持(ffmpeg over https fails)。
答案 1 :(得分:1)
使用此代码: ` //应该在下面的代码中添加缩略图路径 //测试拇指
$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;
}`
答案 2 :(得分:1)
参数必须转义,您不能只是在其中转储变量作为参数,URL包含诸如&
之类的东西,它们在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提取网址(如果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}";
}
答案 3 :(得分:1)
我认为您可以在服务器上检查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");