diff --git a/.gitattributes b/.gitattributes index 7c6f5e1..88dfe64 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,3 +2,6 @@ .gitignore export-ignore .github export-ignore docs export-ignore +tests export-ignore +phpunit.xml.dist export-ignore +.travis.yml export-ignore diff --git a/README.md b/README.md index 97650bc..911fb64 100644 --- a/README.md +++ b/README.md @@ -12,12 +12,10 @@ Check another amazing repo: [PHP FFMpeg extras](https://github.com/alchemy-fr/PH ### How this library works: -This library requires a working FFMpeg install. You will need both FFMpeg and FFProbe binaries to use it. +This library requires a working [FFMpeg install](https://ffmpeg.org/download.html). You will need both FFMpeg and FFProbe binaries to use it. Be sure that these binaries can be located with system PATH to get the benefit of the binary detection, otherwise you should have to explicitly give the binaries path on load. -For Windows users: Please find the binaries at http://ffmpeg.zeranoe.com/builds/. - ### Known issues: - Using rotate and resize will produce a corrupted output when using @@ -111,7 +109,7 @@ video. Frames can be extracted. You can transcode videos using the `FFMpeg\Media\Video:save` method. You will pass a `FFMpeg\Format\FormatInterface` for that. -Please note that audio and video bitrate are set on the format. +Please note that audio and video bitrate are set on the format. You can disable the `-b:v` option by setting the kilo bitrate to 0. ```php $format = new FFMpeg\Format\Video\X264(); @@ -503,7 +501,7 @@ $video The boolean parameter of the save function allows you to use the copy parameter which accelerates drastically the generation of the encoded file. -To concatenate videos encoded with the same codec, do as follow: +To concatenate videos encoded with the different codec, do as follow: ```php // In order to instantiate the video object, you HAVE TO pass a path to a valid video file. diff --git a/src/FFMpeg/Format/Video/DefaultVideo.php b/src/FFMpeg/Format/Video/DefaultVideo.php index 9d827bb..733df44 100644 --- a/src/FFMpeg/Format/Video/DefaultVideo.php +++ b/src/FFMpeg/Format/Video/DefaultVideo.php @@ -54,7 +54,7 @@ abstract class DefaultVideo extends DefaultAudio implements VideoInterface */ public function setKiloBitrate($kiloBitrate) { - if ($kiloBitrate < 1) { + if ($kiloBitrate < 0) { throw new InvalidArgumentException('Wrong kiloBitrate value'); } diff --git a/src/FFMpeg/Format/Video/X264.php b/src/FFMpeg/Format/Video/X264.php index c1fd453..c6cfb41 100644 --- a/src/FFMpeg/Format/Video/X264.php +++ b/src/FFMpeg/Format/Video/X264.php @@ -22,7 +22,7 @@ class X264 extends DefaultVideo /** @var int */ private $passes = 2; - public function __construct($audioCodec = 'libfaac', $videoCodec = 'libx264') + public function __construct($audioCodec = 'aac', $videoCodec = 'libx264') { $this ->setAudioCodec($audioCodec) @@ -81,7 +81,7 @@ class X264 extends DefaultVideo */ public function getPasses() { - return $this->passes; + return $this->getKiloBitrate() === 0 ? 1 : $this->passes; } /** diff --git a/src/FFMpeg/Media/AbstractVideo.php b/src/FFMpeg/Media/AbstractVideo.php index 339e4da..1f68dad 100644 --- a/src/FFMpeg/Media/AbstractVideo.php +++ b/src/FFMpeg/Media/AbstractVideo.php @@ -86,6 +86,10 @@ abstract class AbstractVideo extends Audio // FFMpeg\Format\ProgressListener\AbstractProgressListener class foreach ($filters as $filter) { if ($filter instanceof ClipFilter) { + if ($filter->getDuration() === NULL) { + continue; + } + $duration = $filter->getDuration()->toSeconds(); break; } @@ -158,8 +162,11 @@ abstract class AbstractVideo extends Audio } if ($format instanceof VideoInterface) { - $commands[] = '-b:v'; - $commands[] = $format->getKiloBitrate() . 'k'; + if ($format->getKiloBitrate() !== 0) { + $commands[] = '-b:v'; + $commands[] = $format->getKiloBitrate() . 'k'; + } + $commands[] = '-refs'; $commands[] = '6'; $commands[] = '-coder'; diff --git a/tests/Functional/AudioConcatenationTest.php b/tests/Functional/AudioConcatenationTest.php index f4ca197..cac6232 100644 --- a/tests/Functional/AudioConcatenationTest.php +++ b/tests/Functional/AudioConcatenationTest.php @@ -10,22 +10,22 @@ class AudioConcatenationTest extends FunctionalTestCase public function testSimpleAudioFileConcatTest() { $ffmpeg = $this->getFFMpeg(); - + $files = [ - __DIR__ . '/../files/Jahzzar_-_05_-_Siesta.mp3', - __DIR__ . '/../files/02_-_Favorite_Secrets.mp3', + realpath(__DIR__ . '/../files/Jahzzar_-_05_-_Siesta.mp3'), + realpath(__DIR__ . '/../files/02_-_Favorite_Secrets.mp3'), ]; $audio = $ffmpeg->open(reset($files)); $this->assertInstanceOf('FFMpeg\Media\Audio', $audio); - + clearstatcache(); $filename = __DIR__ . '/output/concat-output.mp3'; $audio->concat($files)->saveFromSameCodecs($filename, TRUE); - + $this->assertFileExists($filename); unlink($filename); } -} \ No newline at end of file +} diff --git a/tests/Unit/Format/Video/VideoTestCase.php b/tests/Unit/Format/Video/VideoTestCase.php index 0df42ee..b96b470 100644 --- a/tests/Unit/Format/Video/VideoTestCase.php +++ b/tests/Unit/Format/Video/VideoTestCase.php @@ -39,9 +39,16 @@ abstract class VideoTestCase extends AudioTestCase $this->assertEquals(2560, $format->getKiloBitrate()); } + public function testSetKiloBitrateBelowZero() + { + $this->expectException('FFMpeg\Exception\InvalidArgumentException'); + $format = $this->getFormat(); + $format->setKiloBitrate(-1); + } + public function testSetInvalidVideoCodec() { - $this->expectException('\FFMpeg\Exception\InvalidArgumentException'); + $this->expectException('FFMpeg\Exception\InvalidArgumentException'); $this->getFormat()->setVideoCodec('invalid-random-video-codec'); } diff --git a/tests/Unit/Media/VideoTest.php b/tests/Unit/Media/VideoTest.php index 03c42de..8352c45 100644 --- a/tests/Unit/Media/VideoTest.php +++ b/tests/Unit/Media/VideoTest.php @@ -4,6 +4,7 @@ namespace Tests\FFMpeg\Unit\Media; use FFMpeg\Exception\RuntimeException; use FFMpeg\Media\Video; +use FFMpeg\Format\Video\X264; use Alchemy\BinaryDriver\Exception\ExecutionFailureException; use FFMpeg\Format\VideoInterface; @@ -677,6 +678,35 @@ class VideoTest extends AbstractStreamableTestCase } } + public function testCaseWhereKiloBitRateIsEqualToZero() + { + $driver = $this->getFFMpegDriverMock(); + $ffprobe = $this->getFFProbeMock(); + + $pathfile = '/target/destination'; + $outputPathfile = '/target/file'; + + $format = new X264(); + $format->setKiloBitrate(0); + + $configuration = $this->getMockBuilder('Alchemy\BinaryDriver\ConfigurationInterface')->getMock(); + + $driver->expects($this->any()) + ->method('getConfiguration') + ->will($this->returnValue($configuration)); + + $driver->expects($this->exactly(1)) + ->method('command') + ->with($this->isType('array'), false, $this->anything()) + ->will($this->returnCallback(function ($commands, $errors, $listeners) { + var_dump($commands); + $this->assertTrue(!in_array('-b:v', $commands)); + })); + + $video = new Video(__FILE__, $driver, $ffprobe); + $video->save($format, $outputPathfile); + } + public function getClassName() { return 'FFMpeg\Media\Video';