【问题标题】:Use ff mpeg inside a loop to create thumbnails在循环中使用 ff mpeg 创建缩略图
【发布时间】:2014-06-16 14:10:52
【问题描述】:

我有一个正在为网站创建的上传器。上传器是我正在创建的一个 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 处理程序中,该处理程序将计算所需时间并将其显示给用户。

【问题讨论】:

    标签: php jquery for-loop ffmpeg exec


    【解决方案1】:

    使用-ss 作为输入选项(在-i 之前)。来自documentation

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

    当用作输入选项时(在 -i 之前),在此输入文件中查找 位置。请注意,在大多数格式中,无法搜索 确切地说,所以 ffmpeg 将寻找到最近的寻找点 位置。启用转码和“-accurate_seek”时( 默认),搜索点和位置之间的这个额外段将 被解码并丢弃。进行流复制时或 '-noaccurate_seek' 被使用,它将被保留。

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

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

    另见Seeking with FFmpeg

    【讨论】:

    • 这很酷,我离得不远,然后我只需要重新排序命令
    猜你喜欢
    • 1970-01-01
    • 2012-05-10
    • 2015-08-21
    • 1970-01-01
    • 2011-01-30
    • 2011-12-31
    • 2013-01-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多