diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f10eed..618d572 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG * 0.3.5 (xx-xx-2013) * Add vorbis audio format (@jacobbudin). + * Fix #66 : Allow single pass encodings. * 0.3.4 (05-09-2013) diff --git a/composer.json b/composer.json index 1a680d5..4020aa1 100644 --- a/composer.json +++ b/composer.json @@ -17,10 +17,11 @@ } ], "require": { - "php" : ">=5.3.3", - "alchemy/binary-driver" : "~1.5", - "doctrine/cache" : "~1.0", - "evenement/evenement" : "~1.0" + "php" : ">=5.3.3", + "alchemy/binary-driver" : "~1.5", + "doctrine/cache" : "~1.0", + "evenement/evenement" : "~1.0", + "neutron/temporary-filesystem" : "~2.1, >=2.1.1" }, "suggest": { "php-ffmpeg/extras" : "A compilation of common audio & video drivers for PHP-FFMpeg" diff --git a/src/FFMpeg/Media/Video.php b/src/FFMpeg/Media/Video.php index 006e346..082f168 100644 --- a/src/FFMpeg/Media/Video.php +++ b/src/FFMpeg/Media/Video.php @@ -14,12 +14,14 @@ namespace FFMpeg\Media; use Alchemy\BinaryDriver\Exception\ExecutionFailureException; use FFMpeg\Coordinate\TimeCode; use FFMpeg\Filters\Audio\SimpleFilter; +use FFMpeg\Exception\InvalidArgumentException; use FFMpeg\Exception\RuntimeException; use FFMpeg\Filters\Video\VideoFilters; use FFMpeg\Filters\FilterInterface; use FFMpeg\Format\FormatInterface; use FFMpeg\Format\ProgressableInterface; use FFMpeg\Media\Frame; +use Neutron\TemporaryFilesystem\Manager as FsManager; class Video extends Audio { @@ -104,32 +106,39 @@ class Video extends Audio $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; - $pass2 = $commands; + if (1 > $totalPasses) { + throw new InvalidArgumentException('Pass number should be a positive value.'); + } - $pass1[] = '-pass'; - $pass1[] = '1'; - $pass1[] = '-passlogfile'; - $pass1[] = $passPrefix; - $pass1[] = $outputPathfile; + for ($i = 1; $i <= $totalPasses; $i++) { + $pass = $commands; - $pass2[] = '-pass'; - $pass2[] = '2'; - $pass2[] = '-passlogfile'; - $pass2[] = $passPrefix; - $pass2[] = $outputPathfile; + if ($totalPasses > 1) { + $pass[] = '-pass'; + $pass[] = $i; + $pass[] = '-passlogfile'; + $pass[] = $passPrefix; + $pass[] = $outputPathfile; + } + + $passes[] = $pass; + } $failure = null; - foreach (array($pass1, $pass2) as $pass => $passCommands) { + foreach ($passes as $pass => $passCommands) { try { /** add listeners here */ $listeners = null; 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); @@ -139,10 +148,7 @@ class Video extends Audio } } - $this - ->cleanupTemporaryFile(getcwd() . '/' . $passPrefix . '-0.log') - ->cleanupTemporaryFile(getcwd() . '/' . $passPrefix . '-0.log') - ->cleanupTemporaryFile(getcwd() . '/' . $passPrefix . '-0.log.mbtree'); + $fs->clean($fsId); if (null !== $failure) { throw new RuntimeException('Encoding failed', $failure->getCode(), $failure); diff --git a/tests/FFMpeg/Tests/Media/VideoTest.php b/tests/FFMpeg/Tests/Media/VideoTest.php index 3cc5771..de3985d 100644 --- a/tests/FFMpeg/Tests/Media/VideoTest.php +++ b/tests/FFMpeg/Tests/Media/VideoTest.php @@ -92,6 +92,9 @@ class VideoTest extends AbstractStreamableTestCase $ffprobe = $this->getFFProbeMock(); $outputPathfile = '/target/file'; $format = $this->getMock('FFMpeg\Format\VideoInterface'); + $format->expects($this->any()) + ->method('getPasses') + ->will($this->returnValue(1)); $format->expects($this->any()) ->method('getExtraParams') ->will($this->returnValue(array())); @@ -121,6 +124,9 @@ class VideoTest extends AbstractStreamableTestCase $format->expects($this->any()) ->method('getExtraParams') ->will($this->returnValue(array())); + $format->expects($this->any()) + ->method('getPasses') + ->will($this->returnValue(2)); $configuration = $this->getMock('Alchemy\BinaryDriver\ConfigurationInterface'); @@ -205,7 +211,8 @@ class VideoTest extends AbstractStreamableTestCase foreach ($capturedCommands as $passKey => $pass) { foreach ($pass as $command) { - if (0 === strpos($command, 'pass-')) { + $prefix = null; + if (false !== strpos($command, '/pass-')) { $prefix = $command; break; } @@ -246,6 +253,9 @@ class VideoTest extends AbstractStreamableTestCase $format->expects($this->any()) ->method('getAudioKiloBitrate') ->will($this->returnValue(92)); + $format->expects($this->any()) + ->method('getPasses') + ->will($this->returnValue(2)); $audioVideoFormat = $this->getMock('FFMpeg\Format\VideoInterface'); $audioVideoFormat->expects($this->any()) @@ -263,6 +273,9 @@ class VideoTest extends AbstractStreamableTestCase $audioVideoFormat->expects($this->any()) ->method('getAudioKiloBitrate') ->will($this->returnValue(92)); + $audioVideoFormat->expects($this->any()) + ->method('getPasses') + ->will($this->returnValue(2)); $formatExtra = $this->getMock('FFMpeg\Format\VideoInterface'); $formatExtra->expects($this->any()) @@ -274,6 +287,9 @@ class VideoTest extends AbstractStreamableTestCase $formatExtra->expects($this->any()) ->method('getAudioKiloBitrate') ->will($this->returnValue(92)); + $formatExtra->expects($this->any()) + ->method('getPasses') + ->will($this->returnValue(2)); $listeners = array($this->getMock('Alchemy\BinaryDriver\Listeners\ListenerInterface')); @@ -291,6 +307,9 @@ class VideoTest extends AbstractStreamableTestCase $progressableFormat->expects($this->any()) ->method('getAudioKiloBitrate') ->will($this->returnValue(92)); + $progressableFormat->expects($this->any()) + ->method('getPasses') + ->will($this->returnValue(2)); return array( array(false, array(array( @@ -440,6 +459,9 @@ class VideoTest extends AbstractStreamableTestCase $format->expects($this->any()) ->method('getExtraParams') ->will($this->returnValue(array('param'))); + $format->expects($this->any()) + ->method('getPasses') + ->will($this->returnValue(2)); $video = new Video(__FILE__, $driver, $ffprobe); $video->save($format, $outputPathfile); @@ -462,8 +484,9 @@ class VideoTest extends AbstractStreamableTestCase $n = 1; foreach ($capturedCommands as $capturedCommand) { + $prefix = null; foreach ($capturedCommand as $command) { - if (0 === strpos($command, 'pass-')) { + if (false !== strpos($command, '/pass-')) { $prefix = $command; break; }