php视频上传和ffmpeg不会创建缩略图

Azz*_*zzo 4 php 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");
Run Code Online (Sandbox Code Playgroud)

但是我将其var_dump();用于var_dump($videoa);var_dump($videob);

字符串(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");
Run Code Online (Sandbox Code Playgroud)

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;
              }
Run Code Online (Sandbox Code Playgroud)

我也这样测试过:

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");
Run Code Online (Sandbox Code Playgroud)

我看到以下回声

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");
Run Code Online (Sandbox Code Playgroud)

这是最后一个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");    
Run Code Online (Sandbox Code Playgroud)

ffmpeg版本2.8.15版权所有(c)2000-2018,使用gcc 4.8.5(GCC)20150623(Red Hat 4.8.5-36)构建的FFmpeg开发人员配置:--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-nutnuts --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-shared --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 libavformat 56. 40.101 / 56. 40.101 libavdevice 56. 4.100 / 56. 4.100 libavfilter 5. 40.101 / 5. 40.101 libavresample 2. 1. 0 / 2. 1. 0 libswscale 3. 1.101 / 3. 1.101 libswresample 1. 2.101 / 1. 2.101 libpostproc 53. 3.100 / 53. 3.100输入#0,mov,mp4,m4a,3gp,3g2,mj2,来自“https://website.com/uploads/video/e0J6HwtK_video.mp4 ':元数据:major_brand:mp42 minor_version:0compatible_brands:isommp42 creation_time:2018-01-01 12:09:49持续时间:00:00:41.49,开始: 0.000000,比特率:230 kb / s流#0:0(und):视频:h264(受约束的基线)(avc1 / 0x31637661),yuv420p,240x360 [SAR 1:1 DAR 2:3],158 kb / s,9.73 fps,9.73 tbr,19462 tbn,19.46 tbc(默认)元数据:handler_name:VideoHandler Stream#0:1(und):音频:aac(LC)(mp4a / 0x6134706D),44100 Hz,单声道,fltp,71 kb / s (默认值)元数据:creation_time:2018-01-01 12:09:49 handler_name:IsoMedia文件由Google制作,2011年5月11日[swscaler @ 0xc8c580]已弃用像素格式,请确保您正确设置了范围输出#0 ,mjpeg到' https://website.com/uploads/video/e0J6HwtK_video.png':元数据:major_brand:mp42 minor_version:0compatible_brands:isommp42编码器:Lavf56.40.101流#0:0(und):视频:mjpeg,yuvj420p(pc),240x360 [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流映射:流#0:0->#0:0(h264(本机) -> mjpeg(本机))按[q]停止,[?]表示帮助帧= 5 fps = 0.0 q = 1.6 Lsize = 100kB时间= 00:00:05.00比特率= 163.9kbits / s dup = 0 drop = 32视频:100kB音频:0kB字幕:0kB其他流:0kB全局标头:0kB混合开销:0.000000%

小智 7

如果使用https,则必须为ffmpeg配置ssl支持(基于https的ffmpeg失败)。


han*_*rik 5

参数必须被转义,你不能只是将变量作为参数转储在那里,网址包含类似&在 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);
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

<?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}";
}
Run Code Online (Sandbox Code Playgroud)