Question

I have an uploader which I am creating for a site. The uploader is a jquery plugin which I am on creating that allows single of multiple uploads of images or videos.

The uploader works with no problems and ffmpeg does create thumbnails no problem. However I have a max file size of 1GB which I will implement to the total of uploads so that users cannot upload to much in one go. But for testing I haven't yet so I can test the limits of the uploader capabilities before adding restrictions.

I have 4 videos I am using to test 246mb each. The files upload and move to the folder set on the test server (localhost) but the thumbnails don't create as the PHP script extends the maximum time limit. The easy option would be to change this in php.ini easily.

The problem is thought the progress bar only tracks the upload not the ffmpeg conversion. Is there a way of tracking this in my progress bar or running this as a background task with multiple video files.

It might be worth mentioning but with smaller videos, under 70mb each there is no problem at all thumbnails are created but still after the progress bar reaches 100%.

If it helps heres the relevant sections of the code. I can add the full source on git if needed. But I do fear that the answer will be no or alter the php.ini file

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');
                }
            }
        }
    }
}

**UPDATE the process of converting the files to thumbnails takes less time if I drop the posotion of where the thumb is taken from ie:

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

would become

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

I presume this is because ffmpeg plays the video until it gets to that point in the video to take the thumbnail. There for if the video is 5mins and the the thumb is taken at 2.30 then each conversion would take 2 min 30. I think I answered my own question here but take the thumbnail form somewhere between 1 - 5 seconds. Or alternately add a second progress bar into the onComplete handler which would calculate the time this would take and display it to the user.

Was it helpful?

Solution

Use -ss as an input option (before -i). From the documentation:

‘-ss position (input/output)’

When used as an input option (before -i), seeks in this input file to position. Note the in most formats it is not possible to seek exactly, so ffmpeg will seek to the closest seek point before position. When transcoding and ‘-accurate_seek’ is enabled (the default), this extra segment between the seek point and position will be decoded and discarded. When doing stream copy or when ‘-noaccurate_seek’ is used, it will be preserved.

When used as an output option (before an output filename), decodes but discards input until the timestamps reach position.

position may be either in seconds or in hh:mm:ss[.xxx] form.

Also see Seeking with FFmpeg.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top