Fix #66 : Allow single pass encoding

This commit is contained in:
Romain Neutron 2013-10-10 13:27:06 +02:00
commit 5da128acaa
3 changed files with 55 additions and 25 deletions

View file

@ -17,10 +17,11 @@
} }
], ],
"require": { "require": {
"php" : ">=5.3.3", "php" : ">=5.3.3",
"alchemy/binary-driver" : "~1.5", "alchemy/binary-driver" : "~1.5",
"doctrine/cache" : "~1.0", "doctrine/cache" : "~1.0",
"evenement/evenement" : "~1.0" "evenement/evenement" : "~1.0",
"neutron/temporary-filesystem" : "~2.1, >=2.1.1"
}, },
"suggest": { "suggest": {
"php-ffmpeg/extras" : "A compilation of common audio & video drivers for PHP-FFMpeg" "php-ffmpeg/extras" : "A compilation of common audio & video drivers for PHP-FFMpeg"

View file

@ -14,12 +14,14 @@ namespace FFMpeg\Media;
use Alchemy\BinaryDriver\Exception\ExecutionFailureException; use Alchemy\BinaryDriver\Exception\ExecutionFailureException;
use FFMpeg\Coordinate\TimeCode; use FFMpeg\Coordinate\TimeCode;
use FFMpeg\Filters\Audio\SimpleFilter; use FFMpeg\Filters\Audio\SimpleFilter;
use FFMpeg\Exception\InvalidArgumentException;
use FFMpeg\Exception\RuntimeException; use FFMpeg\Exception\RuntimeException;
use FFMpeg\Filters\Video\VideoFilters; use FFMpeg\Filters\Video\VideoFilters;
use FFMpeg\Filters\FilterInterface; use FFMpeg\Filters\FilterInterface;
use FFMpeg\Format\FormatInterface; use FFMpeg\Format\FormatInterface;
use FFMpeg\Format\ProgressableInterface; use FFMpeg\Format\ProgressableInterface;
use FFMpeg\Media\Frame; use FFMpeg\Media\Frame;
use Neutron\TemporaryFilesystem\Manager as FsManager;
class Video extends Audio class Video extends Audio
{ {
@ -104,32 +106,39 @@ class Video extends Audio
$commands[] = $format->getAudioKiloBitrate() . 'k'; $commands[] = $format->getAudioKiloBitrate() . 'k';
} }
$passPrefix = uniqid('pass-'); $fs = FsManager::create();
$fsId = uniqid('ffmpeg-passes');
$passPrefix = $fs->createTemporaryDirectory(0777, 50, $fsId) . '/' . uniqid('pass-');
$passes = array();
$totalPasses = $format->getPasses();
$pass1 = $commands; if (1 > $totalPasses) {
$pass2 = $commands; throw new InvalidArgumentException('Pass number should be a positive value.');
}
$pass1[] = '-pass'; for ($i = 1; $i <= $totalPasses; $i++) {
$pass1[] = '1'; $pass = $commands;
$pass1[] = '-passlogfile';
$pass1[] = $passPrefix;
$pass1[] = $outputPathfile;
$pass2[] = '-pass'; if ($totalPasses > 1) {
$pass2[] = '2'; $pass[] = '-pass';
$pass2[] = '-passlogfile'; $pass[] = $i;
$pass2[] = $passPrefix; $pass[] = '-passlogfile';
$pass2[] = $outputPathfile; $pass[] = $passPrefix;
$pass[] = $outputPathfile;
}
$passes[] = $pass;
}
$failure = null; $failure = null;
foreach (array($pass1, $pass2) as $pass => $passCommands) { foreach ($passes as $pass => $passCommands) {
try { try {
/** add listeners here */ /** add listeners here */
$listeners = null; $listeners = null;
if ($format instanceof ProgressableInterface) { if ($format instanceof ProgressableInterface) {
$listeners = $format->createProgressListener($this, $this->ffprobe, $pass + 1, 2); $listeners = $format->createProgressListener($this, $this->ffprobe, $pass + 1, $totalPasses);
} }
$this->driver->command($passCommands, false, $listeners); $this->driver->command($passCommands, false, $listeners);
@ -139,10 +148,7 @@ class Video extends Audio
} }
} }
$this $fs->clean($fsId);
->cleanupTemporaryFile(getcwd() . '/' . $passPrefix . '-0.log')
->cleanupTemporaryFile(getcwd() . '/' . $passPrefix . '-0.log')
->cleanupTemporaryFile(getcwd() . '/' . $passPrefix . '-0.log.mbtree');
if (null !== $failure) { if (null !== $failure) {
throw new RuntimeException('Encoding failed', $failure->getCode(), $failure); throw new RuntimeException('Encoding failed', $failure->getCode(), $failure);

View file

@ -92,6 +92,9 @@ class VideoTest extends AbstractStreamableTestCase
$ffprobe = $this->getFFProbeMock(); $ffprobe = $this->getFFProbeMock();
$outputPathfile = '/target/file'; $outputPathfile = '/target/file';
$format = $this->getMock('FFMpeg\Format\VideoInterface'); $format = $this->getMock('FFMpeg\Format\VideoInterface');
$format->expects($this->any())
->method('getPasses')
->will($this->returnValue(1));
$format->expects($this->any()) $format->expects($this->any())
->method('getExtraParams') ->method('getExtraParams')
->will($this->returnValue(array())); ->will($this->returnValue(array()));
@ -121,6 +124,9 @@ class VideoTest extends AbstractStreamableTestCase
$format->expects($this->any()) $format->expects($this->any())
->method('getExtraParams') ->method('getExtraParams')
->will($this->returnValue(array())); ->will($this->returnValue(array()));
$format->expects($this->any())
->method('getPasses')
->will($this->returnValue(2));
$configuration = $this->getMock('Alchemy\BinaryDriver\ConfigurationInterface'); $configuration = $this->getMock('Alchemy\BinaryDriver\ConfigurationInterface');
@ -205,7 +211,8 @@ class VideoTest extends AbstractStreamableTestCase
foreach ($capturedCommands as $passKey => $pass) { foreach ($capturedCommands as $passKey => $pass) {
foreach ($pass as $command) { foreach ($pass as $command) {
if (0 === strpos($command, 'pass-')) { $prefix = null;
if (false !== strpos($command, '/pass-')) {
$prefix = $command; $prefix = $command;
break; break;
} }
@ -246,6 +253,9 @@ class VideoTest extends AbstractStreamableTestCase
$format->expects($this->any()) $format->expects($this->any())
->method('getAudioKiloBitrate') ->method('getAudioKiloBitrate')
->will($this->returnValue(92)); ->will($this->returnValue(92));
$format->expects($this->any())
->method('getPasses')
->will($this->returnValue(2));
$audioVideoFormat = $this->getMock('FFMpeg\Format\VideoInterface'); $audioVideoFormat = $this->getMock('FFMpeg\Format\VideoInterface');
$audioVideoFormat->expects($this->any()) $audioVideoFormat->expects($this->any())
@ -263,6 +273,9 @@ class VideoTest extends AbstractStreamableTestCase
$audioVideoFormat->expects($this->any()) $audioVideoFormat->expects($this->any())
->method('getAudioKiloBitrate') ->method('getAudioKiloBitrate')
->will($this->returnValue(92)); ->will($this->returnValue(92));
$audioVideoFormat->expects($this->any())
->method('getPasses')
->will($this->returnValue(2));
$formatExtra = $this->getMock('FFMpeg\Format\VideoInterface'); $formatExtra = $this->getMock('FFMpeg\Format\VideoInterface');
$formatExtra->expects($this->any()) $formatExtra->expects($this->any())
@ -274,6 +287,9 @@ class VideoTest extends AbstractStreamableTestCase
$formatExtra->expects($this->any()) $formatExtra->expects($this->any())
->method('getAudioKiloBitrate') ->method('getAudioKiloBitrate')
->will($this->returnValue(92)); ->will($this->returnValue(92));
$formatExtra->expects($this->any())
->method('getPasses')
->will($this->returnValue(2));
$listeners = array($this->getMock('Alchemy\BinaryDriver\Listeners\ListenerInterface')); $listeners = array($this->getMock('Alchemy\BinaryDriver\Listeners\ListenerInterface'));
@ -291,6 +307,9 @@ class VideoTest extends AbstractStreamableTestCase
$progressableFormat->expects($this->any()) $progressableFormat->expects($this->any())
->method('getAudioKiloBitrate') ->method('getAudioKiloBitrate')
->will($this->returnValue(92)); ->will($this->returnValue(92));
$progressableFormat->expects($this->any())
->method('getPasses')
->will($this->returnValue(2));
return array( return array(
array(false, array(array( array(false, array(array(
@ -440,6 +459,9 @@ class VideoTest extends AbstractStreamableTestCase
$format->expects($this->any()) $format->expects($this->any())
->method('getExtraParams') ->method('getExtraParams')
->will($this->returnValue(array('param'))); ->will($this->returnValue(array('param')));
$format->expects($this->any())
->method('getPasses')
->will($this->returnValue(2));
$video = new Video(__FILE__, $driver, $ffprobe); $video = new Video(__FILE__, $driver, $ffprobe);
$video->save($format, $outputPathfile); $video->save($format, $outputPathfile);
@ -462,8 +484,9 @@ class VideoTest extends AbstractStreamableTestCase
$n = 1; $n = 1;
foreach ($capturedCommands as $capturedCommand) { foreach ($capturedCommands as $capturedCommand) {
$prefix = null;
foreach ($capturedCommand as $command) { foreach ($capturedCommand as $command) {
if (0 === strpos($command, 'pass-')) { if (false !== strpos($command, '/pass-')) {
$prefix = $command; $prefix = $command;
break; break;
} }