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.
Getting FFMPEG's output
First I had to get the output from ffmpeg -i, which was a challenge in itself. Thanks to hegemon's answer on my other question, I was finally able to get it working with 2>&1
at the end of my command. And thanks to Evert's answer to this question, I was able to parse the output with preg_match
to find the original file's height and width.
function get_vid_dim($file)
{
$command = '/usr/bin/ffmpeg -i ' . escapeshellarg($file) . ' 2>&1';
$dimensions = array();
exec($command,$output,$status);
if (!preg_match('/Stream #(?:[0-9\.]+)(?:.*)\: Video: (?P<videocodec>.*) (?P<width>[0-9]*)x(?P<height>[0-9]*)/',implode('\n',$output),$matches))
{
preg_match('/Could not find codec parameters \(Video: (?P<videocodec>.*) (?P<width>[0-9]*)x(?P<height>[0-9]*)\)/',implode('\n',$output),$matches);
}
if(!empty($matches['width']) && !empty($matches['height']))
{
$dimensions['width'] = $matches['width'];
$dimensions['height'] = $matches['height'];
}
return $dimensions;
}
Determining the best dimensions
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.
function get_dimensions($original_width,$original_height,$target_width,$target_height,$force_aspect = true)
{
$target = array();
$aspect = $target_width / $target_height;
$raspect = $target_height / $target_width;
if($original_width/$original_height !== $aspect)
{
if($original_width/$original_height > $aspect)
{
if($original_width < $target_width)
{
$target_width = $original_width;
$target_height = round($raspect * $target_width);
}
$original_height = round($original_height / $original_width * $target_width);
$original_width = $target_width;
if($force_aspect)
{
$dif = round(($target_height - $original_height) / 2);
$target['padtop'] = $dif;
$target['padbottom'] = $dif;
}
}
else
{
if($original_height < $target_height)
{
$target_height = $original_height;
$target_width = round($aspect * $target_height);
}
$original_width = round($original_width / $original_height * $target_height);
$original_height = $target_height;
if($force_aspect)
{
$dif = round(($target_width - $original_width) / 2);
$target['padleft'] = $dif;
$target['padright'] = $dif;
}
}
}
else
{
if($original_width !== $target_width)
{
if($original_width < $target_width)
{
$target_width = $original_width;
$target_height = $original_height;
}
else
{
$original_width = $target_width;
$original_height = $target_height;
}
}
}
if($force_aspect)
{
$target['width'] = $target_width;
$target['height'] = $target_height;
}
else
{
$target['width'] = $original_width;
$target['height'] = $original_height;
}
return $target;
}
Usage
Here are a few examples of what you will get from get_dimensions()
to make things more clear:
get_dimensions(480,360,640,480,true);
-returns: Array([width] => 480, [height] => 360)
get_dimensions(480,182,640,480,true);
-returns: Array([padtop] => 89, [padbottom] => 89, [width] => 480, [height] => 360)
get_dimensions(480,182,640,480,false);
-returns: Array([width] => 480, [height] => 182)
get_dimensions(640,480,480,182,true);
-returns: Array([padleft] => 119, [padright] => 119, [width] => 480, [height] => 182)
get_dimensions(720,480,640,480,true);
-returns: Array([padtop] => 27, [padbottom] => 27, [width] => 640, [height] => 480)
get_dimensions(720,480,640,480,false);
-returns: Array([width] => 640, [height] => 427)
The Finished Product
Now, to put it all together:
$src = '/var/videos/originals/original.mpg';
$original = get_vid_dim($src);
if(!empty($original['width']) && !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>&1';
exec($command,$output,$status);
if($status == 0)
{
echo 'Woohoo!';
}
else
{
echo '<pre>',join('\n',$output),'</pre>';
}
}