Error in Jquery upload file due to FFMPEG conversi

2019-08-01 07:27发布

问题:

I am using jQuery upload file plugin, and when videos are uploaded, they are converted using FFMPEG. For short sized files everything works perfectly but when I try to upload bigger files, nothing is returned in the response. I thought that this could me max_execution_time issue so I have removed the limit but still it happens, but when I see the folder, the files are converted completely and entered into database so everything seems to work of large files except it doesn't echo. I tried to remove one FFMPEG conversion statement and convert file to just one size but still the result is same for large files.

and I see this result

Here is my PHP code

    $default = ini_get('max_execution_time');
    set_time_limit(0);
    $fileName = $_FILES["myfile"]["name"];
    $fileName = str_ireplace(' ', '_', $fileName);                
    $fn = $_FILES["myfile"]["name"];
    $i = 1;
    $actual_name = pathinfo($fileName,PATHINFO_FILENAME);
    $original_name = $actual_name;
    $extension = strtolower (pathinfo($fileName, PATHINFO_EXTENSION));      
    while(file_exists($output_dir.$fileName))
    {           
       $actual_name = (string)$original_name.$i;
       $fileName = $actual_name.".".$extension;
       $filetoconvert = $actual_name.".mp4";
       $filetoconvertSD=$actual_name."SD.mp4";
       $i++;
    }
    //echo $fileName;
        move_uploaded_file($_FILES["myfile"]["tmp_name"],$output_dir.$fileName);

       $url = $output_dir1.$fileName; 
       $outputnameSD="";
       $time="";
       $del_url = $output_dir.$fileName;


          $i = 1;
          while(file_exists($output_dir.$filetoconvert))
          {           
              $actual_name = (string)$original_name.$i;
              $fileName = $actual_name.".mp4";
              $filetoconvert = $actual_name.".mp4";
              $filetoconvertSD=$actual_name."SD.mp4";
              $i++;
          }
          $outputname = $output_dir1.$filetoconvert;
          $outputnameSD=$output_dir1.$filetoconvertSD;

          $videofile="/var/www/html/".$url; 
          $xyz = shell_exec("ffmpeg -i \"{$videofile}\" 2>&1"); //Get duration 
          $search='/Duration: (.*?),/';
          preg_match($search, $xyz, $matches);
          $tim=explode(".", $matches[1]);
          $time=$tim[0];
          $ret = exec(' ffmpeg -i /var/www/html/'.$url.' -acodec libfaac -b:a 128k -vcodec libx264 -preset fast -vprofile baseline -b:v 400k -maxrate 400k -bufsize 800k -crf 26 -flags +aic+mv4 /var/www/html/'.$outputnameSD, $out, $err);
          $ret = exec(' ffmpeg -i /var/www/html/'.$url.' -acodec libfaac -b:a 196k -vcodec libx264 -preset fast -vprofile high -b:v 1000k -crf 20 -flags +aic+mv4 /var/www/html/'.$outputname, $out, $err);

          unlink($del_url);
          $url = $output_dir1.$fileName;              

       Database QUERY HERE         
       $ret[]= $fileName;
      echo '<li>
      '.$fileName.'
    </li>';
    set_time_limit($default);

回答1:

I had a similar issue when doing the same thing and wasted many hours playing around with all sorts of timeouts. The ones involved are php execution time, server post timeout, server response timeout and javascript timers.

In the end I found it better to break up the process into parts:

  1. Receive upload and copy to tempdir.
  2. Insert data into sql batch table.
  3. Cron looking at batch table to convert videos, copy to final location and update final table.
  4. Script that monitors batch process and returns state of videos being processes.

The upload form just uploads and executes steps 1 and 2. On the same page I have js that pings my monitor script and shows the relevant info.

This helps a few things. First the user can upload and forget the files without having to sit ther waiting for each one to be processed. Second I can restart the process at any step of the way without having the user go back to the beginning. And finally everything is faster since I can run uploads and conversions in parallel and they each have their own process that can be independently managed.



回答2:

Incase someone encounter same issue, than this is how I fixed it. I changed the ffmpeg code to

 $ret = exec('ffmpeg -i /var/www/html/'.$url.' -vcodec libx264 -crf 20 -preset fast /var/www/html/'.$outputname.' >/dev/null 2>/dev/null &', $out, $err);
 $ret = exec('ffmpeg -i /var/www/html/'.$url.' -vcodec libx264 -crf 26 -preset fast /var/www/html/'.$outputnameSD.' >/dev/null 2>/dev/null &', $out, $err);

The last part >/dev/null 2>/dev/null & lets it believe that exec command is executed while it runs at the background. The only drawback of this solution is that you can't delete the original file after conversion if you want to like I had to.

To cater this solution, the answer provided by @hdezela is the way to go about it i.e. to write a cronjob