在循环中使用ffmpeg来创建缩略图


Use ff mpeg inside a loop to create thumbnails

我有一个上传程序,我正在为一个网站创建。上传器是一个jquery插件,我正在创建它,它允许多次上传图像或视频。

上传器工作没有问题,ffmpeg创建缩略图也没有问题。然而,我有一个1GB的最大文件大小,我将实现总上传量,这样用户就不能一次上传太多。但对于测试,我还没有,所以我可以在添加限制之前测试上传器功能的限制。

我有4个视频,我正在使用每个测试246mb。文件上传并移动到测试服务器(localhost(上设置的文件夹中,但由于PHP脚本延长了最长时间限制,因此不会创建缩略图。简单的选择是在php.ini中轻松地更改它。

问题是进度条只跟踪上传,而不是ffmpeg转换。有没有一种方法可以在我的进度条中跟踪它,或者将它作为多个视频文件的后台任务运行。

值得一提的是,对于较小的视频,每个视频的容量小于70mb,创建缩略图时没有任何问题,但在进度条达到100%后仍然如此。

如果有帮助,请参阅代码的相关部分。如果需要,我可以在git上添加完整的源代码。但我确实担心答案是否定的,或者更改php.ini文件

JQuery/Ajax:

$.ajax({
        url: options.processor,
        type: "POST",
        data: formdata,
        processData: false,
        contentType: false,
        dataType:"JSON",
        beforeSend: init,
        error: error,
        xhr: function() {
            var myXhr = $.ajaxSettings.xhr();
            if(myXhr.upload){
                myXhr.upload.addEventListener('progress',uploadProgress, false);
            }
            return myXhr;
        },
        success: onComplete
    });
var uploadProgress = function(e){
        if(e.lengthComputable){
            if(options.single === true){
                $('#'+options.counter).html('File 1 of 1');
            }else{
                $('#'+options.counter).html('Files '+ item_count +' of ' + item_count + ' uploading');  
            }
            var p = (e.loaded / e.total) * 100;
            $('#'+options.progress_text).html(Math.round(p) + '%');
            $('#'+options.progress_bar).width(p + '%');
        }
    }

PHP:

if(!empty($_FILES['file'])){
    if(!empty($_POST['single'])){
        //single file upload
        if($_FILES['file']['error'] === 0){
            $temp = $_FILES['file']['tmp_name'];
            $name = $_FILES['file']['name'];
            $ext = explode('.',$name);
            $ext = strtolower(end($ext));
            $file = md5($temp).time().'.'.$ext;
            if(in_array($ext,$allowed) === true &&  move_uploaded_file($temp,"../uploads/{$file}") === true){
                $succedeed[] = array('name' => $name,'file' => $file,'type'=>'image');              
            }else{
                $failed[] = array('name' => $name, 'file' => $file, 'error' => 'File type not allowed');
            }
        }
    }else{
        //multiple file upload
        foreach($_FILES['file']['name'] as $key => $name){
            if($_FILES['file']['error'][$key] === 0){
                $temp = $_FILES['file']['tmp_name'][$key];
                $ext = explode('.',$name);
                $ext = strtolower(end($ext));
                $_file = md5($temp).time();
                $file = $_file.'.'.$ext;
                if(in_array($ext,$allowed) === true &&  move_uploaded_file($temp,"../uploads/{$file}") === true){
                    $file_type = explode('/',$_FILES['file']['type'][$key]);
                    if($file_type[0] === 'image'){
                        echo 'image';
                        $succedeed[] = array('name' => $name,'file' => $file, 'type' => 'image');               
                    }else{
                        $ffmpeg = 'ffmpeg';
                        $output = dirname(__DIR__).'/uploads/thumbs/'.$_file.'.jpg';
                        $input = dirname(__DIR__).'/uploads/'.$file;
                        $mov = new ffmpeg_movie($input);
                        $d =  $mov->getDuration();
                        $iscopy = $mov->getCopyright();
                        $h = $mov->getFrameHeight();
                        $w = $mov->getFrameWidth();
                        $pos = ceil((int)$d /3);
                        $size = $w.'x'.$h;
                        $cmd = "ffmpeg -i $input -an -ss $pos -s $size $output";
                        shell_exec($cmd);
                        $succedeed[] = array('name' => $name,'file' => '/thumbs/'.$_file.'.jpg', 'type' => 'video');                
                    }
                }else{
                    $failed[] = array('name' => $name, 'file' => $file, 'error' => 'File type not allowed');
                }
            }
        }
    }
}

**更新将文件转换为缩略图的过程需要更少的时间,如果我放弃拇指的位置,即:

$cmd = "ffmpeg -i $input -an -ss $pos -s $size $output";

将成为

$cmd = "ffmpeg -i $input -an -ss 3 -s $size $output";

我想这是因为ffmpeg播放视频,直到它到达视频中的那个点来拍摄缩略图。如果视频是5分钟,拇指是在2.30拍的,那么每次转换需要2分钟30。我想我在这里回答了我自己的问题,但采用了1-5秒之间的缩略图形式。或者在onComplete处理程序中添加第二个进度条,该处理程序将计算所需的时间并将其显示给用户。

使用-ss作为输入选项(在-i之前(。来自文件:

'-ss位置(输入/输出('

当用作输入选项(在-i之前(时,在此输入文件中查找位置请注意,在大多数格式中,无法查找确切地说,因此ffmpeg将在之前搜索到最近的搜索点位置当启用代码转换和"-accrete_sek"时(默认值(,在寻道点和位置之间的这段额外的线段将被解码并丢弃。进行流复制时或如果使用了"-noaccurate_sek",它将被保留。

当用作输出选项(在输出文件名之前(时,解码但是丢弃输入,直到时间戳到达位置。

位置可以是以秒为单位,也可以是hh:mm:ss[.xxx]形式。

另请参阅使用FFmpeg进行查找。