Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Ok. I have a fully-functional solution. This is for anyone who finds this question wanting to do the same thing. My code may not be very elegant, but it gets the job done.</p> <hr> <h2>Getting FFMPEG's output</h2> <p>First I had to get the output from ffmpeg -i, which was a challenge in itself. Thanks to hegemon's answer on <a href="https://stackoverflow.com/questions/1110655/capture-ffmpeg-output-in-php/1110765#1110765">my other question</a>, I was finally able to get it working with <code>2&gt;&amp;1</code> at the end of my command. And thanks to Evert's answer to this question, I was able to parse the output with <code>preg_match</code> to find the original file's height and width.</p> <pre><code>function get_vid_dim($file) { $command = '/usr/bin/ffmpeg -i ' . escapeshellarg($file) . ' 2&gt;&amp;1'; $dimensions = array(); exec($command,$output,$status); if (!preg_match('/Stream #(?:[0-9\.]+)(?:.*)\: Video: (?P&lt;videocodec&gt;.*) (?P&lt;width&gt;[0-9]*)x(?P&lt;height&gt;[0-9]*)/',implode('\n',$output),$matches)) { preg_match('/Could not find codec parameters \(Video: (?P&lt;videocodec&gt;.*) (?P&lt;width&gt;[0-9]*)x(?P&lt;height&gt;[0-9]*)\)/',implode('\n',$output),$matches); } if(!empty($matches['width']) &amp;&amp; !empty($matches['height'])) { $dimensions['width'] = $matches['width']; $dimensions['height'] = $matches['height']; } return $dimensions; } </code></pre> <hr> <h2>Determining the best dimensions</h2> <p>I wrote this function to determine the best dimensions to use for conversion. It takes the original's dimensions, target dimensions, and whether or not to force conversion to the target aspect ratio (determined from its width/height). The target dimensions will always be the largest result this function can return.</p> <pre><code>function get_dimensions($original_width,$original_height,$target_width,$target_height,$force_aspect = true) { // Array to be returned by this function $target = array(); // Target aspect ratio (width / height) $aspect = $target_width / $target_height; // Target reciprocal aspect ratio (height / width) $raspect = $target_height / $target_width; if($original_width/$original_height !== $aspect) { // Aspect ratio is different if($original_width/$original_height &gt; $aspect) { // Width is the greater of the two dimensions relative to the target dimensions if($original_width &lt; $target_width) { // Original video is smaller. Scale down dimensions for conversion $target_width = $original_width; $target_height = round($raspect * $target_width); } // Calculate height from width $original_height = round($original_height / $original_width * $target_width); $original_width = $target_width; if($force_aspect) { // Pad top and bottom $dif = round(($target_height - $original_height) / 2); $target['padtop'] = $dif; $target['padbottom'] = $dif; } } else { // Height is the greater of the two dimensions relative to the target dimensions if($original_height &lt; $target_height) { // Original video is smaller. Scale down dimensions for conversion $target_height = $original_height; $target_width = round($aspect * $target_height); } //Calculate width from height $original_width = round($original_width / $original_height * $target_height); $original_height = $target_height; if($force_aspect) { // Pad left and right $dif = round(($target_width - $original_width) / 2); $target['padleft'] = $dif; $target['padright'] = $dif; } } } else { // The aspect ratio is the same if($original_width !== $target_width) { if($original_width &lt; $target_width) { // The original video is smaller. Use its resolution for conversion $target_width = $original_width; $target_height = $original_height; } else { // The original video is larger, Use the target dimensions for conversion $original_width = $target_width; $original_height = $target_height; } } } if($force_aspect) { // Use the target_ vars because they contain dimensions relative to the target aspect ratio $target['width'] = $target_width; $target['height'] = $target_height; } else { // Use the original_ vars because they contain dimensions relative to the original's aspect ratio $target['width'] = $original_width; $target['height'] = $original_height; } return $target; } </code></pre> <hr> <h2>Usage</h2> <p>Here are a few examples of what you will get from <code>get_dimensions()</code> to make things more clear:</p> <pre><code>get_dimensions(480,360,640,480,true); -returns: Array([width] =&gt; 480, [height] =&gt; 360) get_dimensions(480,182,640,480,true); -returns: Array([padtop] =&gt; 89, [padbottom] =&gt; 89, [width] =&gt; 480, [height] =&gt; 360) get_dimensions(480,182,640,480,false); -returns: Array([width] =&gt; 480, [height] =&gt; 182) get_dimensions(640,480,480,182,true); -returns: Array([padleft] =&gt; 119, [padright] =&gt; 119, [width] =&gt; 480, [height] =&gt; 182) get_dimensions(720,480,640,480,true); -returns: Array([padtop] =&gt; 27, [padbottom] =&gt; 27, [width] =&gt; 640, [height] =&gt; 480) get_dimensions(720,480,640,480,false); -returns: Array([width] =&gt; 640, [height] =&gt; 427) </code></pre> <hr> <h2>The Finished Product</h2> <p>Now, to put it all together:</p> <pre><code>$src = '/var/videos/originals/original.mpg'; $original = get_vid_dim($src); if(!empty($original['width']) &amp;&amp; !empty($original['height'])) { $target = get_dimensions($original['width'],$original['height'],640,480,true); $command = '/usr/bin/ffmpeg -i ' . $src . ' -ab 96k -b 700k -ar 44100 -s ' . $target['width'] . 'x' . $target['height']; $command .= (!empty($target['padtop']) ? ' -padtop ' . $target['padtop'] : ''); $command .= (!empty($target['padbottom']) ? ' -padbottom ' . $target['padbottom'] : ''); $command .= (!empty($target['padleft']) ? ' -padleft ' . $target['padleft'] : ''); $command .= (!empty($target['padright']) ? ' -padright ' . $target['padright'] : ''); $command .= ' -acodec mp3 /var/videos/converted/target.flv 2&gt;&amp;1'; exec($command,$output,$status); if($status == 0) { // Success echo 'Woohoo!'; } else { // Error. $output has the details echo '&lt;pre&gt;',join('\n',$output),'&lt;/pre&gt;'; } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload