🔥 Replace all other files with 💀

This commit is contained in:
Dan Jones 2022-08-21 15:37:37 -05:00
commit d187e02d24
124 changed files with 345 additions and 8227 deletions

View file

@ -1,300 +0,0 @@
<?php
namespace Alchemy\Tests\BinaryDriver;
use Alchemy\BinaryDriver\AbstractBinary;
use Alchemy\BinaryDriver\BinaryDriverTestCase;
use Alchemy\BinaryDriver\Configuration;
use Alchemy\BinaryDriver\Exception\ExecutableNotFoundException;
use Alchemy\BinaryDriver\Listeners\ListenerInterface;
use Symfony\Component\Process\ExecutableFinder;
class AbstractBinaryTest extends BinaryDriverTestCase
{
protected function getPhpBinary()
{
$finder = new ExecutableFinder();
$php = $finder->find('php');
if (null === $php) {
$this->markTestSkipped('Unable to find a php binary');
}
return $php;
}
public function testSimpleLoadWithBinaryPath()
{
$php = $this->getPhpBinary();
$imp = Implementation::load($php);
$this->assertInstanceOf('Alchemy\Tests\BinaryDriver\Implementation', $imp);
$this->assertEquals($php, $imp->getProcessBuilderFactory()->getBinary());
}
public function testMultipleLoadWithBinaryPath()
{
$php = $this->getPhpBinary();
$imp = Implementation::load(['/zz/path/to/unexisting/command', $php]);
$this->assertInstanceOf('Alchemy\Tests\BinaryDriver\Implementation', $imp);
$this->assertEquals($php, $imp->getProcessBuilderFactory()->getBinary());
}
public function testSimpleLoadWithBinaryName()
{
$php = $this->getPhpBinary();
$imp = Implementation::load('php');
$this->assertInstanceOf('Alchemy\Tests\BinaryDriver\Implementation', $imp);
$this->assertEquals($php, $imp->getProcessBuilderFactory()->getBinary());
}
public function testMultipleLoadWithBinaryName()
{
$php = $this->getPhpBinary();
$imp = Implementation::load(['bachibouzouk', 'php']);
$this->assertInstanceOf('Alchemy\Tests\BinaryDriver\Implementation', $imp);
$this->assertEquals($php, $imp->getProcessBuilderFactory()->getBinary());
}
public function testLoadWithMultiplePathExpectingAFailure()
{
$this->expectException(ExecutableNotFoundException::class);
Implementation::load(['bachibouzouk', 'moribon']);
}
public function testLoadWithUniquePathExpectingAFailure()
{
$this->expectException(ExecutableNotFoundException::class);
Implementation::load('bachibouzouk');
}
public function testLoadWithCustomLogger()
{
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
$imp = Implementation::load('php', $logger);
$this->assertEquals($logger, $imp->getProcessRunner()->getLogger());
}
public function testLoadWithCustomConfigurationAsArray()
{
$conf = ['timeout' => 200];
$imp = Implementation::load('php', null, $conf);
$this->assertEquals($conf, $imp->getConfiguration()->all());
}
public function testLoadWithCustomConfigurationAsObject()
{
$conf = $this->getMockBuilder('Alchemy\BinaryDriver\ConfigurationInterface')->getMock();
$imp = Implementation::load('php', null, $conf);
$this->assertEquals($conf, $imp->getConfiguration());
}
public function testProcessBuilderFactoryGetterAndSetters()
{
$imp = Implementation::load('php');
$factory = $this->getMockBuilder('Alchemy\BinaryDriver\ProcessBuilderFactoryInterface')->getMock();
$imp->setProcessBuilderFactory($factory);
$this->assertEquals($factory, $imp->getProcessBuilderFactory());
}
public function testConfigurationGetterAndSetters()
{
$imp = Implementation::load('php');
$conf = $this->getMockBuilder('Alchemy\BinaryDriver\ConfigurationInterface')->getMock();
$imp->setConfiguration($conf);
$this->assertEquals($conf, $imp->getConfiguration());
}
public function testTimeoutIsSetOnConstruction()
{
$imp = Implementation::load('php', null, ['timeout' => 42]);
$this->assertEquals(42, $imp->getProcessBuilderFactory()->getTimeout());
}
public function testTimeoutIsSetOnConfigurationSetting()
{
$imp = Implementation::load('php', null);
$imp->setConfiguration(new Configuration(['timeout' => 42]));
$this->assertEquals(42, $imp->getProcessBuilderFactory()->getTimeout());
}
public function testTimeoutIsSetOnProcessBuilderSetting()
{
$imp = Implementation::load('php', null, ['timeout' => 42]);
$factory = $this->getMockBuilder('Alchemy\BinaryDriver\ProcessBuilderFactoryInterface')->getMock();
$factory->expects($this->once())
->method('setTimeout')
->with(42);
$imp->setProcessBuilderFactory($factory);
}
public function testListenRegistersAListener()
{
$imp = Implementation::load('php');
$listeners = $this->getMockBuilder('Alchemy\BinaryDriver\Listeners\Listeners')
->disableOriginalConstructor()
->getMock();
$listener = $this->getMockBuilder('Alchemy\BinaryDriver\Listeners\ListenerInterface')->getMock();
$listeners->expects($this->once())
->method('register')
->with($this->equalTo($listener), $this->equalTo($imp));
$reflexion = new \ReflectionClass('Alchemy\BinaryDriver\AbstractBinary');
$prop = $reflexion->getProperty('listenersManager');
$prop->setAccessible(true);
$prop->setValue($imp, $listeners);
$imp->listen($listener);
}
/**
* @dataProvider provideCommandParameters
*/
public function testCommandRunsAProcess($parameters, $bypassErrors, $expectedParameters, $output)
{
$imp = Implementation::load('php');
$factory = $this->getMockBuilder('Alchemy\BinaryDriver\ProcessBuilderFactoryInterface')->getMock();
$processRunner = $this->getMockBuilder('Alchemy\BinaryDriver\ProcessRunnerInterface')->getMock();
$process = $this->getMockBuilder('Symfony\Component\Process\Process')
->disableOriginalConstructor()
->getMock();
$processRunner->expects($this->once())
->method('run')
->with($this->equalTo($process), $this->isInstanceOf('SplObjectStorage'), $this->equalTo($bypassErrors))
->will($this->returnValue($output));
$factory->expects($this->once())
->method('create')
->with($expectedParameters)
->will($this->returnValue($process));
$imp->setProcessBuilderFactory($factory);
$imp->setProcessRunner($processRunner);
$this->assertEquals($output, $imp->command($parameters, $bypassErrors));
}
/**
* @dataProvider provideCommandWithListenersParameters
*/
public function testCommandWithTemporaryListeners($parameters, $bypassErrors, $expectedParameters, $output, $count, $listeners)
{
$imp = Implementation::load('php');
$factory = $this->getMockBuilder('Alchemy\BinaryDriver\ProcessBuilderFactoryInterface')->getMock();
$processRunner = $this->getMockBuilder('Alchemy\BinaryDriver\ProcessRunnerInterface')->getMock();
$process = $this->getMockBuilder('Symfony\Component\Process\Process')
->disableOriginalConstructor()
->getMock();
$firstStorage = $secondStorage = null;
$processRunner->expects($this->exactly(2))
->method('run')
->with($this->equalTo($process), $this->isInstanceOf('SplObjectStorage'), $this->equalTo($bypassErrors))
->will($this->returnCallback(function ($process, $storage, $errors) use ($output, &$firstStorage, &$secondStorage) {
if (null === $firstStorage) {
$firstStorage = $storage;
} else {
$secondStorage = $storage;
}
return $output;
}));
$factory->expects($this->exactly(2))
->method('create')
->with($expectedParameters)
->will($this->returnValue($process));
$imp->setProcessBuilderFactory($factory);
$imp->setProcessRunner($processRunner);
$this->assertEquals($output, $imp->command($parameters, $bypassErrors, $listeners));
$this->assertCount($count, $firstStorage);
$this->assertEquals($output, $imp->command($parameters, $bypassErrors));
$this->assertCount(0, $secondStorage);
}
public function provideCommandWithListenersParameters()
{
return [
['-a', false, ['-a'], 'loubda', 2, [$this->getMockListener(), $this->getMockListener()]],
['-a', false, ['-a'], 'loubda', 1, [$this->getMockListener()]],
['-a', false, ['-a'], 'loubda', 1, $this->getMockListener()],
['-a', false, ['-a'], 'loubda', 0, []],
];
}
public function provideCommandParameters()
{
return [
['-a', false, ['-a'], 'loubda'],
['-a', true, ['-a'], 'loubda'],
['-a -b', false, ['-a -b'], 'loubda'],
[['-a'], false, ['-a'], 'loubda'],
[['-a'], true, ['-a'], 'loubda'],
[['-a', '-b'], false, ['-a', '-b'], 'loubda'],
];
}
public function testUnlistenUnregistersAListener()
{
$imp = Implementation::load('php');
$listeners = $this->getMockBuilder('Alchemy\BinaryDriver\Listeners\Listeners')
->disableOriginalConstructor()
->getMock();
$listener = $this->getMockBuilder('Alchemy\BinaryDriver\Listeners\ListenerInterface')->getMock();
$listeners->expects($this->once())
->method('unregister')
->with($this->equalTo($listener), $this->equalTo($imp));
$reflexion = new \ReflectionClass('Alchemy\BinaryDriver\AbstractBinary');
$prop = $reflexion->getProperty('listenersManager');
$prop->setAccessible(true);
$prop->setValue($imp, $listeners);
$imp->unlisten($listener);
}
/**
* @return \PHPUnit_Framework_MockObject_MockObject
*/
private function getMockListener()
{
$listener = $this->getMockBuilder(ListenerInterface::class)->getMock();
$listener->expects($this->any())
->method('forwardedEvents')
->willReturn([]);
return $listener;
}
}
class Implementation extends AbstractBinary
{
public function getName()
{
return 'Implementation';
}
}

View file

@ -1,98 +0,0 @@
<?php
namespace Alchemy\Tests\BinaryDriver;
use Alchemy\BinaryDriver\Exception\InvalidArgumentException;
use Alchemy\BinaryDriver\ProcessBuilderFactory;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Process\ExecutableFinder;
abstract class AbstractProcessBuilderFactoryTest extends TestCase
{
public static $phpBinary;
private $original;
/**
* @return ProcessBuilderFactory
*/
abstract protected function getProcessBuilderFactory($binary);
public function setUp(): void
{
ProcessBuilderFactory::$emulateSfLTS = null;
if (null === static::$phpBinary) {
$this->markTestSkipped('Unable to detect php binary, skipping');
}
}
public static function setUpBeforeClass(): void
{
$finder = new ExecutableFinder();
static::$phpBinary = $finder->find('php');
}
public function testThatBinaryIsSetOnConstruction()
{
$factory = $this->getProcessBuilderFactory(static::$phpBinary);
$this->assertEquals(static::$phpBinary, $factory->getBinary());
}
public function testGetSetBinary()
{
$finder = new ExecutableFinder();
$phpUnit = $finder->find('phpunit');
if (null === $phpUnit) {
$this->markTestSkipped('Unable to detect phpunit binary, skipping');
}
$factory = $this->getProcessBuilderFactory(static::$phpBinary);
$factory->useBinary($phpUnit);
$this->assertEquals($phpUnit, $factory->getBinary());
}
public function testUseNonExistantBinary()
{
$this->expectException(InvalidArgumentException::class);
$factory = $this->getProcessBuilderFactory(static::$phpBinary);
$factory->useBinary('itissureitdoesnotexist');
}
public function testCreateShouldReturnAProcess()
{
$factory = $this->getProcessBuilderFactory(static::$phpBinary);
$process = $factory->create();
$this->assertInstanceOf('Symfony\Component\Process\Process', $process);
$this->assertEquals("'" . static::$phpBinary . "'", $process->getCommandLine());
}
public function testCreateWithStringArgument()
{
$factory = $this->getProcessBuilderFactory(static::$phpBinary);
$process = $factory->create('-v');
$this->assertInstanceOf('Symfony\Component\Process\Process', $process);
$this->assertEquals("'" . static::$phpBinary . "' '-v'", $process->getCommandLine());
}
public function testCreateWithArrayArgument()
{
$factory = $this->getProcessBuilderFactory(static::$phpBinary);
$process = $factory->create(['-r', 'echo "Hello !";']);
$this->assertInstanceOf('Symfony\Component\Process\Process', $process);
$this->assertEquals("'" . static::$phpBinary . "' '-r' 'echo \"Hello !\";'", $process->getCommandLine());
}
public function testCreateWithTimeout()
{
$factory = $this->getProcessBuilderFactory(static::$phpBinary);
$factory->setTimeout(200);
$process = $factory->create(['-i']);
$this->assertInstanceOf('Symfony\Component\Process\Process', $process);
$this->assertEquals(200, $process->getTimeout());
}
}

View file

@ -1,78 +0,0 @@
<?php
namespace Alchemy\Tests\BinaryDriver;
use Alchemy\BinaryDriver\Configuration;
use PHPUnit\Framework\TestCase;
class ConfigurationTest extends TestCase
{
public function testArrayAccessImplementation()
{
$configuration = new Configuration(['key' => 'value']);
$this->assertTrue(isset($configuration['key']));
$this->assertEquals('value', $configuration['key']);
$this->assertFalse(isset($configuration['key2']));
unset($configuration['key']);
$this->assertFalse(isset($configuration['key']));
$configuration['key2'] = 'value2';
$this->assertTrue(isset($configuration['key2']));
$this->assertEquals('value2', $configuration['key2']);
}
public function testGetOnNonExistentKeyShouldReturnDefaultValue()
{
$conf = new Configuration();
$this->assertEquals('booba', $conf->get('hooba', 'booba'));
$this->assertEquals(null, $conf->get('hooba'));
}
public function testSetHasGetRemove()
{
$configuration = new Configuration(['key' => 'value']);
$this->assertTrue($configuration->has('key'));
$this->assertEquals('value', $configuration->get('key'));
$this->assertFalse($configuration->has('key2'));
$configuration->remove('key');
$this->assertFalse($configuration->has('key'));
$configuration->set('key2', 'value2');
$this->assertTrue($configuration->has('key2'));
$this->assertEquals('value2', $configuration->get('key2'));
}
public function testIterator()
{
$data = [
'key1' => 'value1',
'key2' => 'value2',
'key3' => 'value3',
];
$captured = [];
$conf = new Configuration($data);
foreach ($conf as $key => $value) {
$captured[$key] = $value;
}
$this->assertEquals($data, $captured);
}
public function testAll()
{
$data = [
'key1' => 'value1',
'key2' => 'value2',
'key3' => 'value3',
];
$conf = new Configuration($data);
$this->assertEquals($data, $conf->all());
}
}

View file

@ -1,33 +0,0 @@
<?php
namespace Alchemy\Tests\BinaryDriver\Exceptions;
use Alchemy\BinaryDriver\BinaryDriverTestCase;
use Alchemy\BinaryDriver\Exception\ExecutionFailureException;
use Alchemy\BinaryDriver\ProcessRunner;
class ExecutionFailureExceptionTest extends BinaryDriverTestCase
{
public function getProcessRunner($logger)
{
return new ProcessRunner($logger, 'test-runner');
}
public function testGetExceptionInfo(){
$logger = $this->createLoggerMock();
$runner = $this->getProcessRunner($logger);
$process = $this->createProcessMock(1, false, '--helloworld--', null, "Error Output", true);
try{
$runner->run($process, new \SplObjectStorage(), false);
$this->fail('An exception should have been raised');
}
catch (ExecutionFailureException $e){
$this->assertEquals("--helloworld--", $e->getCommand());
$this->assertEquals("Error Output", $e->getErrorOutput());
}
}
}

View file

@ -1,54 +0,0 @@
<?php
namespace Alchemy\Tests\BinaryDriver;
use Alchemy\BinaryDriver\ProcessBuilderFactory;
use LogicException;
use Symfony\Component\Process\Process;
use Symfony\Component\Process\ProcessBuilder;
class LTSProcessBuilder extends ProcessBuilder
{
private $arguments;
private $prefix;
private $timeout;
public function __construct(array $arguments = array())
{
$this->arguments = $arguments;
parent::__construct($arguments);
}
public function setArguments(array $arguments)
{
$this->arguments = $arguments;
return $this;
}
public function setPrefix($prefix)
{
$this->prefix = $prefix;
return $this;
}
public function setTimeout($timeout)
{
$this->timeout = $timeout;
return $this;
}
public function getProcess()
{
if (!$this->prefix && !count($this->arguments)) {
throw new LogicException('You must add() command arguments before calling getProcess().');
}
$args = $this->prefix ? array_merge(array($this->prefix), $this->arguments) : $this->arguments;
$script = implode(' ', array_map('escapeshellarg', $args));
return new Process($script, null, null, null, $this->timeout);
}
}

View file

@ -1,28 +0,0 @@
<?php
namespace Alchemy\Tests\BinaryDriver;
use Alchemy\BinaryDriver\ProcessBuilderFactory;
class LTSProcessBuilderFactoryTest extends AbstractProcessBuilderFactoryTest
{
public function setUp(): void
{
if (!class_exists('Symfony\Component\Process\ProcessBuilder')) {
$this->markTestSkipped('ProcessBuilder is not available.');
return;
}
parent::setUp();
}
protected function getProcessBuilderFactory($binary)
{
$factory = new ProcessBuilderFactory($binary);
$factory->setBuilder(new LTSProcessBuilder());
ProcessBuilderFactory::$emulateSfLTS = false;
$factory->useBinary($binary);
return $factory;
}
}

View file

@ -1,34 +0,0 @@
<?php
namespace Alchemy\Tests\BinaryDriver\Listeners;
use Alchemy\BinaryDriver\Listeners\DebugListener;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Process\Process;
class DebugListenerTest extends TestCase
{
public function testHandle()
{
$listener = new DebugListener();
$lines = [];
$listener->on('debug', function ($line) use (&$lines) {
$lines[] = $line;
});
$listener->handle(Process::ERR, "first line\nsecond line");
$listener->handle(Process::OUT, "cool output");
$listener->handle('unknown', "lalala");
$listener->handle(Process::OUT, "another output\n");
$expected = [
'[ERROR] first line',
'[ERROR] second line',
'[OUT] cool output',
'[OUT] another output',
'[OUT] ',
];
$this->assertEquals($expected, $lines);
}
}

View file

@ -1,93 +0,0 @@
<?php
namespace Alchemy\Tests\BinaryDriver\Listeners;
use Alchemy\BinaryDriver\Listeners\ListenerInterface;
use Alchemy\BinaryDriver\Listeners\Listeners;
use Evenement\EventEmitter;
use PHPUnit\Framework\TestCase;
class ListenersTest extends TestCase
{
public function testRegister()
{
$listener = new MockListener();
$listeners = new Listeners();
$listeners->register($listener);
$n = 0;
$listener->on('received', function ($type, $data) use (&$n, &$capturedType, &$capturedData) {
$n++;
$capturedData = $data;
$capturedType = $type;
});
$type = 'type';
$data = 'data';
$listener->handle($type, $data);
$listener->handle($type, $data);
$listeners->unregister($listener);
$listener->handle($type, $data);
$this->assertEquals(3, $n);
$this->assertEquals($type, $capturedType);
$this->assertEquals($data, $capturedData);
}
public function testRegisterAndForwardThenUnregister()
{
$listener = new MockListener();
$target = new EventEmitter();
$n = 0;
$target->on('received', function ($type, $data) use (&$n, &$capturedType, &$capturedData) {
$n++;
$capturedData = $data;
$capturedType = $type;
});
$m = 0;
$listener->on('received', function ($type, $data) use (&$m, &$capturedType2, &$capturedData2) {
$m++;
$capturedData2 = $data;
$capturedType2 = $type;
});
$listeners = new Listeners();
$listeners->register($listener, $target);
$type = 'type';
$data = 'data';
$listener->handle($type, $data);
$listener->handle($type, $data);
$listeners->unregister($listener, $target);
$listener->handle($type, $data);
$this->assertEquals(2, $n);
$this->assertEquals(3, $m);
$this->assertEquals($type, $capturedType);
$this->assertEquals($data, $capturedData);
$this->assertEquals($type, $capturedType2);
$this->assertEquals($data, $capturedData2);
}
}
class MockListener extends EventEmitter implements ListenerInterface
{
public function handle($type, $data)
{
$this->emit('received', [$type, $data]);
}
public function forwardedEvents()
{
return ['received'];
}
}

View file

@ -1,15 +0,0 @@
<?php
namespace Alchemy\Tests\BinaryDriver;
use Alchemy\BinaryDriver\ProcessBuilderFactory;
class NONLTSProcessBuilderFactoryTest extends AbstractProcessBuilderFactoryTest
{
protected function getProcessBuilderFactory($binary)
{
ProcessBuilderFactory::$emulateSfLTS = true;
return new ProcessBuilderFactory($binary);
}
}

View file

@ -1,208 +0,0 @@
<?php
/*
* This file is part of Alchemy\BinaryDriver.
*
* (c) Alchemy <info@alchemy.fr>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Tests\BinaryDriver;
use Alchemy\BinaryDriver\ProcessRunner;
use Alchemy\BinaryDriver\BinaryDriverTestCase;
use Alchemy\BinaryDriver\Exception\ExecutionFailureException;
use Alchemy\BinaryDriver\Listeners\ListenerInterface;
use Evenement\EventEmitter;
use Symfony\Component\Process\Exception\RuntimeException as ProcessRuntimeException;
class ProcessRunnerTest extends BinaryDriverTestCase
{
public function getProcessRunner($logger)
{
return new ProcessRunner($logger, 'test-runner');
}
public function testRunSuccessFullProcess()
{
$logger = $this->createLoggerMock();
$runner = $this->getProcessRunner($logger);
$process = $this->createProcessMock(1, true, '--helloworld--', "Kikoo Romain", null, true);
$logger
->expects($this->never())
->method('error');
$logger
->expects($this->exactly(2))
->method('info');
$this->assertEquals('Kikoo Romain', $runner->run($process, new \SplObjectStorage(), false));
}
public function testRunSuccessFullProcessBypassingErrors()
{
$logger = $this->createLoggerMock();
$runner = $this->getProcessRunner($logger);
$process = $this->createProcessMock(1, true, '--helloworld--', "Kikoo Romain", null, true);
$logger
->expects($this->never())
->method('error');
$logger
->expects($this->exactly(2))
->method('info');
$this->assertEquals('Kikoo Romain', $runner->run($process, new \SplObjectStorage(), true));
}
public function testRunFailingProcess()
{
$logger = $this->createLoggerMock();
$runner = $this->getProcessRunner($logger);
$process = $this->createProcessMock(1, false, '--helloworld--', null, null, true);
$logger
->expects($this->once())
->method('error');
$logger
->expects($this->once())
->method('info');
try {
$runner->run($process, new \SplObjectStorage(), false);
$this->fail('An exception should have been raised');
} catch (ExecutionFailureException $e) {
}
}
public function testRunFailingProcessWithException()
{
$logger = $this->createLoggerMock();
$runner = $this->getProcessRunner($logger);
$exception = new ProcessRuntimeException('Process Failed');
$process = $this->getMockBuilder('Symfony\Component\Process\Process')
->disableOriginalConstructor()
->getMock();
$process->expects($this->once())
->method('run')
->will($this->throwException($exception));
$logger
->expects($this->once())
->method('error');
$logger
->expects($this->once())
->method('info');
try {
$runner->run($process, new \SplObjectStorage(), false);
$this->fail('An exception should have been raised');
} catch (ExecutionFailureException $e) {
$this->assertEquals($exception, $e->getPrevious());
}
}
public function testRunfailingProcessBypassingErrors()
{
$logger = $this->createLoggerMock();
$runner = $this->getProcessRunner($logger);
$process = $this->createProcessMock(1, false, '--helloworld--', 'Hello output', null, true);
$logger
->expects($this->once())
->method('error');
$logger
->expects($this->once())
->method('info');
$this->assertNull($runner->run($process, new \SplObjectStorage(), true));
}
public function testRunFailingProcessWithExceptionBypassingErrors()
{
$logger = $this->createLoggerMock();
$runner = $this->getProcessRunner($logger);
$exception = new ProcessRuntimeException('Process Failed');
$process = $this->getMockBuilder('Symfony\Component\Process\Process')
->disableOriginalConstructor()
->getMock();
$process->expects($this->once())
->method('run')
->will($this->throwException($exception));
$logger
->expects($this->once())
->method('error');
$logger
->expects($this->once())
->method('info');
$this->assertNull($runner->run($process, new \SplObjectStorage(), true));
}
public function testRunSuccessFullProcessWithHandlers()
{
$logger = $this->createLoggerMock();
$runner = $this->getProcessRunner($logger);
$capturedCallback = null;
$process = $this->createProcessMock(1, true, '--helloworld--', "Kikoo Romain", null, true);
$process->expects($this->once())
->method('run')
->with($this->isInstanceOf('Closure'))
->will($this->returnCallback(function ($callback) use (&$capturedCallback) {
$capturedCallback = $callback;
}));
$logger
->expects($this->never())
->method('error');
$logger
->expects($this->exactly(2))
->method('info');
$listener = new TestListener();
$storage = new \SplObjectStorage();
$storage->attach($listener);
$capturedType = $capturedData = null;
$listener->on('received', function ($type, $data) use (&$capturedType, &$capturedData) {
$capturedData = $data;
$capturedType = $type;
});
$this->assertEquals('Kikoo Romain', $runner->run($process, $storage, false));
$type = 'err';
$data = 'data';
$capturedCallback($type, $data);
$this->assertEquals($data, $capturedData);
$this->assertEquals($type, $capturedType);
}
}
class TestListener extends EventEmitter implements ListenerInterface
{
public function handle($type, $data)
{
return $this->emit('received', array($type, $data));
}
public function forwardedEvents()
{
return array();
}
}

5
tests/ExampleTest.php Normal file
View file

@ -0,0 +1,5 @@
<?php
it('can test', function () {
expect(true)->toBeTrue();
});

View file

@ -1,13 +0,0 @@
<?php
namespace Tests\FFMpeg;
use PHPUnit\Framework\TestCase;
class BaseTestCase extends TestCase
{
public function assertScalar($value, $message = '')
{
$this->assertTrue(is_scalar($value), $message);
}
}

View file

@ -1,300 +0,0 @@
<?php
namespace Tests\FFMpeg\Functional;
use FFMpeg\Coordinate\Dimension;
use FFMpeg\Filters\AdvancedMedia\TestSrcFilter;
use FFMpeg\Filters\AdvancedMedia\XStackFilter;
use FFMpeg\Format\Audio\Mp3;
use FFMpeg\Format\Video\X264;
class AdvancedMediaTest extends FunctionalTestCase
{
/**
* Path prefix to avoid conflicts with another tests.
*/
public const OUTPUT_PATH_PREFIX = 'output/advanced_media_';
public function testRunWithoutComplexFilterTestExtractAudio()
{
$ffmpeg = $this->getFFMpeg();
$inputs = [realpath(__DIR__.'/../files/Test.ogv')];
$format = new Mp3();
$output = __DIR__.'/'.self::OUTPUT_PATH_PREFIX.'extracted_with_map.mp3';
// You can run it without -filter_complex, just using -map.
$advancedMedia = $ffmpeg->openAdvanced($inputs);
$advancedMedia
->map(['0:a'], $format, $output)
->save();
$this->assertFileExists($output);
$this->assertEquals(
'MP2/3 (MPEG audio layer 2/3)',
$ffmpeg->open($output)->getFormat()->get('format_long_name')
);
unlink($output);
}
public function testAudio()
{
$ffmpeg = $this->getFFMpeg();
$inputs = [realpath(__DIR__.'/../files/Audio.mp3')];
$format = new Mp3();
$format->setAudioKiloBitrate(30);
$output = __DIR__.'/'.self::OUTPUT_PATH_PREFIX.'audio_test.mp3';
$advancedMedia = $ffmpeg->openAdvanced($inputs);
$advancedMedia
->map(['0:a'], $format, $output)
->save();
$this->assertFileExists($output);
$this->assertEquals(
'MP2/3 (MPEG audio layer 2/3)',
$ffmpeg->open($output)->getFormat()->get('format_long_name')
);
unlink($output);
}
public function testMultipleInputs()
{
$ffmpeg = $this->getFFMpeg();
$inputs = [
realpath(__DIR__.'/../files/portrait.MOV'),
realpath(__DIR__.'/../files/portrait.MOV'),
];
$format = new X264('aac', 'libx264');
$output = __DIR__.'/'.self::OUTPUT_PATH_PREFIX.'multiple_inputs_test.mp4';
$advancedMedia = $ffmpeg->openAdvanced($inputs);
$advancedMedia->filters()
->custom('[0:v][1:v]', 'hstack', '[v]');
$advancedMedia
->map(['0:a', '[v]'], $format, $output)
->save();
$this->assertFileExists($output);
$this->assertEquals(
'QuickTime / MOV',
$ffmpeg->open($output)->getFormat()->get('format_long_name')
);
unlink($output);
}
/**
* @covers \FFMpeg\Media\AdvancedMedia::map
*/
public function testMultipleOutputsTestAbsenceOfInputs()
{
$ffmpeg = $this->getFFMpeg();
// in this test we use only computed inputs
// and can ignore -i part of the command, pass empty inputs array.
$inputs = [];
$formatX264 = new X264('aac', 'libx264');
$formatMp3 = new Mp3();
$outputMp3 = __DIR__.'/'.self::OUTPUT_PATH_PREFIX.'test_multiple_outputs.mp3';
$outputVideo1 = __DIR__.'/'.self::OUTPUT_PATH_PREFIX.'test_multiple_outputs_v1.mp4';
$outputVideo2 = __DIR__.'/'.self::OUTPUT_PATH_PREFIX.'test_multiple_outputs_v2.mp4';
$advancedMedia = $ffmpeg->openAdvanced($inputs);
$advancedMedia->filters()
->sine('[a]', 5)
->testSrc('[v1]', TestSrcFilter::TESTSRC, '160x120', 5)
->testSrc('[v2]', TestSrcFilter::TESTSRC, '160x120', 5)
->custom('[v1]', 'negate', '[v1negate]')
->custom('[v2]', 'edgedetect', '[v2edgedetect]');
$advancedMedia
->map(['[a]'], $formatMp3, $outputMp3)
->map(['[v1negate]'], $formatX264, $outputVideo1)
->map(['[v2edgedetect]'], $formatX264, $outputVideo2)
->save();
$this->assertFileExists($outputMp3);
$this->assertEquals(
'MP2/3 (MPEG audio layer 2/3)',
$ffmpeg->open($outputMp3)->getFormat()->get('format_long_name')
);
unlink($outputMp3);
$this->assertFileExists($outputVideo1);
$this->assertEquals(
'QuickTime / MOV',
$ffmpeg->open($outputVideo1)->getFormat()->get('format_long_name')
);
unlink($outputVideo1);
$this->assertFileExists($outputVideo2);
$this->assertEquals(
'QuickTime / MOV',
$ffmpeg->open($outputVideo2)->getFormat()->get('format_long_name')
);
unlink($outputVideo2);
}
/**
* @covers \FFMpeg\Filters\AdvancedMedia\TestSrcFilter
* @covers \FFMpeg\Filters\AdvancedMedia\SineFilter
*/
public function testTestSrcFilterTestSineFilter()
{
$ffmpeg = $this->getFFMpeg();
$inputs = [realpath(__DIR__.'/../files/Test.ogv')];
$format = new X264('aac', 'libx264');
$output = __DIR__.'/'.self::OUTPUT_PATH_PREFIX.'testsrc.mp4';
$advancedMedia = $ffmpeg->openAdvanced($inputs);
$advancedMedia->filters()
->sine('[a]', 10)
->testSrc('[v]', TestSrcFilter::TESTSRC, '160x120', 10);
$advancedMedia
->map(['[a]', '[v]'], $format, $output)
->save();
$this->assertFileExists($output);
$this->assertEquals(
'QuickTime / MOV',
$ffmpeg->open($output)->getFormat()->get('format_long_name')
);
unlink($output);
}
/**
* XStack filter is supported starting from 4.1 ffmpeg version.
*
* @covers \FFMpeg\Filters\AdvancedMedia\XStackFilter
* @covers \FFMpeg\Filters\AdvancedMedia\SineFilter
*/
public function testXStackFilter()
{
$xStack = new XStackFilter('', 0);
$ffmpeg = $this->getFFMpeg();
$ffmpegVersion = $ffmpeg->getFFMpegDriver()->getVersion();
if (version_compare($ffmpegVersion, $xStack->getMinimalFFMpegVersion(), '<')) {
$this->markTestSkipped('XStack filter is supported starting from ffmpeg version '
.$xStack->getMinimalFFMpegVersion().', your version is '
.$ffmpegVersion);
return;
}
$inputs = [realpath(__DIR__.'/../files/Test.ogv')];
$format = new X264('aac', 'libx264');
$output = __DIR__.'/'.self::OUTPUT_PATH_PREFIX.'xstack_test.mp4';
$advancedMedia = $ffmpeg->openAdvanced($inputs);
$advancedMedia->filters()
->sine('[a]', 5)
->testSrc('[v1]', TestSrcFilter::TESTSRC, '160x120', 5)
->testSrc('[v2]', TestSrcFilter::TESTSRC, '160x120', 5)
->testSrc('[v3]', TestSrcFilter::TESTSRC, '160x120', 5)
->testSrc('[v4]', TestSrcFilter::TESTSRC, '160x120', 5)
->xStack(
'[v1][v2][v3][v4]',
XStackFilter::LAYOUT_2X2,
4,
'[v]'
);
$advancedMedia
->map(['[a]', '[v]'], $format, $output)
->save();
$this->assertFileExists($output);
$this->assertEquals(
'QuickTime / MOV',
$ffmpeg->open($output)->getFormat()->get('format_long_name')
);
unlink($output);
}
public function testOfCompatibilityWithExistedFilters()
{
$ffmpeg = $this->getFFMpeg();
$inputs = [realpath(__DIR__.'/../files/Test.ogv')];
$watermark = realpath(__DIR__.'/../files/watermark.png');
$format = new X264('aac', 'libx264');
$output = __DIR__.'/'.self::OUTPUT_PATH_PREFIX.'test_of_compatibility_with_existed_filters.mp4';
$advancedMedia = $ffmpeg->openAdvanced($inputs);
$advancedMedia->filters()
// For unknown reasons WatermarkFilter produce an error on Windows,
// because the path to the watermark becomes corrupted.
// This behaviour related with Alchemy\BinaryDriver\AbstractBinary::command().
// The path inside filter becomes like
// "D:ServerswwwPHP-FFMpegtestsfileswatermark.png" (without slashes).
// But on Linux systems filter works as expected.
//->watermark('[0:v]', $watermark, '[v]')
->pad('[0:v]', new Dimension(300, 100), '[v]');
$advancedMedia
->map(['0:a', '[v]'], $format, $output)
->save();
$this->assertFileExists($output);
$this->assertEquals(
'QuickTime / MOV',
$ffmpeg->open($output)->getFormat()->get('format_long_name')
);
unlink($output);
}
public function testForceDisableAudio()
{
$ffmpeg = $this->getFFMpeg();
$format = new X264();
$advancedMedia1 = $ffmpeg->openAdvanced([__FILE__]);
$advancedMedia1
->map(['test'], $format, 'outputFile.mp4', false);
$this->assertStringContainsString('acodec', $advancedMedia1->getFinalCommand());
$advancedMedia2 = $ffmpeg->openAdvanced([__FILE__]);
$advancedMedia2
->map(['test'], $format, 'outputFile.mp4', true);
$this->assertStringNotContainsString('acodec', $advancedMedia2->getFinalCommand());
}
public function testForceDisableVideo()
{
$ffmpeg = $this->getFFMpeg();
$format = new X264();
$advancedMedia1 = $ffmpeg->openAdvanced([__FILE__]);
$advancedMedia1->map(
['test'],
$format,
'outputFile.mp4',
false,
false
);
$this->assertStringContainsString('vcodec', $advancedMedia1->getFinalCommand());
$advancedMedia2 = $ffmpeg->openAdvanced([__FILE__]);
$advancedMedia2->map(
['test'],
$format,
'outputFile.mp4',
false,
true
);
$this->assertStringNotContainsString('vcodec', $advancedMedia2->getFinalCommand());
}
public function testGlobalOptions()
{
$configuration = [
'ffmpeg.threads' => 3,
'ffmpeg.filter_threads' => 13,
'ffmpeg.filter_complex_threads' => 24,
];
$ffmpeg = $this->getFFMpeg($configuration);
$advancedMedia = $ffmpeg->openAdvanced([__FILE__]);
$command = $advancedMedia->getFinalCommand();
foreach ($configuration as $optionName => $optionValue) {
$optionName = str_replace('ffmpeg.', '', $optionName);
$this->assertStringContainsString('-'.$optionName.' '.$optionValue, $command);
}
}
}

View file

@ -1,28 +0,0 @@
<?php
namespace Tests\FFMpeg\Functional;
class AudioConcatenationTest extends FunctionalTestCase
{
public function testSimpleAudioFileConcatTest()
{
$ffmpeg = $this->getFFMpeg();
$files = [
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);
}
}

View file

@ -1,40 +0,0 @@
<?php
namespace Tests\FFMpeg\Functional;
use FFMpeg\FFProbe;
class FFProbeTest extends FunctionalTestCase
{
public function testProbeOnFile()
{
$ffprobe = FFProbe::create();
$this->assertGreaterThan(0, count($ffprobe->streams(__DIR__.'/../files/Audio.mp3')));
}
public function testValidateExistingFile()
{
$ffprobe = FFProbe::create();
$this->assertTrue($ffprobe->isValid(__DIR__.'/../files/sample.3gp'));
}
public function testValidateNonExistingFile()
{
$ffprobe = FFProbe::create();
$this->assertFalse($ffprobe->isValid(__DIR__.'/../files/WrongFile.mp4'));
}
public function testProbeOnNonExistantFile()
{
$this->expectException('\FFMpeg\Exception\RuntimeException');
$ffprobe = FFProbe::create();
$ffprobe->streams('/path/to/no/file');
}
public function testProbeOnRemoteFile()
{
$ffprobe = FFProbe::create();
$this->assertGreaterThan(0, count($ffprobe->streams('http://vjs.zencdn.net/v/oceans.mp4')));
}
}

View file

@ -1,19 +0,0 @@
<?php
namespace Tests\FFMpeg\Functional;
use FFMpeg\FFMpeg;
use Tests\FFMpeg\BaseTestCase;
abstract class FunctionalTestCase extends BaseTestCase
{
/**
* @param array $configuration
*
* @return FFMpeg
*/
public function getFFMpeg($configuration = [])
{
return FFMpeg::create(array_merge(['timeout' => 300], $configuration));
}
}

View file

@ -1,146 +0,0 @@
<?php
namespace Tests\FFMpeg\Functional;
use FFMpeg\Coordinate\Dimension;
use FFMpeg\Filters\Video\ResizeFilter;
use FFMpeg\Filters\Video\RotateFilter;
use FFMpeg\Format\Video\X264;
use FFMpeg\Media\Video;
class VideoTranscodeTest extends FunctionalTestCase
{
public function testSimpleTranscodeX264()
{
$filename = __DIR__.'/output/output-x264.mp4';
if (is_file($filename)) {
unlink(__DIR__.'/output/output-x264.mp4');
}
$ffmpeg = $this->getFFMpeg();
$video = $ffmpeg->open(__DIR__.'/../files/Test.ogv');
$this->assertInstanceOf('FFMpeg\Media\Video', $video);
$lastPercentage = null;
$phpunit = $this;
$codec = new X264('aac');
$codec->on('progress', function ($video, $codec, $percentage) use ($phpunit, &$lastPercentage) {
if (null !== $lastPercentage) {
$phpunit->assertGreaterThanOrEqual($lastPercentage, $percentage);
}
$lastPercentage = $percentage;
$phpunit->assertGreaterThanOrEqual(0, $percentage);
$phpunit->assertLessThanOrEqual(100, $percentage);
});
$video->save($codec, $filename);
$this->assertFileExists($filename);
unlink($filename);
}
public function testAacTranscodeX264()
{
$filename = __DIR__.'/output/output-x264_2.mp4';
if (is_file($filename)) {
unlink(__DIR__.'/output/output-x264_2.mp4');
}
$ffmpeg = $this->getFFMpeg();
$video = $ffmpeg->open(__DIR__.'/../files/sample.3gp');
$this->assertInstanceOf('FFMpeg\Media\Video', $video);
$lastPercentage = null;
$phpunit = $this;
$codec = new X264('aac');
$codec->on('progress', function ($video, $codec, $percentage) use ($phpunit, &$lastPercentage) {
if (null !== $lastPercentage) {
$phpunit->assertGreaterThanOrEqual($lastPercentage, $percentage);
}
$lastPercentage = $percentage;
$phpunit->assertGreaterThanOrEqual(0, $percentage);
$phpunit->assertLessThanOrEqual(100, $percentage);
});
$video->save($codec, $filename);
$this->assertFileExists($filename);
unlink($filename);
}
public function testTranscodeInvalidFile()
{
$this->expectException('\FFMpeg\Exception\RuntimeException');
$ffmpeg = $this->getFFMpeg();
$ffmpeg->open(__DIR__.'/../files/UnknownFileTest.ogv');
}
public function testSaveInvalidForgedVideo()
{
$ffmpeg = $this->getFFMpeg();
$video = new Video(__DIR__.'/../files/UnknownFileTest.ogv', $ffmpeg->getFFMpegDriver(), $ffmpeg->getFFProbe());
$this->expectException('\FFMpeg\Exception\RuntimeException');
$video->save(new X264('aac'), __DIR__.'/output/output-x264.mp4');
}
public function testTranscodePortraitVideo()
{
$info = $this->getNameAndVersion();
if ('avconv' === $info['name'] && version_compare($info['version'], '0.9', '<')) {
$this->markTestSkipped('This version of avconv is buggy and does not support this test.');
}
$filename = __DIR__.'/output/output-x264.mp4';
if (is_file($filename)) {
unlink(__DIR__.'/output/output-x264.mp4');
}
$ffmpeg = $this->getFFMpeg();
$video = $ffmpeg->open(__DIR__.'/../files/portrait.MOV');
$video->filters()
->resize(new Dimension(320, 240), ResizeFilter::RESIZEMODE_INSET)
->rotate(RotateFilter::ROTATE_90);
$video->save(new X264('aac'), $filename);
$dimension = $ffmpeg->getFFProbe()
->streams($filename)
->videos()
->first()
->getDimensions();
$this->assertLessThan(1, $dimension->getRatio(false)->getValue());
$this->assertEquals(240, $dimension->getHeight());
$this->assertFileExists($filename);
unlink($filename);
}
private function getNameAndVersion()
{
$binary = $this
->getFFMpeg()
->getFFMpegDriver()
->getProcessBuilderFactory()
->getBinary();
$output = $matches = null;
exec($binary.' -version 2>&1', $output);
if (!isset($output[0])) {
return ['name' => null, 'version' => null];
}
preg_match('/^([a-z]+)\s+version\s+([0-9\.]+)/i', $output[0], $matches);
if (count($matches) > 0) {
return ['name' => $matches[1], 'version' => $matches[2]];
}
return ['name' => null, 'version' => null];
}
}

View file

@ -1,83 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Coordinate;
use FFMpeg\Coordinate\AspectRatio;
use FFMpeg\Coordinate\Dimension;
use Tests\FFMpeg\Unit\TestCase;
class AspectRatioTest extends TestCase
{
/**
* @dataProvider provideDimensionsAndExpectedratio
*/
public function testFromDimensions($width, $height, $strategy, $expected, $calculatedWidth, $calculatedHeight, $modulus = 2)
{
$ratio = AspectRatio::create(new Dimension($width, $height), $strategy);
$this->assertEquals($expected, $ratio->getValue());
$this->assertEquals($calculatedHeight, $ratio->calculateHeight(240, $modulus));
$this->assertEquals($calculatedWidth, $ratio->calculateWidth(320, $modulus));
}
public function provideDimensionsAndExpectedratio()
{
return [
//AR_5_4
[720, 576, false, 5 / 4, 400, 192],
[720, 577, false, 5 / 4, 400, 192],
[720, 620, false, 720 / 620, 372, 206],
[720, 576, true, 5 / 4, 400, 192],
//AR_ROTATED_4_5
[576, 720, false, 4 / 5, 256, 300],
[576, 720, true, 4 / 5, 256, 300],
//AR_4_3
[320, 240, false, 4 / 3, 426, 180],
[320, 240, true, 4 / 3, 426, 180],
//AR_ROTATED_3_4
[240, 320, false, 3 / 4, 240, 320],
[240, 320, true, 3 / 4, 240, 320],
//AR_16_9
[1920, 1080, false, 16 / 9, 568, 136],
[1920, 1080, true, 16 / 9, 568, 136],
[1280, 720, false, 16 / 9, 568, 136],
[1280, 720, true, 16 / 9, 568, 136],
[3840, 2160, false, 16 / 9, 568, 136],
[3840, 2160, true, 16 / 9, 568, 136],
// modulus 4
[1920, 1080, false, 16 / 9, 568, 136, 4],
[1920, 1080, true, 16 / 9, 568, 136, 4],
[1280, 720, false, 16 / 9, 568, 136, 4],
[1280, 720, true, 16 / 9, 568, 136, 4],
[3840, 2160, false, 16 / 9, 568, 136, 4],
[3840, 2160, true, 16 / 9, 568, 136, 4],
// modulus 16
[1920, 1080, false, 16 / 9, 576, 128, 16],
[1920, 1080, true, 16 / 9, 576, 128, 16],
[1280, 720, false, 16 / 9, 576, 128, 16],
[1280, 720, true, 16 / 9, 576, 128, 16],
[3840, 2160, false, 16 / 9, 576, 128, 16],
[3840, 2160, true, 16 / 9, 576, 128, 16],
//AR_ROTATED_9_16
[1080, 1920, false, 9 / 16, 180, 426],
[1080, 1920, true, 9 / 16, 180, 426],
[720, 1280, false, 9 / 16, 180, 426],
[720, 1280, true, 9 / 16, 180, 426],
[2160, 3840, false, 9 / 16, 180, 426],
[2160, 3840, true, 9 / 16, 180, 426],
//AR_3_2
[360, 240, false, 3 / 2, 480, 160],
[360, 240, true, 3 / 2, 480, 160],
//AR_ROTATED_2_3
[240, 360, false, 2 / 3, 214, 360],
[240, 360, true, 2 / 3, 214, 360],
//AR_5_3
//AR_ROTATED_3_5
//AR_1_1
//AR_1_DOT_85_1
//AR_ROTATED_1_DOT_85
//AR_2_DOT_39_1
//AR_ROTATED_2_DOT_39
];
}
}

View file

@ -1,38 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Coordinate;
use FFMpeg\Coordinate\Dimension;
use Tests\FFMpeg\Unit\TestCase;
class DimensionTest extends TestCase
{
/**
* @dataProvider provideInvalidDimensions
*/
public function testInvalidDimensions($width, $height)
{
$this->expectException('\FFMpeg\Exception\InvalidArgumentException');
new Dimension($width, $height);
}
public function provideInvalidDimensions()
{
return [
[320, 0],
[320, -10],
[0, 240],
[-10, 240],
[0, 0],
[0, -10],
[-10, 0],
];
}
public function testGetters()
{
$dimension = new Dimension(320, 240);
$this->assertEquals(320, $dimension->getWidth());
$this->assertEquals(240, $dimension->getHeight());
}
}

View file

@ -1,31 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Coordinate;
use FFMpeg\Coordinate\FrameRate;
use Tests\FFMpeg\Unit\TestCase;
class FrameRateTest extends TestCase
{
public function testGetter()
{
$fr = new FrameRate(23.997);
$this->assertEquals(23.997, $fr->getValue());
}
/**
* @dataProvider provideInvalidFrameRates
*/
public function testInvalidFrameRate($value)
{
$this->expectException('\FFMpeg\Exception\InvalidArgumentException');
new FrameRate($value);
}
public function provideInvalidFrameRates()
{
return [
[0], [-1.5], [-2],
];
}
}

View file

@ -1,23 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Coordinate;
use FFMpeg\Coordinate\Point;
use Tests\FFMpeg\Unit\TestCase;
class PointTest extends TestCase
{
public function testGetters()
{
$point = new Point(4, 25);
$this->assertEquals(4, $point->getX());
$this->assertEquals(25, $point->getY());
}
public function testDynamicPointGetters()
{
$point = new Point('t*100', 't', true);
$this->assertEquals('t*100', $point->getX());
$this->assertEquals('t', $point->getY());
}
}

View file

@ -1,58 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Coordinate;
use FFMpeg\Coordinate\TimeCode;
use Tests\FFMpeg\Unit\TestCase;
class TimeCodeTest extends TestCase
{
/**
* @dataProvider provideTimecodes
*/
public function testFromString($timecode, $expected)
{
$tc = TimeCode::fromString($timecode);
$this->assertEquals((string) $tc, $expected);
}
public function provideTimeCodes()
{
return [
['1:02:04:05:20', '26:04:05.20'],
['1:02:04:05.20', '26:04:05.20'],
['02:04:05:20', '02:04:05.20'],
['02:04:05.20', '02:04:05.20'],
['00:00:05.20', '00:00:05.20'],
['00:00:00.00', '00:00:00.00'],
];
}
public function testFromInvalidString()
{
$this->expectException('\FFMpeg\Exception\InvalidArgumentException');
TimeCode::fromString('lalali lala');
}
/**
* @dataProvider provideSeconds
*/
public function testFromSeconds($seconds, $expected)
{
$tc = TimeCode::fromSeconds($seconds);
$this->assertEquals($expected, (string) $tc);
}
public function provideSeconds()
{
return [
[0.467, '00:00:00.47'],
[12.467, '00:00:12.47'],
[59.867, '00:00:59.87'],
[72.467, '00:01:12.47'],
[3599.467, '00:59:59.47'],
[3600.467, '01:00:00.47'],
[86422.467, '24:00:22.47'],
];
}
}

View file

@ -1,49 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Driver;
use Alchemy\BinaryDriver\Configuration;
use FFMpeg\Driver\FFMpegDriver;
use Symfony\Component\Process\ExecutableFinder;
use Tests\FFMpeg\Unit\TestCase;
class FFMpegDriverTest extends TestCase
{
public function setUp(): void
{
$executableFinder = new ExecutableFinder();
$found = false;
foreach (['avconv', 'ffmpeg'] as $name) {
if (null !== $executableFinder->find($name)) {
$found = true;
break;
}
}
if (!$found) {
$this->markTestSkipped('Neither ffmpeg or avconv found');
}
}
public function testCreate()
{
$logger = $this->getLoggerMock();
$ffmpeg = FFMpegDriver::create($logger, []);
$this->assertInstanceOf('FFMpeg\Driver\FFMpegDriver', $ffmpeg);
$this->assertEquals($logger, $ffmpeg->getProcessRunner()->getLogger());
}
public function testCreateWithConfig()
{
$conf = new Configuration();
$ffmpeg = FFMpegDriver::create($this->getLoggerMock(), $conf);
$this->assertEquals($conf, $ffmpeg->getConfiguration());
}
public function testCreateFailureThrowsAnException()
{
$this->expectException('\FFMpeg\Exception\ExecutableNotFoundException');
FFMpegDriver::create($this->getLoggerMock(), ['ffmpeg.binaries' => '/path/to/nowhere']);
}
}

View file

@ -1,49 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Driver;
use Alchemy\BinaryDriver\Configuration;
use FFMpeg\Driver\FFProbeDriver;
use Symfony\Component\Process\ExecutableFinder;
use Tests\FFMpeg\Unit\TestCase;
class FFProbeDriverTest extends TestCase
{
public function setUp(): void
{
$executableFinder = new ExecutableFinder();
$found = false;
foreach (['avprobe', 'ffprobe'] as $name) {
if (null !== $executableFinder->find($name)) {
$found = true;
break;
}
}
if (!$found) {
$this->markTestSkipped('Neither ffprobe or avprobe found');
}
}
public function testCreate()
{
$logger = $this->getLoggerMock();
$ffprobe = FFProbeDriver::create([], $logger);
$this->assertInstanceOf('FFMpeg\Driver\FFProbeDriver', $ffprobe);
$this->assertEquals($logger, $ffprobe->getProcessRunner()->getLogger());
}
public function testCreateWithConfig()
{
$conf = new Configuration();
$ffprobe = FFProbeDriver::create($conf, $this->getLoggerMock());
$this->assertEquals($conf, $ffprobe->getConfiguration());
}
public function testCreateFailureThrowsAnException()
{
$this->expectException('\FFMpeg\Exception\ExecutableNotFoundException');
FFProbeDriver::create(['ffprobe.binaries' => '/path/to/nowhere']);
}
}

View file

@ -1,110 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit;
use FFMpeg\FFMpeg;
use FFMpeg\FFProbe\DataMapping\Stream;
use FFMpeg\FFProbe\DataMapping\StreamCollection;
class FFMpegTest extends TestCase
{
public function testOpenInvalid()
{
$this->expectException(
'\FFMpeg\Exception\RuntimeException',
'Unable to probe "/path/to/unknown/file"'
);
$ffmpeg = new FFMpeg($this->getFFMpegDriverMock(), $this->getFFProbeMock());
$ffmpeg->open('/path/to/unknown/file');
}
public function testOpenAudio()
{
$streams = $this->getStreamCollectionMock();
$streams->expects($this->once())
->method('audios')
->will($this->returnValue(new StreamCollection([new Stream([])])));
$streams->expects($this->once())
->method('videos')
->will($this->returnValue([]));
$ffprobe = $this->getFFProbeMock();
$ffprobe->expects($this->once())
->method('streams')
->with(__FILE__)
->will($this->returnValue($streams));
$ffmpeg = new FFMpeg($this->getFFMpegDriverMock(), $ffprobe);
$this->assertInstanceOf('FFMpeg\Media\Audio', $ffmpeg->open(__FILE__));
}
public function testOpenVideo()
{
$streams = $this->getStreamCollectionMock();
$streams->expects($this->once())
->method('videos')
->will($this->returnValue(new StreamCollection([new Stream([])])));
$streams->expects($this->never())
->method('audios');
$ffprobe = $this->getFFProbeMock();
$ffprobe->expects($this->once())
->method('streams')
->with(__FILE__)
->will($this->returnValue($streams));
$ffmpeg = new FFMpeg($this->getFFMpegDriverMock(), $ffprobe);
$this->assertInstanceOf('FFMpeg\Media\Video', $ffmpeg->open(__FILE__));
}
public function testOpenUnknown()
{
$this->expectException('\FFMpeg\Exception\InvalidArgumentException');
$ffprobe = $this->getFFProbeMock();
$ffprobe->expects($this->once())
->method('streams')
->with(__FILE__)
->will($this->returnValue(new StreamCollection()));
$ffmpeg = new FFMpeg($this->getFFMpegDriverMock(), $ffprobe);
$ffmpeg->open(__FILE__);
}
public function testCreateWithoutLoggerOrProbe()
{
$this->assertInstanceOf('FFMpeg\FFMpeg', FFMpeg::create());
}
public function testCreateWithLoggerAndProbe()
{
$logger = $this->getLoggerMock();
$ffprobe = $this->getFFProbeMock();
$ffmpeg = FFMpeg::create(['timeout' => 42], $logger, $ffprobe);
$this->assertInstanceOf('FFMpeg\FFMpeg', $ffmpeg);
$this->assertSame($logger, $ffmpeg->getFFMpegDriver()->getProcessRunner()->getLogger());
$this->assertSame($ffprobe, $ffmpeg->getFFProbe());
$this->assertSame(42, $ffmpeg->getFFMpegDriver()->getProcessBuilderFactory()->getTimeout());
}
public function testGetSetFFProbe()
{
$ffprobe = $this->getFFProbeMock();
$ffmpeg = new FFMpeg($this->getFFMpegDriverMock(), $ffprobe);
$this->assertSame($ffprobe, $ffmpeg->getFFProbe());
$anotherFFProbe = $this->getFFProbeMock();
$ffmpeg->setFFProbe($anotherFFProbe);
$this->assertSame($anotherFFProbe, $ffmpeg->getFFProbe());
}
public function testGetSetDriver()
{
$driver = $this->getFFMpegDriverMock();
$ffmpeg = new FFMpeg($driver, $this->getFFProbeMock());
$this->assertSame($driver, $ffmpeg->getFFMpegDriver());
$anotherDriver = $this->getFFMpegDriverMock();
$ffmpeg->setFFMpegDriver($anotherDriver);
$this->assertSame($anotherDriver, $ffmpeg->getFFMpegDriver());
}
}

View file

@ -1,52 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\FFProbe\DataMapping;
use FFMpeg\FFProbe\DataMapping\AbstractData;
use Tests\FFMpeg\Unit\TestCase;
class AbstractDataTest extends TestCase
{
public function testHas()
{
$imp = new Implementation(['key1' => 'value1', 'key2' => 'value2']);
$this->assertTrue($imp->has('key1'));
$this->assertTrue($imp->has('key2'));
$this->assertFalse($imp->has('value1'));
$this->assertFalse($imp->has('key3'));
}
public function testGet()
{
$imp = new Implementation(['key1' => 'value1', 'key2' => 'value2']);
$this->assertEquals('value1', $imp->get('key1'));
$this->assertEquals('value2', $imp->get('key2'));
}
public function testGetDefault()
{
$imp = new Implementation(['key1' => 'value1', 'key2' => 'value2']);
$this->assertSame('yololo', $imp->get('key3', 'yololo'));
}
public function testKeys()
{
$imp = new Implementation(['key1' => 'value1', 'key2' => 'value2']);
$this->assertEquals(['key1', 'key2'], $imp->keys());
}
public function testAll()
{
$values = ['key1' => 'value1', 'key2' => 'value2'];
$imp = new Implementation($values);
$this->assertEquals($values, $imp->all());
}
}
class Implementation extends AbstractData
{
}

View file

@ -1,89 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\FFProbe\DataMapping;
use FFMpeg\FFProbe\DataMapping\StreamCollection;
use Tests\FFMpeg\Unit\TestCase;
class StreamCollectionTest extends TestCase
{
public function testAdd()
{
$stream = $this->getStreamMock();
$collection = new StreamCollection();
$this->assertEquals([], $collection->all());
$collection->add($stream);
$this->assertEquals([$stream], $collection->all());
$collection->add($stream);
$this->assertEquals([$stream, $stream], $collection->all());
}
public function testVideos()
{
$audio = $this->getStreamMock();
$audio->expects($this->once())
->method('isVideo')
->will($this->returnValue(false));
$video = $this->getStreamMock();
$video->expects($this->once())
->method('isVideo')
->will($this->returnValue(true));
$collection = new StreamCollection([$audio, $video]);
$videos = $collection->videos();
$this->assertInstanceOf('FFMpeg\FFProbe\DataMapping\StreamCollection', $videos);
$this->assertCount(1, $videos);
$this->assertEquals([$video], $videos->all());
}
public function testAudios()
{
$audio = $this->getStreamMock();
$audio->expects($this->once())
->method('isAudio')
->will($this->returnValue(true));
$video = $this->getStreamMock();
$video->expects($this->once())
->method('isAudio')
->will($this->returnValue(false));
$collection = new StreamCollection([$audio, $video]);
$audios = $collection->audios();
$this->assertInstanceOf('FFMpeg\FFProbe\DataMapping\StreamCollection', $audios);
$this->assertCount(1, $audios);
$this->assertEquals([$audio], $audios->all());
}
public function testCount()
{
$stream = $this->getStreamMock();
$collection = new StreamCollection([$stream]);
$this->assertCount(1, $collection);
}
public function testGetIterator()
{
$audio = $this->getStreamMock();
$video = $this->getStreamMock();
$collection = new StreamCollection([$audio, $video]);
$this->assertInstanceOf('\Iterator', $collection->getIterator());
$this->assertCount(2, $collection->getIterator());
}
public function testFirst()
{
$stream1 = $this->getStreamMock();
$stream2 = $this->getStreamMock();
$coll = new StreamCollection([$stream1, $stream2]);
$this->assertSame($stream1, $coll->first());
}
}

View file

@ -1,136 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\FFProbe\DataMapping;
use FFMpeg\Coordinate\Dimension;
use FFMpeg\FFProbe\DataMapping\Stream;
use Tests\FFMpeg\Unit\TestCase;
class StreamTest extends TestCase
{
/**
* @dataProvider provideAudioCases
*/
public function testIsAudio($isAudio, $properties)
{
$stream = new Stream($properties);
$this->assertTrue($isAudio === $stream->isAudio());
}
public function provideAudioCases()
{
return [
[true, ['codec_type' => 'audio']],
[false, ['codec_type' => 'video']],
];
}
/**
* @dataProvider provideVideoCases
*/
public function testIsVideo($isVideo, $properties)
{
$stream = new Stream($properties);
$this->assertTrue($isVideo === $stream->isVideo());
}
public function provideVideoCases()
{
return [
[true, ['codec_type' => 'video']],
[false, ['codec_type' => 'audio']],
];
}
public function testGetDimensionsFromAudio()
{
$this->expectException(
'\FFMpeg\Exception\LogicException',
'Dimensions can only be retrieved from video streams.'
);
$stream = new Stream(['codec_type' => 'audio']);
$stream->getDimensions();
}
public function testGetDimensionsFromVideo()
{
$stream = new Stream(['codec_type' => 'video', 'width' => 960, 'height' => 720]);
$this->assertEquals(new Dimension(960, 720), $stream->getDimensions());
}
/**
* @dataProvider provideInvalidPropertiesForDimensionsExtraction
*/
public function testUnableToGetDimensionsFromVideo($properties)
{
$this->expectException(
'\FFMpeg\Exception\RuntimeException',
'Unable to extract dimensions.'
);
$stream = new Stream(['codec_type' => 'video', 'width' => 960]);
$stream->getDimensions();
}
public function provideInvalidPropertiesForDimensionsExtraction()
{
return [
['codec_type' => 'video', 'width' => 960],
['codec_type' => 'video', 'height' => 960],
];
}
/**
* @dataProvider providePropertiesForDimensionsExtraction
*/
public function testGetDimensionsFromVideoWithDisplayRatio($data)
{
$stream = new Stream([
'codec_type' => 'video',
'width' => $data['width'],
'height' => $data['height'],
'sample_aspect_ratio' => $data['sar'],
'display_aspect_ratio' => $data['dar'],
]);
$this->assertEquals(new Dimension($data['result_width'], $data['result_height']), $stream->getDimensions());
}
/**
* @dataProvider provideInvalidRatios
*/
public function testGetDimensionsFromVideoWithInvalidDisplayRatio($invalidRatio)
{
$stream = new Stream(['codec_type' => 'video', 'width' => 960, 'height' => 720, 'sample_aspect_ratio' => $invalidRatio, 'display_aspect_ratio' => '16:9']);
$this->assertEquals(new Dimension(960, 720), $stream->getDimensions());
}
public function provideInvalidRatios()
{
return [['0:1'], ['2:1:3']];
}
public function providePropertiesForDimensionsExtraction()
{
return [
[
['width' => '960', 'height' => '720',
'sar' => '4:3', 'dar' => '16:9',
'result_width' => '1280', 'result_height' => '720', ],
],
[
['width' => '1920', 'height' => '1080',
'sar' => '1:1', 'dar' => '16:9',
'result_width' => '1920', 'result_height' => '1080', ],
],
[
['width' => '640', 'height' => '480',
'sar' => '75:74', 'dar' => '50:37',
'result_width' => '649', 'result_height' => '480', ],
],
[
['width' => '720', 'height' => '576',
'sar' => '52:28', 'dar' => '16:9',
'result_width' => '1337', 'result_height' => '752', ],
],
];
}
}

View file

@ -1,42 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\FFProbe;
use FFMpeg\FFProbe;
use FFMpeg\FFProbe\DataMapping\Format;
use FFMpeg\FFProbe\DataMapping\Stream;
use FFMpeg\FFProbe\DataMapping\StreamCollection;
use FFMpeg\FFProbe\Mapper;
use Tests\FFMpeg\Unit\TestCase;
class MapperTest extends TestCase
{
/**
* @dataProvider provideMappings
*/
public function testMap($type, $data, $expected)
{
$mapper = new Mapper();
$this->assertEquals($expected, $mapper->map($type, $data));
}
public function testMapInvalidArgument()
{
$this->expectException('\FFMpeg\Exception\InvalidArgumentException');
$mapper = new Mapper();
$mapper->map('cool type', 'data');
}
public function provideMappings()
{
$format = json_decode(file_get_contents(__DIR__.'/../../fixtures/ffprobe/show_format.json'), true);
$streams = json_decode(file_get_contents(__DIR__.'/../../fixtures/ffprobe/show_streams.json'), true);
return [
[FFProbe::TYPE_FORMAT, $format, new Format($format['format'])],
[FFProbe::TYPE_STREAMS, $streams, new StreamCollection(array_map(function ($streamData) {
return new Stream($streamData);
}, $streams['streams']))],
];
}
}

View file

@ -1,132 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\FFProbe;
use FFMpeg\FFProbe\OptionsTester;
use Symfony\Component\Cache\CacheItem;
use Tests\FFMpeg\Unit\TestCase;
class OptionsTesterTest extends TestCase
{
public function testHasOptionWithOldFFProbe()
{
$this->expectException(
'\FFMpeg\Exception\RuntimeException',
'Your FFProbe version is too old and does not support `-help` option, please upgrade.'
);
$cache = $this->getCacheMock();
$executionFailerExceptionMock = $this->getMockBuilder('Alchemy\BinaryDriver\Exception\ExecutionFailureException')
->disableOriginalConstructor()
->getMock();
$ffprobe = $this->getFFProbeDriverMock();
$ffprobe->expects($this->once())
->method('command')
->with(['-help', '-loglevel', 'quiet'])
->will($this->throwException($executionFailerExceptionMock));
$tester = new OptionsTester($ffprobe, $cache);
$tester->has('-print_format');
}
/**
* @dataProvider provideOptions
*/
public function testHasOptionWithCacheEmpty($isPresent, $data, $optionName)
{
$cache = $this->getCacheMock();
$cache->expects($this->exactly(2))
->method('getItem')
->will($this->returnValue(new CacheItem));
$cache->expects($this->exactly(2))
->method('hasItem')
->will($this->returnValue(false));
$cache->expects($this->exactly(2))
->method('save');
$ffprobe = $this->getFFProbeDriverMock();
$ffprobe->expects($this->once())
->method('command')
->with(['-help', '-loglevel', 'quiet'])
->will($this->returnValue($data));
$tester = new OptionsTester($ffprobe, $cache);
$this->assertTrue($isPresent === $tester->has($optionName));
}
public function provideOptions()
{
$data = file_get_contents(__DIR__ . '/../../fixtures/ffprobe/help.raw');
return [
[true, $data, '-print_format'],
[false, $data, '-another_print_format'],
];
}
/**
* @dataProvider provideOptions
*/
public function testHasOptionWithHelpCacheLoaded($isPresent, $data, $optionName)
{
$cache = $this->getCacheMock();
$cacheItem = new CacheItem;
$cacheItem->set($data);
$cache->expects($this->exactly(2))
->method('getItem')
->willReturnOnConsecutiveCalls(
$this->returnValue($cacheItem),
$this->returnValue(new CacheItem)
);
$cache->expects($this->exactly(2))
->method('hasItem')
->willReturnOnConsecutiveCalls(
$this->returnValue(false),
$this->returnValue(true)
);
$cache->expects($this->once())
->method('save');
$ffprobe = $this->getFFProbeDriverMock();
$ffprobe->expects($this->never())
->method('command');
$tester = new OptionsTester($ffprobe, $cache);
$this->assertTrue($isPresent === $tester->has($optionName));
}
/**
* @dataProvider provideOptions
*/
public function testHasOptionWithCacheFullyLoaded($isPresent, $data, $optionName)
{
$cache = $this->getCacheMock();
$cacheItem = new CacheItem();
$cacheItem->set($isPresent);
$cache->expects($this->once())
->method('getItem')
->with(md5('option-' . $optionName))
->will($this->returnValue($cacheItem));
$cache->expects($this->once())
->method('hasItem')
->with(md5('option-' . $optionName))
->will($this->returnValue(true));
$ffprobe = $this->getFFProbeDriverMock();
$ffprobe->expects($this->never())
->method('command');
$tester = new OptionsTester($ffprobe, $cache);
$this->assertTrue($isPresent === $tester->has($optionName));
}
}

View file

@ -1,40 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\FFProbe;
use FFMpeg\FFProbe;
use FFMpeg\FFProbe\OutputParser;
use Tests\FFMpeg\Unit\TestCase;
class OutputParserTest extends TestCase
{
/**
* @dataProvider provideTypeDataAndOutput
*/
public function testParse($type, $data, $expectedOutput)
{
$parser = new OutputParser();
$this->assertEquals($expectedOutput, $parser->parse($type, $data));
}
public function testParseWithInvalidArgument()
{
$this->expectException('\FFMpeg\Exception\InvalidArgumentException');
$parser = new OutputParser();
$parser->parse('comme ca', 'data');
}
public function provideTypeDataAndOutput()
{
$expectedFormat = json_decode(file_get_contents(__DIR__.'/../../fixtures/ffprobe/show_format.json'), true);
$expectedStreams = json_decode(file_get_contents(__DIR__.'/../../fixtures/ffprobe/show_streams.json'), true);
$rawFormat = file_get_contents(__DIR__.'/../../fixtures/ffprobe/show_format.raw');
$rawStreams = file_get_contents(__DIR__.'/../../fixtures/ffprobe/show_streams.raw');
return [
[FFProbe::TYPE_FORMAT, $rawFormat, $expectedFormat],
[FFProbe::TYPE_STREAMS, $rawStreams, $expectedStreams],
];
}
}

View file

@ -1,301 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit;
use Alchemy\BinaryDriver\Configuration;
use Alchemy\BinaryDriver\ConfigurationInterface;
use FFMpeg\FFProbe;
use Symfony\Component\Cache\CacheItem;
use Symfony\Component\Process\ExecutableFinder;
class FFProbeTest extends TestCase
{
public function testGetSetParser()
{
$ffprobe = new FFProbe($this->getFFProbeDriverMock(), $this->getCacheMock());
$parser = $this->getFFProbeParserMock();
$ffprobe->setParser($parser);
$this->assertSame($parser, $ffprobe->getParser());
}
public function testGetSetFFProbeDriver()
{
$ffprobe = new FFProbe($this->getFFProbeDriverMock(), $this->getCacheMock());
$driver = $this->getFFProbeDriverMock();
$ffprobe->setFFProbeDriver($driver);
$this->assertSame($driver, $ffprobe->getFFProbeDriver());
}
public function testGetSetFFProbeMapper()
{
$ffprobe = new FFProbe($this->getFFProbeDriverMock(), $this->getCacheMock());
$mapper = $this->getFFProbeMapperMock();
$ffprobe->setMapper($mapper);
$this->assertSame($mapper, $ffprobe->getMapper());
}
public function testGetSetOptionsTester()
{
$ffprobe = new FFProbe($this->getFFProbeDriverMock(), $this->getCacheMock());
$tester = $this->getFFProbeOptionsTesterMock();
$ffprobe->setOptionsTester($tester);
$this->assertSame($tester, $ffprobe->getOptionsTester());
}
public function testGetSetCache()
{
$ffprobe = new FFProbe($this->getFFProbeDriverMock(), $this->getCacheMock());
$cache = $this->getCacheMock();
$ffprobe->setCache($cache);
$this->assertSame($cache, $ffprobe->getCache());
}
public function provideDataWhitoutCache()
{
$stream = $this->getStreamMock();
$format = $this->getFormatMock();
return [
[$stream, 'streams', ['-show_streams', '-print_format'], FFProbe::TYPE_STREAMS, [__FILE__, '-show_streams', '-print_format', 'json'], false],
[$format, 'format', ['-show_format', '-print_format'], FFProbe::TYPE_FORMAT, [__FILE__, '-show_format', '-print_format', 'json'], false],
[$stream, 'streams', ['-show_streams'], FFProbe::TYPE_STREAMS, [__FILE__, '-show_streams'], true],
[$format, 'format', ['-show_format'], FFProbe::TYPE_FORMAT, [__FILE__, '-show_format'], true],
];
}
/**
* @dataProvider provideDataWhitoutCache
*/
public function testProbeWithoutCache($output, $method, $commands, $type, $caughtCommands, $isRaw)
{
$pathfile = __FILE__;
$data = ['key' => 'value'];
$rawData = 'raw data';
$ffprobe = new FFProbe($this->getFFProbeDriverMock(), $this->getCacheMock());
$mapper = $this->getFFProbeMapperMock();
$mapper->expects($this->once())
->method('map')
->with($type, $data)
->will($this->returnValue($output));
$parser = $this->getFFProbeParserMock();
if ($isRaw) {
$parser->expects($this->once())
->method('parse')
->with($type, $rawData)
->will($this->returnValue($data));
} else {
$parser->expects($this->never())
->method('parse');
}
$tester = $this->getFFProbeOptionsTesterMockWithOptions($commands);
$cache = $this->getCacheMock();
$cache->expects($this->once())
->method('hasItem')
->will($this->returnValue(false));
$cache->expects($this->once())
->method('getItem')
->will($this->returnValue(new CacheItem));
$cache->expects($this->once())
->method('save')
->with($this->anything());
$driver = $this->getFFProbeDriverMock();
$driver->expects($this->once())
->method('command')
->with($caughtCommands)
->will($this->returnValue($isRaw ? $rawData : json_encode($data)));
$ffprobe->setOptionsTester($tester)
->setCache($cache)
->setMapper($mapper)
->setFFProbeDriver($driver)
->setParser($parser);
$this->assertEquals($output, call_user_func([$ffprobe, $method], $pathfile));
}
public function provideDataForInvalidJson()
{
$stream = $this->getStreamMock();
$format = $this->getFormatMock();
return [
[$stream, 'streams', ['-show_streams', '-print_format'], FFProbe::TYPE_STREAMS, [__FILE__, '-show_streams', '-print_format', 'json']],
[$format, 'format', ['-show_format', '-print_format'], FFProbe::TYPE_FORMAT, [__FILE__, '-show_format', '-print_format', 'json']],
];
}
/**
* @dataProvider provideDataForInvalidJson
*/
public function testProbeWithWrongJson($output, $method, $commands, $type, $caughtCommands)
{
$pathfile = __FILE__;
$data = ['key' => 'value'];
$ffprobe = new FFProbe($this->getFFProbeDriverMock(), $this->getCacheMock());
$mapper = $this->getFFProbeMapperMock();
$mapper->expects($this->once())
->method('map')
->with($this->isType('string'), 'good data parsed')
->will($this->returnValue($output));
$parser = $this->getFFProbeParserMock();
$parser->expects($this->once())
->method('parse')
->with($this->isType('string', json_encode($data).'lala'))
->will($this->returnValue('good data parsed'));
$tester = $this->getFFProbeOptionsTesterMockWithOptions($commands);
$cache = $this->getCacheMock();
$cache->expects($this->exactly(2))
->method('hasItem')
->will($this->returnValue(false));
$cache->expects($this->once())
->method('getItem')
->will($this->returnValue(new CacheItem));
$driver = $this->getFFProbeDriverMock();
$driver->expects($this->exactly(2))
->method('command')
->will($this->returnValue(json_encode($data).'lala'));
$ffprobe->setOptionsTester($tester)
->setCache($cache)
->setMapper($mapper)
->setFFProbeDriver($driver)
->setParser($parser);
$this->assertEquals($output, call_user_func([$ffprobe, $method], $pathfile));
}
public function provideProbingDataWithCache()
{
$stream = $this->getStreamMock();
$format = $this->getFormatMock();
return [
[$stream, 'streams'],
[$format, 'format'],
];
}
/**
* @dataProvider provideProbingDataWithCache
*/
public function testProbeWithCache($output, $method)
{
$pathfile = __FILE__;
$ffprobe = new FFProbe($this->getFFProbeDriverMock(), $this->getCacheMock());
$mapper = $this->getFFProbeMapperMock();
$mapper->expects($this->never())
->method('map');
$tester = $this->getFFProbeOptionsTesterMock();
$cacheItem = new CacheItem;
$cacheItem->set($output);
$cache = $this->getCacheMock();
$cache->expects($this->once())
->method('hasItem')
->will($this->returnValue(true));
$cache->expects($this->once())
->method('getItem')
->will($this->returnValue($cacheItem));
$cache->expects($this->never())
->method('save');
$driver = $this->getFFProbeDriverMock();
$driver->expects($this->never())
->method('command');
$ffprobe->setOptionsTester($tester)
->setCache($cache)
->setMapper($mapper)
->setFFProbeDriver($driver);
$this->assertEquals($output, call_user_func([$ffprobe, $method], $pathfile));
}
public function provideProbeMethod()
{
return [
['streams'],
['format'],
];
}
/**
* @dataProvider provideProbeMethod
*/
public function testProbeWithoutShowStreamsAvailable($method)
{
$this->expectException('\FFMpeg\Exception\RuntimeException');
$pathfile = __FILE__;
$ffprobe = new FFProbe($this->getFFProbeDriverMock(), $this->getCacheMock());
$ffprobe->setOptionsTester($this->getFFProbeOptionsTesterMock());
call_user_func([$ffprobe, $method], $pathfile);
}
/**
* @dataProvider provideCreateOptions
*/
public function testCreate($logger, $conf, $cache)
{
$finder = new ExecutableFinder();
$found = false;
foreach (['avprobe', 'ffprobe'] as $name) {
if (null !== $finder->find($name)) {
$found = true;
}
}
if (!$found) {
$this->markTestSkipped('Unable to find avprobe or ffprobe on system');
}
$ffprobe = FFProbe::create();
$this->assertInstanceOf('FFMpeg\FFprobe', $ffprobe);
$ffprobe = FFProbe::create($conf, $logger, $cache);
$this->assertInstanceOf('FFMpeg\FFprobe', $ffprobe);
if (null !== $cache) {
$this->assertSame($cache, $ffprobe->getCache());
}
if (null !== $logger) {
$this->assertSame($logger, $ffprobe->getFFProbeDriver()->getProcessRunner()->getLogger());
}
if ($conf instanceof ConfigurationInterface) {
$this->assertSame($conf, $ffprobe->getFFProbeDriver()->getConfiguration());
}
}
public function provideCreateOptions()
{
return [
[null, ['key' => 'value'], null],
[$this->getLoggerMock(), ['key' => 'value'], null],
[null, new Configuration(), null],
[null, ['key' => 'value'], $this->getCacheMock()],
];
}
}

View file

@ -1,48 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Audio;
use FFMpeg\Coordinate\TimeCode;
use FFMpeg\Filters\Audio\AudioFilters;
use Tests\FFMpeg\Unit\TestCase;
class AudioClipTest extends TestCase
{
public function testClipping()
{
$capturedFilter = null;
$audio = $this->getAudioMock();
$audio->expects($this->once())
->method('addFilter')
->with($this->isInstanceOf('FFMpeg\Filters\Audio\AudioClipFilter'))
->will($this->returnCallback(function ($filter) use (&$capturedFilter) {
$capturedFilter = $filter;
}));
$format = $this->getMockBuilder('FFMpeg\Format\AudioInterface')->getMock();
$filters = new AudioFilters($audio);
$filters->clip(TimeCode::fromSeconds(5));
$this->assertEquals([0 => '-ss', 1 => '00:00:05.00', 2 => '-acodec', 3 => 'copy'], $capturedFilter->apply($audio, $format));
}
public function testClippingWithDuration()
{
$capturedFilter = null;
$audio = $this->getAudioMock();
$audio->expects($this->once())
->method('addFilter')
->with($this->isInstanceOf('FFMpeg\Filters\Audio\AudioClipFilter'))
->will($this->returnCallback(function ($filter) use (&$capturedFilter) {
$capturedFilter = $filter;
}));
$format = $this->getMockBuilder('FFMpeg\Format\AudioInterface')->getMock();
$filters = new AudioFilters($audio);
$filters->clip(TimeCode::fromSeconds(5), TimeCode::fromSeconds(5));
$this->assertEquals([0 => '-ss', 1 => '00:00:05.00', 2 => '-t', 3 => '00:00:05.00', 4 => '-acodec', 5 => 'copy'], $capturedFilter->apply($audio, $format));
}
}

View file

@ -1,26 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Audio;
use FFMpeg\Filters\Audio\AudioFilters;
use Tests\FFMpeg\Unit\TestCase;
class AudioFiltersTest extends TestCase
{
public function testResample()
{
$capturedFilter = null;
$audio = $this->getAudioMock();
$audio->expects($this->once())
->method('addFilter')
->with($this->isInstanceOf('FFMpeg\Filters\Audio\AudioResamplableFilter'))
->will($this->returnCallback(function ($filter) use (&$capturedFilter) {
$capturedFilter = $filter;
}));
$filters = new AudioFilters($audio);
$filters->resample(8000);
$this->assertEquals(8000, $capturedFilter->getRate());
}
}

View file

@ -1,64 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Audio;
use FFMpeg\Filters\Audio\AudioFilters;
use Tests\FFMpeg\Unit\TestCase;
class AudioMetadataTest extends TestCase
{
public function testAddMetadata()
{
$capturedFilter = null;
$audio = $this->getAudioMock();
$audio->expects($this->once())
->method('addFilter')
->with($this->isInstanceOf('FFMpeg\Filters\Audio\AddMetadataFilter'))
->will($this->returnCallback(function ($filter) use (&$capturedFilter) {
$capturedFilter = $filter;
}));
$format = $this->getMockBuilder('FFMpeg\Format\AudioInterface')->getMock();
$filters = new AudioFilters($audio);
$filters->addMetadata(['title' => 'Hello World']);
$this->assertEquals([0 => '-metadata', 1 => 'title=Hello World'], $capturedFilter->apply($audio, $format));
}
public function testAddArtwork()
{
$capturedFilter = null;
$audio = $this->getAudioMock();
$audio->expects($this->once())
->method('addFilter')
->with($this->isInstanceOf('FFMpeg\Filters\Audio\AddMetadataFilter'))
->will($this->returnCallback(function ($filter) use (&$capturedFilter) {
$capturedFilter = $filter;
}));
$format = $this->getMockBuilder('FFMpeg\Format\AudioInterface')->getMock();
$filters = new AudioFilters($audio);
$filters->addMetadata(['genre' => 'Some Genre', 'artwork' => '/path/to/file.jpg']);
$this->assertEquals([0 => '-i', 1 => '/path/to/file.jpg', 2 => '-map', 3 => '0', 4 => '-map', 5 => '1', 6 => '-metadata', 7 => 'genre=Some Genre'], $capturedFilter->apply($audio, $format));
$this->assertEquals([0 => '-i', 1 => '/path/to/file.jpg', 2 => '-map', 3 => '0', 4 => '-map', 5 => '1', 6 => '-metadata', 7 => 'genre=Some Genre'], $capturedFilter->apply($audio, $format));
}
public function testRemoveMetadata()
{
$capturedFilter = null;
$audio = $this->getAudioMock();
$audio->expects($this->once())
->method('addFilter')
->with($this->isInstanceOf('FFMpeg\Filters\Audio\AddMetadataFilter'))
->will($this->returnCallback(function ($filter) use (&$capturedFilter) {
$capturedFilter = $filter;
}));
$format = $this->getMockBuilder('FFMpeg\Format\AudioInterface')->getMock();
$filters = new AudioFilters($audio);
$filters->addMetadata();
$this->assertEquals([0 => '-map_metadata', 1 => '-1', 2 => '-vn'], $capturedFilter->apply($audio, $format));
}
}

View file

@ -1,24 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Audio;
use FFMpeg\Filters\Audio\AudioResamplableFilter;
use Tests\FFMpeg\Unit\TestCase;
class AudioResamplableFilterTest extends TestCase
{
public function testGetRate()
{
$filter = new AudioResamplableFilter(500);
$this->assertEquals(500, $filter->getRate());
}
public function testApply()
{
$audio = $this->getAudioMock();
$format = $this->getMockBuilder('FFMpeg\Format\AudioInterface')->getMock();
$filter = new AudioResamplableFilter(500);
$this->assertEquals(['-ac', 2, '-ar', 500], $filter->apply($audio, $format));
}
}

View file

@ -1,18 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Audio;
use FFMpeg\Filters\Audio\CustomFilter;
use Tests\FFMpeg\Unit\TestCase;
class CustomFilterTest extends TestCase
{
public function testApplyCustomFilter()
{
$audio = $this->getAudioMock();
$format = $this->getMockBuilder('FFMpeg\Format\AudioInterface')->getMock();
$filter = new CustomFilter('whatever i put would end up as a filter');
$this->assertEquals(['-af', 'whatever i put would end up as a filter'], $filter->apply($audio, $format));
}
}

View file

@ -1,62 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters;
use FFMpeg\Filters\Audio\SimpleFilter;
use FFMpeg\Filters\FiltersCollection;
use Tests\FFMpeg\Unit\TestCase;
class FiltersCollectionTest extends TestCase
{
public function testCount()
{
$coll = new FiltersCollection();
$this->assertCount(0, $coll);
$coll->add($this->getMockBuilder('FFMpeg\Filters\FilterInterface')->getMock());
$this->assertCount(1, $coll);
$coll->add($this->getMockBuilder('FFMpeg\Filters\FilterInterface')->getMock());
$this->assertCount(2, $coll);
}
public function testIterator()
{
$coll = new FiltersCollection();
$coll->add($this->getMockBuilder('FFMpeg\Filters\FilterInterface')->getMock());
$coll->add($this->getMockBuilder('FFMpeg\Filters\FilterInterface')->getMock());
$this->assertInstanceOf('\ArrayIterator', $coll->getIterator());
$this->assertCount(2, $coll->getIterator());
}
public function testEmptyIterator()
{
$coll = new FiltersCollection();
$this->assertInstanceOf('\ArrayIterator', $coll->getIterator());
}
public function testIteratorSort()
{
$coll = new FiltersCollection();
$coll->add(new SimpleFilter(['a']));
$coll->add(new SimpleFilter(['1'], 12));
$coll->add(new SimpleFilter(['b']));
$coll->add(new SimpleFilter(['2'], 12));
$coll->add(new SimpleFilter(['c']));
$coll->add(new SimpleFilter(['3'], 10));
$coll->add(new SimpleFilter(['d']));
$coll->add(new SimpleFilter(['4'], -2));
$coll->add(new SimpleFilter(['e']));
$data = [];
$video = $this->getVideoMock();
$format = $this->getMockBuilder('FFMpeg\Format\AudioInterface')->getMock();
foreach ($coll as $filter) {
$data = array_merge($data, $filter->apply($video, $format));
}
$this->assertEquals(['1', '2', '3', 'a', 'b', 'c', 'd', 'e', '4'], $data);
}
}

View file

@ -1,17 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Frame;
use FFMpeg\Filters\Frame\CustomFrameFilter;
use Tests\FFMpeg\Unit\TestCase;
class CustomFrameFilterTest extends TestCase
{
public function testApplyCustomFrameFilter()
{
$frame = $this->getFrameMock();
$filter = new CustomFrameFilter('whatever i put would end up as a filter');
$this->assertEquals(['-vf', 'whatever i put would end up as a filter'], $filter->apply($frame));
}
}

View file

@ -1,28 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Frame;
use FFMpeg\Coordinate\TimeCode;
use FFMpeg\FFProbe\DataMapping\Stream;
use FFMpeg\FFProbe\DataMapping\StreamCollection;
use FFMpeg\Filters\Frame\DisplayRatioFixerFilter;
use FFMpeg\Media\Frame;
use Tests\FFMpeg\Unit\TestCase;
class DisplayRatioFixerFilterTest extends TestCase
{
public function testApply()
{
$stream = new Stream(['codec_type' => 'video', 'width' => 960, 'height' => 720]);
$streams = new StreamCollection([$stream]);
$video = $this->getVideoMock(__FILE__);
$video->expects($this->once())
->method('getStreams')
->will($this->returnValue($streams));
$frame = new Frame($video, $this->getFFMpegDriverMock(), $this->getFFProbeMock(), new TimeCode(0, 0, 0, 0));
$filter = new DisplayRatioFixerFilter();
$this->assertEquals(['-s', '960x720'], $filter->apply($frame));
}
}

View file

@ -1,21 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Frame;
use FFMpeg\Filters\Frame\FrameFilters;
use Tests\FFMpeg\Unit\TestCase;
class FrameFiltersTest extends TestCase
{
public function testResize()
{
$frame = $this->getFrameMock();
$filters = new FrameFilters($frame);
$frame->expects($this->once())
->method('addFilter')
->with($this->isInstanceOf('FFMpeg\Filters\Frame\DisplayRatioFixerFilter'));
$filters->fixDisplayRatio();
}
}

View file

@ -1,38 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Video;
use FFMpeg\Coordinate\Dimension;
use FFMpeg\Coordinate\Point;
use FFMpeg\FFProbe\DataMapping\Stream;
use FFMpeg\FFProbe\DataMapping\StreamCollection;
use FFMpeg\Filters\Video\CropFilter;
use Tests\FFMpeg\Unit\TestCase;
class CropFilterTest extends TestCase
{
public function testCommandParamsAreCorrectAndStreamIsUpdated()
{
$stream = new Stream(['width' => 320, 'height' => 240, 'codec_type' => 'video']);
$streams = new StreamCollection([$stream]);
$video = $this->getVideoMock();
$video->expects($this->once())
->method('getStreams')
->will($this->returnValue($streams));
$format = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$dimension = new Dimension(200, 150);
$point = new Point(25, 35);
$filter = new CropFilter($point, $dimension);
$expected = [
'-filter:v',
'crop='.$dimension->getWidth().':'.$dimension->getHeight().':'.$point->getX().':'.$point->getY(),
];
$this->assertEquals($expected, $filter->apply($video, $format));
$this->assertEquals(200, $stream->get('width'));
$this->assertEquals(150, $stream->get('height'));
}
}

View file

@ -1,18 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Video;
use FFMpeg\Filters\Video\CustomFilter;
use Tests\FFMpeg\Unit\TestCase;
class CustomFilterTest extends TestCase
{
public function testApplyCustomFilter()
{
$video = $this->getVideoMock();
$format = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$filter = new CustomFilter('whatever i put would end up as a filter');
$this->assertEquals(['-vf', 'whatever i put would end up as a filter'], $filter->apply($video, $format));
}
}

View file

@ -1,73 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Video;
use FFMpeg\FFProbe\DataMapping\Stream;
use FFMpeg\FFProbe\DataMapping\StreamCollection;
use FFMpeg\Filters\Video\ExtractMultipleFramesFilter;
use Tests\FFMpeg\Unit\TestCase;
class ExtractMultipleFramesFilterTest extends TestCase
{
/**
* @dataProvider provideFrameRates
*/
public function testApply($frameRate, $frameFileType, $destinationFolder, $duration, $modulus, $expected)
{
$video = $this->getVideoMock();
$pathfile = '/path/to/file'.mt_rand();
$format = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$format->expects($this->any())
->method('getModulus')
->will($this->returnValue($modulus));
$streams = new StreamCollection([
new Stream([
'codec_type' => 'video',
'duration' => $duration,
]),
]);
$video->expects($this->once())
->method('getStreams')
->will($this->returnValue($streams));
$filter = new ExtractMultipleFramesFilter($frameRate, $destinationFolder);
$filter->setFrameFileType($frameFileType);
$this->assertEquals($expected, $filter->apply($video, $format));
}
public function provideFrameRates()
{
return [
[ExtractMultipleFramesFilter::FRAMERATE_EVERY_SEC, 'jpg', '/', 100, 2, ['-vf', 'fps=1/1', '/frame-%03d.jpg']],
[ExtractMultipleFramesFilter::FRAMERATE_EVERY_2SEC, 'jpg', '/', 100, 2, ['-vf', 'fps=1/2', '/frame-%02d.jpg']],
[ExtractMultipleFramesFilter::FRAMERATE_EVERY_5SEC, 'jpg', '/', 100, 2, ['-vf', 'fps=1/5', '/frame-%02d.jpg']],
[ExtractMultipleFramesFilter::FRAMERATE_EVERY_10SEC, 'jpg', '/', 100, 2, ['-vf', 'fps=1/10', '/frame-%02d.jpg']],
[ExtractMultipleFramesFilter::FRAMERATE_EVERY_30SEC, 'jpg', '/', 100, 2, ['-vf', 'fps=1/30', '/frame-%02d.jpg']],
[ExtractMultipleFramesFilter::FRAMERATE_EVERY_60SEC, 'jpg', '/', 100, 2, ['-vf', 'fps=1/60', '/frame-%02d.jpg']],
[ExtractMultipleFramesFilter::FRAMERATE_EVERY_SEC, 'jpeg', '/', 100, 2, ['-vf', 'fps=1/1', '/frame-%03d.jpeg']],
[ExtractMultipleFramesFilter::FRAMERATE_EVERY_2SEC, 'jpeg', '/', 100, 2, ['-vf', 'fps=1/2', '/frame-%02d.jpeg']],
[ExtractMultipleFramesFilter::FRAMERATE_EVERY_5SEC, 'jpeg', '/', 100, 2, ['-vf', 'fps=1/5', '/frame-%02d.jpeg']],
[ExtractMultipleFramesFilter::FRAMERATE_EVERY_10SEC, 'jpeg', '/', 100, 2, ['-vf', 'fps=1/10', '/frame-%02d.jpeg']],
[ExtractMultipleFramesFilter::FRAMERATE_EVERY_30SEC, 'jpeg', '/', 100, 2, ['-vf', 'fps=1/30', '/frame-%02d.jpeg']],
[ExtractMultipleFramesFilter::FRAMERATE_EVERY_60SEC, 'jpeg', '/', 100, 2, ['-vf', 'fps=1/60', '/frame-%02d.jpeg']],
[ExtractMultipleFramesFilter::FRAMERATE_EVERY_SEC, 'png', '/', 100, 2, ['-vf', 'fps=1/1', '/frame-%03d.png']],
[ExtractMultipleFramesFilter::FRAMERATE_EVERY_2SEC, 'png', '/', 100, 2, ['-vf', 'fps=1/2', '/frame-%02d.png']],
[ExtractMultipleFramesFilter::FRAMERATE_EVERY_5SEC, 'png', '/', 100, 2, ['-vf', 'fps=1/5', '/frame-%02d.png']],
[ExtractMultipleFramesFilter::FRAMERATE_EVERY_10SEC, 'png', '/', 100, 2, ['-vf', 'fps=1/10', '/frame-%02d.png']],
[ExtractMultipleFramesFilter::FRAMERATE_EVERY_30SEC, 'png', '/', 100, 2, ['-vf', 'fps=1/30', '/frame-%02d.png']],
[ExtractMultipleFramesFilter::FRAMERATE_EVERY_60SEC, 'png', '/', 100, 2, ['-vf', 'fps=1/60', '/frame-%02d.png']],
];
}
public function testInvalidFrameFileType()
{
$this->expectException('\FFMpeg\Exception\InvalidArgumentException');
$filter = new ExtractMultipleFramesFilter('1/1', '/');
$filter->setFrameFileType('webm');
}
}

View file

@ -1,44 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Video;
use FFMpeg\Coordinate\FrameRate;
use FFMpeg\Filters\Video\FrameRateFilter;
use Tests\FFMpeg\Unit\TestCase;
class FrameRateFilterTest extends TestCase
{
public function testApplyWithAFormatThatSupportsBFrames()
{
$framerate = new FrameRate(54);
$gop = 42;
$video = $this->getVideoMock();
$format = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$format->expects($this->any())
->method('supportBFrames')
->will($this->returnValue(true));
$expected = ['-r', 54, '-b_strategy', '1', '-bf', '3', '-g', 42];
$filter = new FrameRateFilter($framerate, $gop);
$this->assertEquals($expected, $filter->apply($video, $format));
}
public function testApplyWithAFormatThatDoesNotSupportsBFrames()
{
$framerate = new FrameRate(54);
$gop = 42;
$video = $this->getVideoMock();
$format = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$format->expects($this->any())
->method('supportBFrames')
->will($this->returnValue(false));
$expected = ['-r', 54];
$filter = new FrameRateFilter($framerate, $gop);
$this->assertEquals($expected, $filter->apply($video, $format));
}
}

View file

@ -1,44 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Video;
use FFMpeg\Coordinate\Dimension;
use FFMpeg\FFProbe\DataMapping\Stream;
use FFMpeg\FFProbe\DataMapping\StreamCollection;
use FFMpeg\Filters\Video\PadFilter;
use Tests\FFMpeg\Unit\TestCase;
class PadFilterTest extends TestCase
{
/**
* @dataProvider provideDimensions
*/
public function testApply(Dimension $dimension, $width, $height, $expected)
{
$video = $this->getVideoMock();
$pathfile = '/path/to/file'.mt_rand();
$format = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$streams = new StreamCollection([
new Stream([
'codec_type' => 'video',
'width' => $width,
'height' => $height,
]),
]);
$filter = new PadFilter($dimension);
$this->assertEquals($expected, $filter->apply($video, $format));
}
public function provideDimensions()
{
return [
[new Dimension(1000, 800), 640, 480, ['-vf', 'scale=iw*min(1000/iw\,800/ih):ih*min(1000/iw\,800/ih),pad=1000:800:(1000-iw)/2:(800-ih)/2']],
[new Dimension(300, 600), 640, 480, ['-vf', 'scale=iw*min(300/iw\,600/ih):ih*min(300/iw\,600/ih),pad=300:600:(300-iw)/2:(600-ih)/2']],
[new Dimension(100, 900), 640, 480, ['-vf', 'scale=iw*min(100/iw\,900/ih):ih*min(100/iw\,900/ih),pad=100:900:(100-iw)/2:(900-ih)/2']],
[new Dimension(1200, 200), 640, 480, ['-vf', 'scale=iw*min(1200/iw\,200/ih):ih*min(1200/iw\,200/ih),pad=1200:200:(1200-iw)/2:(200-ih)/2']],
];
}
}

View file

@ -1,75 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Video;
use FFMpeg\Coordinate\Dimension;
use FFMpeg\FFProbe\DataMapping\Stream;
use FFMpeg\FFProbe\DataMapping\StreamCollection;
use FFMpeg\Filters\Video\ResizeFilter;
use Tests\FFMpeg\Unit\TestCase;
class ResizeFilterTest extends TestCase
{
/**
* @dataProvider provideDimensions
*/
public function testApply(Dimension $dimension, $mode, $width, $height, $modulus, $expected, $forceStandards = true)
{
$video = $this->getVideoMock();
$pathfile = '/path/to/file'.mt_rand();
$format = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$format->expects($this->any())
->method('getModulus')
->will($this->returnValue($modulus));
$streams = new StreamCollection([
new Stream([
'codec_type' => 'video',
'width' => $width,
'height' => $height,
]),
]);
$video->expects($this->once())
->method('getStreams')
->will($this->returnValue($streams));
$filter = new ResizeFilter($dimension, $mode, $forceStandards);
$this->assertEquals($expected, $filter->apply($video, $format));
}
public function provideDimensions()
{
return [
[new Dimension(320, 240), ResizeFilter::RESIZEMODE_FIT, 640, 480, 2, ['-vf', '[in]scale=320:240 [out]']],
[new Dimension(320, 240), ResizeFilter::RESIZEMODE_INSET, 640, 480, 2, ['-vf', '[in]scale=320:240 [out]']],
[new Dimension(320, 240), ResizeFilter::RESIZEMODE_SCALE_HEIGHT, 640, 480, 2, ['-vf', '[in]scale=320:240 [out]']],
[new Dimension(320, 240), ResizeFilter::RESIZEMODE_SCALE_WIDTH, 640, 480, 2, ['-vf', '[in]scale=320:240 [out]']],
[new Dimension(640, 480), ResizeFilter::RESIZEMODE_FIT, 320, 240, 2, ['-vf', '[in]scale=640:480 [out]']],
[new Dimension(640, 480), ResizeFilter::RESIZEMODE_INSET, 320, 240, 2, ['-vf', '[in]scale=640:480 [out]']],
[new Dimension(640, 480), ResizeFilter::RESIZEMODE_SCALE_HEIGHT, 320, 240, 2, ['-vf', '[in]scale=640:480 [out]']],
[new Dimension(640, 480), ResizeFilter::RESIZEMODE_SCALE_WIDTH, 320, 240, 2, ['-vf', '[in]scale=640:480 [out]']],
[new Dimension(640, 360), ResizeFilter::RESIZEMODE_FIT, 1280, 720, 2, ['-vf', '[in]scale=640:360 [out]']],
[new Dimension(640, 360), ResizeFilter::RESIZEMODE_INSET, 1280, 720, 2, ['-vf', '[in]scale=640:360 [out]']],
[new Dimension(640, 360), ResizeFilter::RESIZEMODE_SCALE_HEIGHT, 1280, 720, 2, ['-vf', '[in]scale=640:360 [out]']],
[new Dimension(640, 360), ResizeFilter::RESIZEMODE_SCALE_WIDTH, 1280, 720, 2, ['-vf', '[in]scale=640:360 [out]']],
[new Dimension(640, 360), ResizeFilter::RESIZEMODE_FIT, 1280, 720, 2, ['-vf', '[in]scale=640:360 [out]']],
[new Dimension(640, 360), ResizeFilter::RESIZEMODE_INSET, 1280, 720, 2, ['-vf', '[in]scale=640:360 [out]']],
[new Dimension(640, 360), ResizeFilter::RESIZEMODE_SCALE_HEIGHT, 1280, 720, 2, ['-vf', '[in]scale=640:360 [out]']],
[new Dimension(640, 360), ResizeFilter::RESIZEMODE_SCALE_WIDTH, 1280, 720, 2, ['-vf', '[in]scale=640:360 [out]']],
// test non standard dimension
[new Dimension(700, 150), ResizeFilter::RESIZEMODE_INSET, 123, 456, 2, ['-vf', '[in]scale=62:150 [out]'], true],
[new Dimension(700, 150), ResizeFilter::RESIZEMODE_INSET, 123, 456, 2, ['-vf', '[in]scale=40:150 [out]'], false],
[new Dimension(320, 320), ResizeFilter::RESIZEMODE_FIT, 640, 480, 2, ['-vf', '[in]scale=320:320 [out]']],
[new Dimension(320, 320), ResizeFilter::RESIZEMODE_INSET, 640, 480, 2, ['-vf', '[in]scale=320:240 [out]']],
[new Dimension(320, 320), ResizeFilter::RESIZEMODE_SCALE_HEIGHT, 640, 480, 2, ['-vf', '[in]scale=320:240 [out]']],
[new Dimension(320, 320), ResizeFilter::RESIZEMODE_SCALE_WIDTH, 640, 480, 2, ['-vf', '[in]scale=426:320 [out]']],
];
}
}

View file

@ -1,72 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Video;
use FFMpeg\FFProbe\DataMapping\Stream;
use FFMpeg\FFProbe\DataMapping\StreamCollection;
use FFMpeg\Filters\Video\RotateFilter;
use Tests\FFMpeg\Unit\TestCase;
class RotateFilterTest extends TestCase
{
/**
* @dataProvider provide90degresTranspositions
*/
public function testApplyWithSizeTransformation($value)
{
$stream = new Stream(['width' => 320, 'height' => 240, 'codec_type' => 'video']);
$streams = new StreamCollection([$stream]);
$video = $this->getVideoMock();
$video->expects($this->once())
->method('getStreams')
->will($this->returnValue($streams));
$format = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$filter = new RotateFilter($value);
$this->assertEquals(['-vf', $value, '-metadata:s:v:0', 'rotate=0'], $filter->apply($video, $format));
$this->assertEquals(240, $stream->get('width'));
$this->assertEquals(320, $stream->get('height'));
}
public function provide90degresTranspositions()
{
return [
[RotateFilter::ROTATE_90],
[RotateFilter::ROTATE_270],
];
}
/**
* @dataProvider provideDegresWithoutTranspositions
*/
public function testApplyWithoutSizeTransformation($value)
{
$video = $this->getVideoMock();
$video->expects($this->never())
->method('getStreams');
$format = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$filter = new RotateFilter($value);
$this->assertEquals(['-vf', $value, '-metadata:s:v:0', 'rotate=0'], $filter->apply($video, $format));
}
public function provideDegresWithoutTranspositions()
{
return [
[RotateFilter::ROTATE_180],
];
}
public function testApplyInvalidAngle()
{
$this->expectException(
'\FFMpeg\Exception\InvalidArgumentException',
'Invalid angle value.'
);
new RotateFilter('90');
}
}

View file

@ -1,18 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Video;
use FFMpeg\Filters\Video\SynchronizeFilter;
use Tests\FFMpeg\Unit\TestCase;
class SynchronizeFilterTest extends TestCase
{
public function testApply()
{
$video = $this->getVideoMock();
$format = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$filter = new SynchronizeFilter();
$this->assertEquals(['-async', '1', '-metadata:s:v:0', 'start_time=0'], $filter->apply($video, $format));
}
}

View file

@ -1,79 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Video;
use FFMpeg\Filters\Video\ResizeFilter;
use FFMpeg\Filters\Video\VideoFilters;
use Tests\FFMpeg\Unit\TestCase;
class VideoFiltersTest extends TestCase
{
/**
* @dataProvider provideResizeOptions
*/
public function testResize($mode, $forceStandards)
{
$capturedFilter = null;
$video = $this->getVideoMock();
$filters = new VideoFilters($video);
$dimension = $this->getDimensionMock();
$video->expects($this->once())
->method('addFilter')
->with($this->isInstanceOf('FFMpeg\Filters\Video\ResizeFilter'))
->will($this->returnCallback(function ($filter) use (&$capturedFilter) {
$capturedFilter = $filter;
}));
$filters->resize($dimension, $mode, $forceStandards);
$this->assertSame($mode, $capturedFilter->getMode());
$this->assertSame($forceStandards, $capturedFilter->areStandardsForced());
$this->assertSame($dimension, $capturedFilter->getDimension());
}
public function provideResizeOptions()
{
return [
[ResizeFilter::RESIZEMODE_FIT, true],
[ResizeFilter::RESIZEMODE_SCALE_WIDTH, true],
[ResizeFilter::RESIZEMODE_SCALE_HEIGHT, false],
[ResizeFilter::RESIZEMODE_INSET, false],
];
}
public function testResample()
{
$capturedFilter = null;
$video = $this->getVideoMock();
$filters = new VideoFilters($video);
$framerate = $this->getFramerateMock();
$gop = 42;
$video->expects($this->once())
->method('addFilter')
->with($this->isInstanceOf('FFMpeg\Filters\Video\FrameRateFilter'))
->will($this->returnCallback(function ($filter) use (&$capturedFilter) {
$capturedFilter = $filter;
}));
$filters->framerate($framerate, $gop);
$this->assertSame($framerate, $capturedFilter->getFramerate());
$this->assertSame($gop, $capturedFilter->getGOP());
}
public function testSynchronize()
{
$video = $this->getVideoMock();
$filters = new VideoFilters($video);
$video->expects($this->once())
->method('addFilter')
->with($this->isInstanceOf('FFMpeg\Filters\Video\SynchronizeFilter'));
$filters->synchronize();
}
}

View file

@ -1,62 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Video;
use FFMpeg\FFProbe\DataMapping\Stream;
use FFMpeg\FFProbe\DataMapping\StreamCollection;
use FFMpeg\Filters\Video\WatermarkFilter;
use Tests\FFMpeg\Unit\TestCase;
class WatermarkFilterTest extends TestCase
{
public function testApplyWatermark()
{
$stream = new Stream(['width' => 320, 'height' => 240, 'codec_type' => 'video']);
$streams = new StreamCollection([$stream]);
$video = $this->getVideoMock();
$format = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$filter = new WatermarkFilter(__DIR__.'/../../../files/watermark.png');
$this->assertEquals(['-vf', 'movie='.__DIR__.'/../../../files/watermark.png [watermark]; [in][watermark] overlay=0:0 [out]'], $filter->apply($video, $format));
// check size of video is unchanged
$this->assertEquals(320, $stream->get('width'));
$this->assertEquals(240, $stream->get('height'));
}
public function testDifferentCoordinaates()
{
$video = $this->getVideoMock();
$format = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
// test position absolute
$filter = new WatermarkFilter(__DIR__.'/../../../files/watermark.png', [
'position' => 'absolute',
'x' => 10, 'y' => 5,
]);
$this->assertEquals(['-vf', 'movie='.__DIR__.'/../../../files/watermark.png [watermark]; [in][watermark] overlay=10:5 [out]'], $filter->apply($video, $format));
// test position relative
$filter = new WatermarkFilter(__DIR__.'/../../../files/watermark.png', [
'position' => 'relative',
'bottom' => 10, 'left' => 5,
]);
$this->assertEquals(['-vf', 'movie='.__DIR__.'/../../../files/watermark.png [watermark]; [in][watermark] overlay=5:main_h - 10 - overlay_h [out]'], $filter->apply($video, $format));
// test position relative
$filter = new WatermarkFilter(__DIR__.'/../../../files/watermark.png', [
'position' => 'relative',
'bottom' => 5, 'right' => 4,
]);
$this->assertEquals(['-vf', 'movie='.__DIR__.'/../../../files/watermark.png [watermark]; [in][watermark] overlay=main_w - 4 - overlay_w:main_h - 5 - overlay_h [out]'], $filter->apply($video, $format));
// test position relative
$filter = new WatermarkFilter(__DIR__.'/../../../files/watermark.png', [
'position' => 'relative',
'left' => 5, 'top' => 11,
]);
$this->assertEquals(['-vf', 'movie='.__DIR__.'/../../../files/watermark.png [watermark]; [in][watermark] overlay=5:11 [out]'], $filter->apply($video, $format));
}
}

View file

@ -1,27 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Waveform;
use FFMpeg\FFProbe\DataMapping\Stream;
use FFMpeg\FFProbe\DataMapping\StreamCollection;
use FFMpeg\Filters\Waveform\WaveformDownmixFilter;
use FFMpeg\Media\Waveform;
use Tests\FFMpeg\Unit\TestCase;
class WaveformDownmixFilterTest extends TestCase
{
public function testApply()
{
$stream = new Stream(['codec_type' => 'audio', 'width' => 960, 'height' => 720]);
$streams = new StreamCollection([$stream]);
$audio = $this->getAudioMock(__FILE__);
$audio->expects($this->once())
->method('getStreams')
->will($this->returnValue($streams));
$waveform = new Waveform($audio, $this->getFFMpegDriverMock(), $this->getFFProbeMock(), 640, 120);
$filter = new WaveformDownmixFilter(true);
$this->assertEquals(['"aformat=channel_layouts=mono"'], $filter->apply($waveform));
}
}

View file

@ -1,21 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Waveform;
use FFMpeg\Filters\Waveform\WaveformFilters;
use Tests\FFMpeg\Unit\TestCase;
class WaveformFiltersTest extends TestCase
{
public function testResize()
{
$Waveform = $this->getWaveformMock();
$filters = new WaveformFilters($Waveform);
$Waveform->expects($this->once())
->method('addFilter')
->with($this->isInstanceOf('FFMpeg\Filters\Waveform\WaveformDownmixFilter'));
$filters->setDownmix();
}
}

View file

@ -1,13 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Format\Audio;
use FFMpeg\Format\Audio\Aac;
class AacTest extends AudioTestCase
{
public function getFormat()
{
return new Aac();
}
}

View file

@ -1,118 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Format\Audio;
use FFMpeg\Format\Audio\DefaultAudio;
use Tests\FFMpeg\Unit\TestCase;
abstract class AudioTestCase extends TestCase
{
public function testExtraParams()
{
$extraParams = $this->getFormat()->getExtraParams();
$this->assertIsArray($extraParams);
foreach ($extraParams as $param) {
$this->assertScalar($param);
}
}
public function testGetAudioCodec()
{
$this->assertScalar($this->getFormat()->getAudioCodec());
$this->assertContains($this->getFormat()->getAudioCodec(), $this->getFormat()->getAvailableAudioCodecs());
}
public function testSetAudioCodec()
{
$format = $this->getFormat();
foreach ($format->getAvailableAudioCodecs() as $codec) {
$format->setAudioCodec($codec);
$this->assertEquals($codec, $format->getAudioCodec());
}
}
public function testSetInvalidAudioCodec()
{
$this->expectException('\FFMpeg\Exception\InvalidArgumentException');
$this->getFormat()->setAudioCodec('invalid-random-audio-codec');
}
public function testGetAvailableAudioCodecs()
{
$this->assertGreaterThan(0, count($this->getFormat()->getAvailableAudioCodecs()));
}
public function testGetAudioKiloBitrate()
{
$this->assertIsInt($this->getFormat()->getAudioKiloBitrate());
}
public function testSetAudioKiloBitrate()
{
$format = $this->getFormat();
$format->setAudioKiloBitrate(256);
$this->assertEquals(256, $format->getAudioKiloBitrate());
}
public function testSetInvalidKiloBitrate()
{
$this->expectException('\FFMpeg\Exception\InvalidArgumentException');
$this->getFormat()->setAudioKiloBitrate(0);
}
public function testSetNegativeKiloBitrate()
{
$this->expectException('\FFMpeg\Exception\InvalidArgumentException');
$this->getFormat()->setAudioKiloBitrate(-10);
}
public function testGetAudioChannels()
{
$this->assertNull($this->getFormat()->getAudioChannels());
}
public function testSetAudioChannels()
{
$format = $this->getFormat();
$format->setAudioChannels(2);
$this->assertEquals(2, $format->getAudioChannels());
}
public function testSetInvalidChannels()
{
$this->expectException('\FFMpeg\Exception\InvalidArgumentException');
$this->getFormat()->setAudioChannels(0);
}
public function testSetNegativeChannels()
{
$this->expectException('\FFMpeg\Exception\InvalidArgumentException');
$this->getFormat()->setAudioChannels(-10);
}
public function testCreateProgressListener()
{
$media = $this->getMockBuilder('FFMpeg\Media\MediaTypeInterface')->getMock();
$media->expects($this->any())
->method('getPathfile')
->will($this->returnValue(__FILE__));
$format = $this->getFormat();
$ffprobe = $this->getFFProbeMock();
foreach ($format->createProgressListener($media, $ffprobe, 1, 3) as $listener) {
$this->assertInstanceOf('FFMpeg\Format\ProgressListener\AudioProgressListener', $listener);
$this->assertSame($ffprobe, $listener->getFFProbe());
$this->assertSame(__FILE__, $listener->getPathfile());
$this->assertSame(1, $listener->getCurrentPass());
$this->assertSame(3, $listener->getTotalPass());
}
}
/**
* @return DefaultAudio
*/
abstract public function getFormat();
}

View file

@ -1,13 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Format\Audio;
use FFMpeg\Format\Audio\Flac;
class FlacTest extends AudioTestCase
{
public function getFormat()
{
return new Flac();
}
}

View file

@ -1,13 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Format\Audio;
use FFMpeg\Format\Audio\Mp3;
class Mp3Test extends AudioTestCase
{
public function getFormat()
{
return new Mp3();
}
}

View file

@ -1,13 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Format\Audio;
use FFMpeg\Format\Audio\Vorbis;
class VorbisTest extends AudioTestCase
{
public function getFormat()
{
return new Vorbis();
}
}

View file

@ -1,13 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Format\Audio;
use FFMpeg\Format\Audio\Wav;
class WavTest extends AudioTestCase
{
public function getFormat()
{
return new Wav();
}
}

View file

@ -1,95 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Format\ProgressListener;
use FFMpeg\FFProbe\DataMapping\Format;
use FFMpeg\Format\ProgressListener\AudioProgressListener;
use Tests\FFMpeg\Unit\TestCase;
class AudioProgressListenerTest extends TestCase
{
/**
* @dataProvider provideData
*/
public function testHandle(
$size,
$duration,
$data,
$expectedPercent,
$expectedRemaining,
$expectedRate,
$data2,
$expectedPercent2,
$expectedRemaining2,
$expectedRate2,
$currentPass,
$totalPass
) {
$ffprobe = $this->getFFProbeMock();
$ffprobe->expects($this->once())
->method('format')
->with(__FILE__)
->will($this->returnValue(new Format([
'size' => $size,
'duration' => $duration,
])));
$listener = new AudioProgressListener($ffprobe, __FILE__, $currentPass, $totalPass);
$phpunit = $this;
$n = 0;
$listener->on('progress', function ($percent, $remaining, $rate) use (&$n, $phpunit, $expectedPercent, $expectedRemaining, $expectedRate, $expectedPercent2, $expectedRemaining2, $expectedRate2) {
if (0 === $n) {
$phpunit->assertEquals($expectedPercent, $percent);
$phpunit->assertEquals($expectedRemaining, $remaining);
$phpunit->assertEquals($expectedRate, $rate);
} elseif (1 === $n) {
$phpunit->assertEquals($expectedPercent2, $percent);
$phpunit->assertEquals($expectedRemaining2, $remaining);
$phpunit->assertLessThan($expectedRate2 + 3, $rate);
$phpunit->assertGreaterThan($expectedRate2 - 3, $rate);
}
++$n;
});
// first one does not trigger progress event
$listener->handle('any-type'.mt_rand(), $data);
sleep(1);
$listener->handle('any-type'.mt_rand(), $data);
sleep(1);
$listener->handle('any-type'.mt_rand(), $data2);
$this->assertEquals(2, $n);
}
public function provideData()
{
return [
[
2894412,
180.900750,
'size= 712kB time=00:00:45.50 bitrate= 128.1kbits/s',
25,
0,
0,
'size= 1274kB time=00:01:29.32 bitrate= 142.8kbits/s',
49,
2,
563,
1,
1,
],
[
2894412,
180.900750,
'size= 712kB time=00:00:45.50 bitrate= 128.1kbits/s',
12,
0,
0,
'size= 1274kB time=00:01:29.32 bitrate= 142.8kbits/s',
24,
2,
563,
1,
2,
],
];
}
}

View file

@ -1,113 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Format\ProgressListener;
use FFMpeg\FFProbe\DataMapping\Format;
use FFMpeg\Format\ProgressListener\VideoProgressListener;
use Tests\FFMpeg\Unit\TestCase;
class VideoProgressListenerTest extends TestCase
{
/**
* @dataProvider provideData
*/
public function testHandle(
$size,
$duration,
$newVideoDuration,
$data,
$expectedPercent,
$expectedRemaining,
$expectedRate,
$data2,
$expectedPercent2,
$expectedRemaining2,
$expectedRate2,
$currentPass,
$totalPass
) {
$ffprobe = $this->getFFProbeMock();
$ffprobe->expects($this->once())
->method('format')
->with(__FILE__)
->will($this->returnValue(new Format([
'size' => $size,
'duration' => $duration,
])));
$listener = new VideoProgressListener($ffprobe, __FILE__, $currentPass, $totalPass, $newVideoDuration);
$phpunit = $this;
$n = 0;
$listener->on('progress', function ($percent, $remaining, $rate) use (&$n, $phpunit, $expectedPercent, $expectedRemaining, $expectedRate, $expectedPercent2, $expectedRemaining2, $expectedRate2) {
if (0 === $n) {
$phpunit->assertEquals($expectedPercent, $percent);
$phpunit->assertEquals($expectedRemaining, $remaining);
$phpunit->assertEquals($expectedRate, $rate);
} elseif (1 === $n) {
$phpunit->assertEquals($expectedPercent2, $percent);
$phpunit->assertEquals($expectedRemaining2, $remaining);
$phpunit->assertLessThan($expectedRate2 + 10, $rate);
$phpunit->assertGreaterThan($expectedRate2 - 10, $rate);
}
++$n;
});
// first one does not trigger progress event
$listener->handle('any-type'.mt_rand(), $data);
sleep(1);
$listener->handle('any-type'.mt_rand(), $data);
sleep(1);
$listener->handle('any-type'.mt_rand(), $data2);
$this->assertEquals(2, $n);
}
public function provideData()
{
return [
[
147073958,
281.147533,
281.147533,
'frame= 206 fps=202 q=10.0 size= 571kB time=00:00:07.12 bitrate= 656.8kbits/s dup=9 drop=0',
2,
0,
0,
'frame= 854 fps=113 q=20.0 size= 4430kB time=00:00:33.04 bitrate=1098.5kbits/s dup=36 drop=0',
11,
32,
3868,
1,
1,
],
[
147073958,
281.147533,
281.147533,
'frame= 206 fps=202 q=10.0 size= 571kB time=00:00:07.12 bitrate= 656.8kbits/s dup=9 drop=0',
1,
0,
0,
'frame= 854 fps=113 q=20.0 size= 4430kB time=00:00:33.04 bitrate=1098.5kbits/s dup=36 drop=0',
5,
32,
3868,
1,
2,
],
[
147073958,
281.147533,
35,
'frame= 206 fps=202 q=10.0 size= 571kB time=00:00:07.12 bitrate= 656.8kbits/s dup=9 drop=0',
60,
0,
0,
'frame= 854 fps=113 q=20.0 size= 4430kB time=00:00:33.04 bitrate=1098.5kbits/s dup=36 drop=0',
97,
0,
3868,
2,
2,
],
];
}
}

View file

@ -1,16 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Format\Video;
use FFMpeg\Format\Video\X264;
use Tests\FFMpeg\Unit\TestCase;
class InitialParametersTest extends TestCase
{
public function testApplyInitialParameters()
{
$format = new X264();
$format->setInitialParameters(['-acodec', 'libopus']);
$this->assertEquals(['-acodec', 'libopus'], $format->getInitialParameters());
}
}

View file

@ -1,13 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Format\Video;
use FFMpeg\Format\Video\Ogg;
class OggTest extends VideoTestCase
{
public function getFormat()
{
return new Ogg();
}
}

View file

@ -1,90 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Format\Video;
use Tests\FFMpeg\Unit\Format\Audio\AudioTestCase;
abstract class VideoTestCase extends AudioTestCase
{
public function testGetVideoCodec()
{
$this->assertScalar($this->getFormat()->getVideoCodec());
$this->assertContains($this->getFormat()->getVideoCodec(), $this->getFormat()->getAvailableVideoCodecs());
}
public function testSupportBFrames()
{
$this->assertIsBool($this->getFormat()->supportBFrames());
}
public function testSetVideoCodec()
{
$format = $this->getFormat();
foreach ($format->getAvailableVideoCodecs() as $codec) {
$format->setVideoCodec($codec);
$this->assertEquals($codec, $format->getVideoCodec());
}
}
public function testGetKiloBitrate()
{
$this->assertIsInt($this->getFormat()->getKiloBitrate());
}
public function testSetKiloBitrate()
{
$format = $this->getFormat();
$format->setKiloBitrate(2560);
$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->getFormat()->setVideoCodec('invalid-random-video-codec');
}
public function testGetAvailableVideoCodecs()
{
$this->assertGreaterThan(0, count($this->getFormat()->getAvailableVideoCodecs()));
}
public function testCreateProgressListener()
{
$media = $this->getMockBuilder('FFMpeg\Media\MediaTypeInterface')->getMock();
$media->expects($this->any())
->method('getPathfile')
->will($this->returnValue(__FILE__));
$format = $this->getFormat();
$ffprobe = $this->getFFProbeMock();
foreach ($format->createProgressListener($media, $ffprobe, 1, 3) as $listener) {
$this->assertInstanceOf('FFMpeg\Format\ProgressListener\VideoProgressListener', $listener);
$this->assertSame($ffprobe, $listener->getFFProbe());
$this->assertSame(__FILE__, $listener->getPathfile());
$this->assertSame(1, $listener->getCurrentPass());
$this->assertSame(3, $listener->getTotalPass());
}
}
public function testGetPasses()
{
$this->assertIsInt($this->getFormat()->getPasses());
$this->assertGreaterThan(0, $this->getFormat()->getPasses());
}
public function testGetModulus()
{
$this->assertIsInt($this->getFormat()->getModulus());
$this->assertGreaterThan(0, $this->getFormat()->getModulus());
$this->assertEquals(0, $this->getFormat()->getModulus() % 2);
}
}

View file

@ -1,13 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Format\Video;
use FFMpeg\Format\Video\WMV3;
class WMV3Test extends VideoTestCase
{
public function getFormat()
{
return new WMV3();
}
}

View file

@ -1,13 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Format\Video;
use FFMpeg\Format\Video\WMV;
class WMVTest extends VideoTestCase
{
public function getFormat()
{
return new WMV();
}
}

View file

@ -1,13 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Format\Video;
use FFMpeg\Format\Video\WebM;
class WebMTest extends VideoTestCase
{
public function getFormat()
{
return new WebM();
}
}

View file

@ -1,13 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Format\Video;
use FFMpeg\Format\Video\X264;
class X264Test extends VideoTestCase
{
public function getFormat()
{
return new X264();
}
}

View file

@ -1,9 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Media;
use Tests\FFMpeg\Unit\TestCase;
abstract class AbstractMediaTestCase extends TestCase
{
}

View file

@ -1,38 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Media;
abstract class AbstractStreamableTestCase extends AbstractMediaTestCase
{
public function testGetStreams()
{
$classname = $this->getClassName();
$ffprobe = $this->getFFProbeMock();
$format = $this->getFormatMock();
$ffprobe->expects($this->once())
->method('format')
->with(__FILE__)
->will($this->returnValue($format));
$media = new $classname(__FILE__, $this->getFFMpegDriverMock(), $ffprobe);
$this->assertSame($format, $media->getFormat());
}
public function testGetFormat()
{
$classname = $this->getClassName();
$ffprobe = $this->getFFProbeMock();
$streams = $this->getStreamCollectionMock();
$ffprobe->expects($this->once())
->method('streams')
->with(__FILE__)
->will($this->returnValue($streams));
$media = new $classname(__FILE__, $this->getFFMpegDriverMock(), $ffprobe);
$this->assertSame($streams, $media->getStreams());
}
abstract protected function getClassName();
}

View file

@ -1,73 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Media;
use FFMpeg\Media\AdvancedMedia;
class AdvancedMediaTest extends AbstractMediaTestCase
{
public function testGetInputs()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$advancedMedia = new AdvancedMedia([__FILE__, __FILE__], $driver, $ffprobe);
$this->assertSame([__FILE__, __FILE__], $advancedMedia->getInputs());
}
public function testGetInputsCount()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$advancedMedia = new AdvancedMedia([__FILE__, __FILE__], $driver, $ffprobe);
$this->assertEquals(2, $advancedMedia->getInputsCount());
}
public function testFiltersReturnFilters()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$advancedMedia = new AdvancedMedia([__FILE__, __FILE__], $driver, $ffprobe);
$this->assertInstanceOf('FFMpeg\Filters\AdvancedMedia\ComplexFilters', $advancedMedia->filters());
}
public function testGetTemporaryDirectoryWithoutCustomConfiguration()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$configuration = $this->getConfigurationMock();
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$configuration->expects($this->once())
->method('get')
->with($this->equalTo('temporary_directory'))
->will($this->returnValue(null));
$advancedMedia = new AdvancedMedia([__FILE__, __FILE__], $driver, $ffprobe);
$this->assertEquals('', $advancedMedia->getTemporaryDirectory()->path());
}
public function testGetTemporaryDirectoryWithCustomConfiguration()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$configuration = $this->getConfigurationMock();
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$configuration->expects($this->once())
->method('get')
->with($this->equalTo('temporary_directory'))
->will($this->returnValue('/var/ffmpeg'));
$advancedMedia = new AdvancedMedia([__FILE__, __FILE__], $driver, $ffprobe);
$this->assertEquals('/var/ffmpeg', $advancedMedia->getTemporaryDirectory()->path());
}
}

View file

@ -1,10 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Media;
use FFMpeg\Format\AudioInterface;
use FFMpeg\Format\ProgressableInterface;
abstract class AudioProg implements ProgressableInterface, AudioInterface
{
}

View file

@ -1,341 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Media;
use FFMpeg\Exception\RuntimeException;
use FFMpeg\Media\Audio;
class AudioTest extends AbstractStreamableTestCase
{
public function testFiltersReturnsAudioFilters()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$audio = new Audio(__FILE__, $driver, $ffprobe);
$this->assertInstanceOf('FFMpeg\Filters\Audio\AudioFilters', $audio->filters());
}
public function testAddFiltersAddsAFilter()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$filters = $this->getMockBuilder('FFMpeg\Filters\FiltersCollection')
->disableOriginalConstructor()
->getMock();
$audio = new Audio(__FILE__, $driver, $ffprobe);
$audio->setFiltersCollection($filters);
$filter = $this->getMockBuilder('FFMpeg\Filters\Audio\AudioFilterInterface')->getMock();
$filters->expects($this->once())
->method('add')
->with($filter);
$audio->addFilter($filter);
}
public function testAddAVideoFilterThrowsException()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$filters = $this->getMockBuilder('FFMpeg\Filters\FiltersCollection')
->disableOriginalConstructor()
->getMock();
$audio = new Audio(__FILE__, $driver, $ffprobe);
$audio->setFiltersCollection($filters);
$filter = $this->getMockBuilder('FFMpeg\Filters\Video\VideoFilterInterface')->getMock();
$filters->expects($this->never())
->method('add');
$this->expectException('\FFMpeg\Exception\InvalidArgumentException');
$audio->addFilter($filter);
}
public function testSaveWithFailure()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$outputPathfile = '/target/file';
$format = $this->getMockBuilder('FFMpeg\Format\AudioInterface')->getMock();
$format->expects($this->any())
->method('getExtraParams')
->will($this->returnValue([]));
$configuration = $this->getMockBuilder('Alchemy\BinaryDriver\ConfigurationInterface')->getMock();
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$failure = new RuntimeException('failed to encode');
$driver->expects($this->once())
->method('command')
->will($this->throwException($failure));
$audio = new Audio(__FILE__, $driver, $ffprobe);
$this->expectException('\FFMpeg\Exception\RuntimeException');
$audio->save($format, $outputPathfile);
}
public function testSaveAppliesFilters()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$outputPathfile = '/target/file';
$format = $this->getMockBuilder('FFMpeg\Format\AudioInterface')->getMock();
$format->expects($this->any())
->method('getExtraParams')
->will($this->returnValue([]));
$configuration = $this->getMockBuilder('Alchemy\BinaryDriver\ConfigurationInterface')->getMock();
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$audio = new Audio(__FILE__, $driver, $ffprobe);
$filter = $this->getMockBuilder('FFMpeg\Filters\Audio\AudioFilterInterface')->getMock();
$filter->expects($this->once())
->method('apply')
->with($audio, $format)
->will($this->returnValue(['extra-filter-command']));
$capturedCommands = [];
$driver->expects($this->once())
->method('command')
->with($this->isType('array'), false, $this->anything())
->will($this->returnCallback(function ($commands, $errors, $listeners) use (&$capturedCommands) {
$capturedCommands[] = $commands;
}));
$audio->addFilter($filter);
$audio->save($format, $outputPathfile);
foreach ($capturedCommands as $commands) {
$this->assertEquals('-y', $commands[0]);
$this->assertEquals('-i', $commands[1]);
$this->assertEquals(__FILE__, $commands[2]);
$this->assertEquals('extra-filter-command', $commands[3]);
}
}
/**
* @dataProvider provideSaveData
*/
public function testSaveShouldSave($threads, $expectedCommands, $expectedListeners, $format)
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$configuration = $this->getMockBuilder('Alchemy\BinaryDriver\ConfigurationInterface')->getMock();
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$configuration->expects($this->once())
->method('has')
->with($this->equalTo('ffmpeg.threads'))
->will($this->returnValue($threads));
if ($threads) {
$configuration->expects($this->once())
->method('get')
->with($this->equalTo('ffmpeg.threads'))
->will($this->returnValue(24));
} else {
$configuration->expects($this->never())
->method('get');
}
$capturedCommand = $capturedListeners = null;
$driver->expects($this->once())
->method('command')
->with($this->isType('array'), false, $this->anything())
->will($this->returnCallback(function ($commands, $errors, $listeners) use (&$capturedCommand, &$capturedListeners) {
$capturedCommand = $commands;
$capturedListeners = $listeners;
}));
$outputPathfile = '/target/file';
$audio = new Audio(__FILE__, $driver, $ffprobe);
$audio->save($format, $outputPathfile);
$this->assertEquals($expectedCommands, $capturedCommand);
$this->assertEquals($expectedListeners, $capturedListeners);
}
public function provideSaveData()
{
$format = $this->getMockBuilder('FFMpeg\Format\AudioInterface')->getMock();
$format->expects($this->any())
->method('getExtraParams')
->will($this->returnValue([]));
$format->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(663));
$format->expects($this->any())
->method('getAudioChannels')
->will($this->returnValue(5));
$audioFormat = $this->getMockBuilder('FFMpeg\Format\AudioInterface')->getMock();
$audioFormat->expects($this->any())
->method('getExtraParams')
->will($this->returnValue([]));
$audioFormat->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(664));
$audioFormat->expects($this->any())
->method('getAudioChannels')
->will($this->returnValue(5));
$audioFormat->expects($this->any())
->method('getAudioCodec')
->will($this->returnValue('patati-patata-audio'));
$formatExtra = $this->getMockBuilder('FFMpeg\Format\AudioInterface')->getMock();
$formatExtra->expects($this->any())
->method('getExtraParams')
->will($this->returnValue(['extra', 'param']));
$formatExtra->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(665));
$formatExtra->expects($this->any())
->method('getAudioChannels')
->will($this->returnValue(5));
$listeners = [$this->getMockBuilder('Alchemy\BinaryDriver\Listeners\ListenerInterface')->getMock()];
$progressableFormat = $this->getMockBuilder('Tests\FFMpeg\Unit\Media\AudioProg')
->disableOriginalConstructor()->getMock();
$progressableFormat->expects($this->any())
->method('getExtraParams')
->will($this->returnValue([]));
$progressableFormat->expects($this->any())
->method('createProgressListener')
->will($this->returnValue($listeners));
$progressableFormat->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(666));
$progressableFormat->expects($this->any())
->method('getAudioChannels')
->will($this->returnValue(5));
return [
[false, [
'-y', '-i', __FILE__,
'-b:a', '663k',
'-ac', '5',
'/target/file',
], null, $format],
[false, [
'-y', '-i', __FILE__,
'-acodec', 'patati-patata-audio',
'-b:a', '664k',
'-ac', '5',
'/target/file',
], null, $audioFormat],
[false, [
'-y', '-i', __FILE__,
'extra', 'param',
'-b:a', '665k',
'-ac', '5',
'/target/file',
], null, $formatExtra],
[true, [
'-y', '-i', __FILE__,
'-threads', 24,
'-b:a', '663k',
'-ac', '5',
'/target/file',
], null, $format],
[true, [
'-y', '-i', __FILE__,
'extra', 'param',
'-threads', 24,
'-b:a', '665k',
'-ac', '5',
'/target/file',
], null, $formatExtra],
[false, [
'-y', '-i', __FILE__,
'-b:a', '666k',
'-ac', '5',
'/target/file',
], $listeners, $progressableFormat],
[true, [
'-y', '-i', __FILE__,
'-threads', 24,
'-b:a', '666k',
'-ac', '5',
'/target/file',
], $listeners, $progressableFormat],
];
}
public function testSaveShouldNotStoreCodecFiltersInTheMedia()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$configuration = $this->getMockBuilder('Alchemy\BinaryDriver\ConfigurationInterface')->getMock();
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$configuration->expects($this->any())
->method('has')
->with($this->equalTo('ffmpeg.threads'))
->will($this->returnValue(true));
$configuration->expects($this->any())
->method('get')
->with($this->equalTo('ffmpeg.threads'))
->will($this->returnValue(24));
$capturedCommands = [];
$driver->expects($this->exactly(2))
->method('command')
->with($this->isType('array'), false, $this->anything())
->will($this->returnCallback(function ($commands, $errors, $listeners) use (&$capturedCommands, &$capturedListeners) {
$capturedCommands[] = $commands;
}));
$outputPathfile = '/target/file';
$format = $this->getMockBuilder('FFMpeg\Format\AudioInterface')->getMock();
$format->expects($this->any())
->method('getExtraParams')
->will($this->returnValue(['param']));
$audio = new Audio(__FILE__, $driver, $ffprobe);
$audio->save($format, $outputPathfile);
$audio->save($format, $outputPathfile);
$expected = [
'-y', '-i', __FILE__, 'param', '-threads', 24, '/target/file',
];
foreach ($capturedCommands as $capturedCommand) {
$this->assertEquals($expected, $capturedCommand);
}
}
public function getClassName()
{
return 'FFMpeg\Media\Audio';
}
}

View file

@ -1,67 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Media;
use FFMpeg\Media\Clip;
class ClipTest extends AbstractMediaTestCase
{
/**
* @dataProvider provideBuildOptions
*/
public function testBuildCommand($startValue, $durationValue, $commands)
{
$configuration = $this->getConfigurationMock();
$driver = $this->getFFMpegDriverMock();
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$ffprobe = $this->getFFProbeMock();
$start = $this->getTimeCodeMock();
$start->expects($this->once())
->method('__toString')
->will($this->returnValue($startValue));
$duration = null;
if (null !== $durationValue) {
$duration = $this->getTimeCodeMock();
$duration->expects($this->once())
->method('__toString')
->will($this->returnValue($durationValue));
}
$outputPathfile = '/target/file';
$format = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$format->expects($this->any())
->method('getPasses')
->will($this->returnValue(1));
$format->expects($this->any())
->method('getExtraParams')
->will($this->returnValue([]));
$clip = new Clip($this->getVideoMock(__FILE__), $driver, $ffprobe, $start, $duration);
$fc = $clip->getFinalCommand($format, $outputPathfile);
$this->assertCount(1, $fc);
$this->assertStringStartsWith(implode(' ', $commands), $fc[0]);
}
public function provideBuildOptions()
{
return [
['SS01', null, [
'-y', '-ss', 'SS01',
'-i', __FILE__, ],
],
['SS02', 'D02', [
'-y', '-ss', 'SS02',
'-i', __FILE__,
'-t', 'D02', ],
],
];
}
}

View file

@ -1,161 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Media;
use FFMpeg\Media\Concat;
use Mockery;
use Spatie\TemporaryDirectory\TemporaryDirectory;
class ConcatTest extends AbstractMediaTestCase
{
public function testGetSources()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$concat = new Concat([__FILE__, __FILE__], $driver, $ffprobe);
$this->assertSame([__FILE__, __FILE__], $concat->getSources());
}
public function testFiltersReturnFilters()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$concat = new Concat([__FILE__, __FILE__], $driver, $ffprobe);
$this->assertInstanceOf('FFMpeg\Filters\Concat\ConcatFilters', $concat->filters());
}
public function testAddFiltersAddsAFilter()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$filters = $this->getMockBuilder('FFMpeg\Filters\FiltersCollection')
->disableOriginalConstructor()
->getMock();
$filter = $this->getMockBuilder('FFMpeg\Filters\Concat\ConcatFilterInterface')->getMock();
$filters->expects($this->once())
->method('add')
->with($filter);
$concat = new Concat([__FILE__, __FILE__], $driver, $ffprobe);
$concat->setFiltersCollection($filters);
$concat->addFilter($filter);
}
/**
* @dataProvider provideSaveFromSameCodecsOptions
*/
public function testSaveFromSameCodecs($streamCopy, $commands)
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$pathfile = '/target/destination';
array_push($commands, $pathfile);
$configuration = Mockery::mock('Alchemy\BinaryDriver\ConfigurationInterface');
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$configuration->shouldReceive('get')
->once()
->with('temporary_directory')
->andReturnNull();
$driver->expects($this->exactly(1))
->method('command')
->with($this->isType('array'), false, $this->anything())
->will($this->returnCallback(function ($commands, $errors, $listeners) {
}));
$concat = new Concat([__FILE__, 'concat-2.mp4'], $driver, $ffprobe);
$concat->saveFromSameCodecs($pathfile, $streamCopy);
$this->assertEquals('-f', $commands[0]);
$this->assertEquals('concat', $commands[1]);
$this->assertEquals('-safe', $commands[2]);
$this->assertEquals('0', $commands[3]);
$this->assertEquals('-i', $commands[4]);
if (isset($commands[6]) && (0 == strcmp($commands[6], '-c'))) {
$this->assertEquals('-c', $commands[6]);
$this->assertEquals('copy', $commands[7]);
}
}
public function provideSaveFromSameCodecsOptions()
{
$fs = (new TemporaryDirectory())->create();
$tmpFile = $fs->path('ffmpeg-concat');
touch($tmpFile);
return [
[
true,
[
'-f', 'concat',
'-safe', '0',
'-i', $tmpFile,
'-c', 'copy',
],
],
[
false,
[
'-f', 'concat',
'-safe', '0',
'-i', $tmpFile,
],
],
];
}
/**
* @dataProvider provideSaveFromDifferentCodecsOptions
*/
public function testSaveFromDifferentCodecs($commands)
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$format = $this->getFormatInterfaceMock();
$pathfile = '/target/destination';
array_push($commands, $pathfile);
$configuration = $this->getMockBuilder('Alchemy\BinaryDriver\ConfigurationInterface')->getMock();
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$driver->expects($this->once())
->method('command')
->with($commands);
$concat = new Concat([__FILE__, 'concat-2.mp4'], $driver, $ffprobe);
$this->assertSame($concat, $concat->saveFromDifferentCodecs($format, $pathfile));
}
public function provideSaveFromDifferentCodecsOptions()
{
return [
[
[
'-i', __FILE__,
'-i', 'concat-2.mp4',
'-filter_complex',
'[0:v:0] [0:a:0] [1:v:0] [1:a:0] concat=n=2:v=1:a=1 [v] [a]',
'-map', '[v]',
'-map', '[a]',
],
],
];
}
}

View file

@ -1,108 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Media;
use FFMpeg\Media\Frame;
class FrameTest extends AbstractMediaTestCase
{
public function testGetTimeCode()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$timecode = $this->getTimeCodeMock();
$frame = new Frame($this->getVideoMock(__FILE__), $driver, $ffprobe, $timecode);
$this->assertSame($timecode, $frame->getTimeCode());
}
public function testFiltersReturnFilters()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$timecode = $this->getTimeCodeMock();
$frame = new Frame($this->getVideoMock(__FILE__), $driver, $ffprobe, $timecode);
$this->assertInstanceOf('FFMpeg\Filters\Frame\FrameFilters', $frame->filters());
}
public function testAddFiltersAddsAFilter()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$timecode = $this->getTimeCodeMock();
$filters = $this->getMockBuilder('FFMpeg\Filters\FiltersCollection')
->disableOriginalConstructor()
->getMock();
$filter = $this->getMockBuilder('FFMpeg\Filters\Frame\FrameFilterInterface')->getMock();
$filters->expects($this->once())
->method('add')
->with($filter);
$frame = new Frame($this->getVideoMock(__FILE__), $driver, $ffprobe, $timecode);
$frame->setFiltersCollection($filters);
$frame->addFilter($filter);
}
/**
* @dataProvider provideSaveOptions
*/
public function testSave($accurate, $base64, $commands)
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$timecode = $this->getTimeCodeMock();
$timecode->expects($this->once())
->method('__toString')
->will($this->returnValue('timecode'));
$pathfile = '/target/destination';
if (!$base64) {
array_push($commands, $pathfile);
}
$driver->expects($this->once())
->method('command')
->with($commands);
if (!$base64) {
$frame = new Frame($this->getVideoMock(__FILE__), $driver, $ffprobe, $timecode);
$this->assertSame($frame, $frame->save($pathfile, $accurate, $base64));
} else {
$frame = new Frame($this->getVideoMock(__FILE__), $driver, $ffprobe, $timecode);
$frame->save($pathfile, $accurate, $base64);
}
}
public function provideSaveOptions()
{
return [
[false, false, [
'-y', '-ss', 'timecode',
'-i', __FILE__,
'-vframes', '1',
'-f', 'image2', ],
],
[true, false, [
'-y', '-i', __FILE__,
'-vframes', '1', '-ss', 'timecode',
'-f', 'image2', ],
],
[false, true, [
'-y', '-ss', 'timecode',
'-i', __FILE__,
'-vframes', '1',
'-f', 'image2pipe', '-', ],
],
[true, true, [
'-y', '-i', __FILE__,
'-vframes', '1', '-ss', 'timecode',
'-f', 'image2pipe', '-', ],
],
];
}
}

View file

@ -1,116 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Media;
use FFMpeg\Coordinate\Dimension;
use FFMpeg\Media\Gif;
class GifTest extends AbstractMediaTestCase
{
public function testGetTimeCode()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$timecode = $this->getTimeCodeMock();
$dimension = $this->getDimensionMock();
$gif = new Gif($this->getVideoMock(__FILE__), $driver, $ffprobe, $timecode, $dimension);
$this->assertSame($timecode, $gif->getTimeCode());
}
public function testGetDimension()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$timecode = $this->getTimeCodeMock();
$dimension = $this->getDimensionMock();
$gif = new Gif($this->getVideoMock(__FILE__), $driver, $ffprobe, $timecode, $dimension);
$this->assertSame($dimension, $gif->getDimension());
}
public function testFiltersReturnFilters()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$timecode = $this->getTimeCodeMock();
$dimension = $this->getDimensionMock();
$gif = new Gif($this->getVideoMock(__FILE__), $driver, $ffprobe, $timecode, $dimension);
$this->assertInstanceOf('FFMpeg\Filters\Gif\GifFilters', $gif->filters());
}
public function testAddFiltersAddsAFilter()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$timecode = $this->getTimeCodeMock();
$dimension = $this->getDimensionMock();
$filters = $this->getMockBuilder('FFMpeg\Filters\FiltersCollection')
->disableOriginalConstructor()
->getMock();
$filter = $this->getMockBuilder('FFMpeg\Filters\Gif\GifFilterInterface')->getMock();
$filters->expects($this->once())
->method('add')
->with($filter);
$gif = new Gif($this->getVideoMock(__FILE__), $driver, $ffprobe, $timecode, $dimension);
$gif->setFiltersCollection($filters);
$gif->addFilter($filter);
}
/**
* @dataProvider provideSaveOptions
*/
public function testSave($dimension, $duration, $commands)
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$timecode = $this->getTimeCodeMock();
$timecode->expects($this->once())
->method('__toString')
->will($this->returnValue('timecode'));
$pathfile = '/target/destination';
array_push($commands, $pathfile);
$driver->expects($this->once())
->method('command')
->with($commands);
$gif = new Gif($this->getVideoMock(__FILE__), $driver, $ffprobe, $timecode, $dimension, $duration);
$this->assertSame($gif, $gif->save($pathfile));
}
public function provideSaveOptions()
{
return [
[
new Dimension(320, 240), 3,
[
'-ss', 'timecode',
'-t', '3',
'-i', __FILE__,
'-vf',
'scale=320:-1', '-gifflags',
'+transdiff', '-y',
],
],
[
new Dimension(320, 240), null,
[
'-ss', 'timecode',
'-i', __FILE__,
'-vf',
'scale=320:-1', '-gifflags',
'+transdiff', '-y',
],
],
];
}
}

View file

@ -1,10 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Media;
use FFMpeg\Format\ProgressableInterface;
use FFMpeg\Format\VideoInterface;
abstract class Prog implements ProgressableInterface, VideoInterface
{
}

View file

@ -1,720 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Media;
use FFMpeg\Exception\RuntimeException;
use FFMpeg\Format\Video\X264;
use FFMpeg\Media\Video;
use Mockery;
class VideoTest extends AbstractStreamableTestCase
{
public function testFiltersReturnsVideoFilters()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$video = new Video(__FILE__, $driver, $ffprobe);
$this->assertInstanceOf('FFMpeg\Filters\Video\VideoFilters', $video->filters());
}
public function testAddFiltersAddsAFilter()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$filters = $this->getMockBuilder('FFMpeg\Filters\FiltersCollection')
->disableOriginalConstructor()
->getMock();
$video = new Video(__FILE__, $driver, $ffprobe);
$video->setFiltersCollection($filters);
$filter = $this->getMockBuilder('FFMpeg\Filters\Video\VideoFilterInterface')->getMock();
$filters->expects($this->once())
->method('add')
->with($filter);
$video->addFilter($filter);
}
public function testAddAudioFilterAddsAFilter()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$filters = $this->getMockBuilder('FFMpeg\Filters\FiltersCollection')
->disableOriginalConstructor()
->getMock();
$video = new Video(__FILE__, $driver, $ffprobe);
$video->setFiltersCollection($filters);
$filter = $this->getMockBuilder('FFMpeg\Filters\Audio\AudioFilterInterface')->getMock();
$filters->expects($this->once())
->method('add')
->with($filter);
$video->addFilter($filter);
}
public function testFrameShouldReturnAFrame()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$at = $this->getTimeCodeMock();
$video = new Video(__FILE__, $driver, $ffprobe);
$frame = $video->frame($at);
$this->assertInstanceOf('FFMpeg\Media\Frame', $frame);
$this->assertSame($at, $frame->getTimeCode());
$this->assertSame(__FILE__, $frame->getPathfile());
}
public function testSaveWithFailure()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$outputPathfile = '/target/file';
$format = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$format->expects($this->any())
->method('getPasses')
->will($this->returnValue(1));
$format->expects($this->any())
->method('getExtraParams')
->will($this->returnValue([]));
$configuration = $this->getMockBuilder('Alchemy\BinaryDriver\ConfigurationInterface')->getMock();
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$failure = new RuntimeException('failed to encode');
$driver->expects($this->once())
->method('command')
->will($this->throwException($failure));
$video = new Video(__FILE__, $driver, $ffprobe);
$this->expectException('\FFMpeg\Exception\RuntimeException');
$video->save($format, $outputPathfile);
}
public function testSaveAppliesFilters()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$outputPathfile = '/target/file';
$format = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$format->expects($this->any())
->method('getExtraParams')
->will($this->returnValue([]));
$format->expects($this->any())
->method('getPasses')
->will($this->returnValue(2));
$configuration = $this->getMockBuilder('Alchemy\BinaryDriver\ConfigurationInterface')->getMock();
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$video = new Video(__FILE__, $driver, $ffprobe);
$filter = $this->getMockBuilder('FFMpeg\Filters\Video\VideoFilterInterface')->getMock();
$filter->expects($this->once())
->method('apply')
->with($video, $format)
->will($this->returnValue(['extra-filter-command']));
$capturedCommands = [];
$driver->expects($this->exactly(2))
->method('command')
->with($this->isType('array'), false, $this->anything())
->will($this->returnCallback(function ($commands, $errors, $listeners) use (&$capturedCommands) {
$capturedCommands[] = $commands;
}));
$video->addFilter($filter);
$video->save($format, $outputPathfile);
foreach ($capturedCommands as $commands) {
$this->assertEquals('-y', $commands[0]);
$this->assertEquals('-i', $commands[1]);
$this->assertEquals(__FILE__, $commands[2]);
$this->assertEquals('extra-filter-command', $commands[3]);
}
}
/**
* @dataProvider provideSaveData
*/
public function testSaveShouldSave($threads, $expectedCommands, $expectedListeners, $format)
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$configuration = Mockery::mock('Alchemy\BinaryDriver\ConfigurationInterface');
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$configuration->shouldReceive('has')
->once()
->with('ffmpeg.threads')
->andReturn($threads);
$configuration->shouldReceive('get')
->once()
->with('temporary_directory')
->andReturnNull();
if ($threads) {
$configuration->shouldReceive('get')
->once()
->with('ffmpeg.threads')
->andReturn(24);
}
$capturedCommands = [];
$capturedListeners = null;
$driver->expects($this->exactly(count($expectedCommands)))
->method('command')
->with($this->isType('array'), false, $this->anything())
->will($this->returnCallback(function ($commands, $errors, $listeners) use (&$capturedCommands, &$capturedListeners) {
$capturedCommands[] = $commands;
$capturedListeners = $listeners;
}));
$outputPathfile = '/target/file';
$video = new Video(__FILE__, $driver, $ffprobe);
$video->save($format, $outputPathfile);
foreach ($capturedCommands as $passKey => $pass) {
$prefix = null;
if (count($expectedCommands) > 1) {
// look for pass commands only in multipass cases
foreach ($pass as $command) {
$prefix = null;
if (false !== strpos($command, '/pass-')) {
$prefix = $command;
break;
}
}
if (null === $prefix) {
$this->fail('Unable to find pass prefix command.');
}
}
$found = false || (null === $prefix);
foreach ($pass as $key => $command) {
if ($command === $prefix) {
$found = true;
unset($capturedCommands[$passKey][$key]);
$capturedCommands[$passKey] = array_values($capturedCommands[$passKey]);
break;
}
}
if (!$found) {
$this->fail('Unable to find pass prefix command back.');
}
}
$this->assertEquals($expectedCommands, $capturedCommands);
$this->assertEquals($expectedListeners, $capturedListeners);
}
public function provideSaveData()
{
$format = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$format->expects($this->any())
->method('getExtraParams')
->will($this->returnValue([]));
$format->expects($this->any())
->method('getKiloBitrate')
->will($this->returnValue(663));
$format->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(92));
$format->expects($this->any())
->method('getAudioChannels')
->will($this->returnValue(2));
$format->expects($this->any())
->method('getPasses')
->will($this->returnValue(2));
$format->expects($this->any())
->method('getAdditionalParameters')
->will($this->returnValue(['foo', 'bar']));
$format2 = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$format2->expects($this->any())
->method('getExtraParams')
->will($this->returnValue([]));
$format2->expects($this->any())
->method('getKiloBitrate')
->will($this->returnValue(663));
$format2->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(92));
$format2->expects($this->any())
->method('getAudioChannels')
->will($this->returnValue(2));
$format2->expects($this->any())
->method('getPasses')
->will($this->returnValue(2));
$format2->expects($this->any())
->method('getAdditionalParameters')
->will($this->returnValue(['foo', 'bar']));
$audioFormat = $this->getMockBuilder('FFMpeg\Format\AudioInterface')->getMock();
$audioFormat->expects($this->any())
->method('getExtraParams')
->will($this->returnValue([]));
$audioFormat->expects($this->any())
->method('getAudioCodec')
->will($this->returnValue('patati-patata-audio'));
$audioFormat->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(92));
$audioFormat->expects($this->any())
->method('getAudioChannels')
->will($this->returnValue(2));
$audioFormat->expects($this->any())
->method('getPasses')
->will($this->returnValue(1));
$audioVideoFormat = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$audioVideoFormat->expects($this->any())
->method('getExtraParams')
->will($this->returnValue([]));
$audioVideoFormat->expects($this->any())
->method('getVideoCodec')
->will($this->returnValue('gloubi-boulga-video'));
$audioVideoFormat->expects($this->any())
->method('getAudioCodec')
->will($this->returnValue('patati-patata-audio'));
$audioVideoFormat->expects($this->any())
->method('getKiloBitrate')
->will($this->returnValue(664));
$audioVideoFormat->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(92));
$audioVideoFormat->expects($this->any())
->method('getAudioChannels')
->will($this->returnValue(2));
$audioVideoFormat->expects($this->any())
->method('getPasses')
->will($this->returnValue(2));
$audioVideoFormat->expects($this->any())
->method('getAdditionalParameters')
->will($this->returnValue([]));
$audioVideoFormatSinglePass = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$audioVideoFormatSinglePass->expects($this->any())
->method('getExtraParams')
->will($this->returnValue([]));
$audioVideoFormatSinglePass->expects($this->any())
->method('getVideoCodec')
->will($this->returnValue('gloubi-boulga-video'));
$audioVideoFormatSinglePass->expects($this->any())
->method('getAudioCodec')
->will($this->returnValue('patati-patata-audio'));
$audioVideoFormatSinglePass->expects($this->any())
->method('getKiloBitrate')
->will($this->returnValue(664));
$audioVideoFormatSinglePass->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(92));
$audioVideoFormatSinglePass->expects($this->any())
->method('getAudioChannels')
->will($this->returnValue(2));
$audioVideoFormatSinglePass->expects($this->any())
->method('getPasses')
->will($this->returnValue(1));
$audioVideoFormatSinglePass->expects($this->any())
->method('getAdditionalParameters')
->will($this->returnValue([]));
$formatExtra = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$formatExtra->expects($this->any())
->method('getExtraParams')
->will($this->returnValue(['extra', 'param']));
$formatExtra->expects($this->any())
->method('getKiloBitrate')
->will($this->returnValue(665));
$formatExtra->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(92));
$formatExtra->expects($this->any())
->method('getAudioChannels')
->will($this->returnValue(2));
$formatExtra->expects($this->any())
->method('getPasses')
->will($this->returnValue(2));
$formatExtra->expects($this->any())
->method('getAdditionalParameters')
->will($this->returnValue([]));
$formatExtra2 = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$formatExtra2->expects($this->any())
->method('getExtraParams')
->will($this->returnValue(['extra', 'param']));
$formatExtra2->expects($this->any())
->method('getKiloBitrate')
->will($this->returnValue(665));
$formatExtra2->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(92));
$formatExtra2->expects($this->any())
->method('getAudioChannels')
->will($this->returnValue(2));
$formatExtra2->expects($this->any())
->method('getPasses')
->will($this->returnValue(2));
$formatExtra2->expects($this->any())
->method('getAdditionalParameters')
->will($this->returnValue([]));
$listeners = [$this->getMockBuilder('Alchemy\BinaryDriver\Listeners\ListenerInterface')->getMock()];
$progressableFormat = $this->getMockBuilder('Tests\FFMpeg\Unit\Media\Prog')
->disableOriginalConstructor()->getMock();
$progressableFormat->expects($this->any())
->method('getExtraParams')
->will($this->returnValue([]));
$progressableFormat->expects($this->any())
->method('createProgressListener')
->will($this->returnValue($listeners));
$progressableFormat->expects($this->any())
->method('getKiloBitrate')
->will($this->returnValue(666));
$progressableFormat->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(92));
$progressableFormat->expects($this->any())
->method('getAudioChannels')
->will($this->returnValue(2));
$progressableFormat->expects($this->any())
->method('getPasses')
->will($this->returnValue(2));
$progressableFormat2 = $this->getMockBuilder('Tests\FFMpeg\Unit\Media\Prog')
->disableOriginalConstructor()->getMock();
$progressableFormat2->expects($this->any())
->method('getExtraParams')
->will($this->returnValue([]));
$progressableFormat2->expects($this->any())
->method('createProgressListener')
->will($this->returnValue($listeners));
$progressableFormat2->expects($this->any())
->method('getKiloBitrate')
->will($this->returnValue(666));
$progressableFormat2->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(92));
$progressableFormat2->expects($this->any())
->method('getAudioChannels')
->will($this->returnValue(2));
$progressableFormat2->expects($this->any())
->method('getPasses')
->will($this->returnValue(2));
$progressableAudioFormat = $this->getMockBuilder('Tests\FFMpeg\Unit\Media\AudioProg')
->disableOriginalConstructor()->getMock();
$progressableAudioFormat->expects($this->any())
->method('getExtraParams')
->will($this->returnValue([]));
$progressableAudioFormat->expects($this->any())
->method('getAudioCodec')
->will($this->returnValue('patati-patata-audio'));
$progressableAudioFormat->expects($this->any())
->method('createProgressListener')
->will($this->returnValue($listeners));
$progressableAudioFormat->expects($this->any())
->method('getAudioKiloBitrate')
->will($this->returnValue(92));
$progressableAudioFormat->expects($this->any())
->method('getAudioChannels')
->will($this->returnValue(2));
$progressableAudioFormat->expects($this->any())
->method('getPasses')
->will($this->returnValue(1));
return [
[false, [[
'-y', '-i', __FILE__, '-b:v', '663k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-ac', 2, 'foo', 'bar', '-pass', 1, '-passlogfile',
'/target/file',
], [
'-y', '-i', __FILE__,
'-b:v', '663k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-ac', 2, 'foo', 'bar', '-pass', 2, '-passlogfile',
'/target/file',
]], null, $format],
[false, [[
'-y', '-i', __FILE__,
'-vcodec', 'gloubi-boulga-video',
'-acodec', 'patati-patata-audio', '-b:v', '664k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-ac', '2', '-pass', '1', '-passlogfile',
'/target/file',
], [
'-y', '-i', __FILE__,
'-vcodec', 'gloubi-boulga-video',
'-acodec', 'patati-patata-audio',
'-b:v', '664k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-ac', '2', '-pass', '2', '-passlogfile',
'/target/file',
]], null, $audioVideoFormat],
[false, [[
'-y', '-i', __FILE__,
'-vcodec', 'gloubi-boulga-video',
'-acodec', 'patati-patata-audio', '-b:v', '664k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-ac', '2',
'/target/file',
]], null, $audioVideoFormatSinglePass],
[false, [[
'-y', '-i', __FILE__,
'extra', 'param', '-b:v', '665k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-ac', '2', '-pass', '1', '-passlogfile',
'/target/file',
], [
'-y', '-i', __FILE__,
'extra', 'param', '-b:v', '665k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-ac', '2', '-pass', '2', '-passlogfile',
'/target/file',
]], null, $formatExtra],
[true, [[
'-y', '-i', __FILE__,
'-threads', 24, '-b:v', '663k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-ac', 2, 'foo', 'bar', '-pass', 1, '-passlogfile',
'/target/file',
], [
'-y', '-i', __FILE__,
'-threads', 24,
'-b:v', '663k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-ac', 2, 'foo', 'bar', '-pass', 2, '-passlogfile',
'/target/file',
]], null, $format2],
[true, [[
'-y', '-i', __FILE__,
'extra', 'param', '-threads', 24, '-b:v', '665k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-ac', '2', '-pass', '1', '-passlogfile',
'/target/file',
], [
'-y', '-i', __FILE__,
'extra', 'param', '-threads', 24, '-b:v', '665k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-ac', '2', '-pass', '2', '-passlogfile',
'/target/file',
]], null, $formatExtra2],
[false, [[
'-y', '-i', __FILE__, '-b:v', '666k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-ac', '2', '-pass', '1', '-passlogfile',
'/target/file',
], [
'-y', '-i', __FILE__,
'-b:v', '666k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-ac', '2', '-pass', '2', '-passlogfile',
'/target/file',
]], $listeners, $progressableFormat2],
[true, [[
'-y', '-i', __FILE__,
'-threads', 24, '-b:v', '666k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-ac', '2', '-pass', '1', '-passlogfile',
'/target/file',
], [
'-y', '-i', __FILE__,
'-threads', 24,
'-b:v', '666k',
'-refs', '6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71', '-qcomp', '0.6',
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-ac', '2', '-pass', '2', '-passlogfile',
'/target/file',
]], $listeners, $progressableFormat],
[true, [[
'-y', '-i', __FILE__,
'-threads', 24, '-acodec', 'patati-patata-audio',
'-b:a', '92k', '-ac', '2',
'/target/file',
]], null, $audioFormat],
[true, [[
'-y', '-i', __FILE__,
'-threads', 24, '-acodec', 'patati-patata-audio',
'-b:a', '92k', '-ac', '2',
'/target/file',
]], $listeners, $progressableAudioFormat],
];
}
public function testSaveShouldNotStoreCodecFiltersInTheMedia()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$configuration = Mockery::mock('Alchemy\BinaryDriver\ConfigurationInterface');
$driver->expects($this->any())
->method('getConfiguration')
->will($this->returnValue($configuration));
$configuration->shouldReceive('has')
->with('ffmpeg.threads')
->andReturn(true);
$configuration->shouldReceive('get')
->once()
->with('ffmpeg.threads')
->andReturn(24);
$configuration->shouldReceive('get')
->once()
->with('temporary_directory')
->andReturnNull();
$capturedCommands = [];
$driver->expects($this->exactly(4))
->method('command')
->with($this->isType('array'), false, $this->anything())
->will($this->returnCallback(function ($commands, $errors, $listeners) use (&$capturedCommands, &$capturedListeners) {
$capturedCommands[] = $commands;
}));
$outputPathfile = '/target/file';
$format = $this->getMockBuilder('FFMpeg\Format\VideoInterface')->getMock();
$format->expects($this->any())
->method('getExtraParams')
->will($this->returnValue(['param']));
$format->expects($this->any())
->method('getPasses')
->will($this->returnValue(2));
$video = new Video(__FILE__, $driver, $ffprobe);
$video->save($format, $outputPathfile);
$video->save($format, $outputPathfile);
$expectedPass1 = [
'-y', '-i', __FILE__, 'param', '-threads', 24, '-b:v', 'k', '-refs',
'6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71',
'-qcomp', '0.6', '-qdiff', '4', '-trellis', '1',
'-pass', '1', '-passlogfile', '/target/file',
];
$expectedPass2 = [
'-y', '-i', __FILE__, 'param', '-threads', 24, '-b:v', 'k', '-refs',
'6', '-coder', '1', '-sc_threshold', '40', '-flags', '+loop',
'-me_range', '16', '-subq', '7', '-i_qfactor', '0.71',
'-qcomp', '0.6', '-qdiff', '4', '-trellis', '1',
'-pass', '2', '-passlogfile', '/target/file',
];
$n = 1;
foreach ($capturedCommands as $capturedCommand) {
$prefix = null;
foreach ($capturedCommand as $command) {
if (false !== strpos($command, '/pass-')) {
$prefix = $command;
break;
}
}
if (null === $prefix) {
$this->fail('Unable to find pass prefix command.');
}
$found = false;
foreach ($capturedCommand as $key => $command) {
if ($command === $prefix) {
$found = true;
unset($capturedCommand[$key]);
$capturedCommand = array_values($capturedCommand);
break;
}
}
if (!$found) {
$this->fail('Unable to find pass prefix command back.');
}
if (0 === $n % 2) {
$this->assertEquals($expectedPass2, $capturedCommand);
} else {
$this->assertEquals($expectedPass1, $capturedCommand);
}
++$n;
}
}
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));
$self = $this;
$driver->expects($this->exactly(1))
->method('command')
->with($this->isType('array'), false, $this->anything())
->will($this->returnCallback(function ($commands, $errors, $listeners) use ($self) {
$self->assertTrue(!in_array('-b:v', $commands));
}));
$video = new Video(__FILE__, $driver, $ffprobe);
$video->save($format, $outputPathfile);
}
public function getClassName()
{
return 'FFMpeg\Media\Video';
}
}

View file

@ -1,70 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Media;
use FFMpeg\Media\Waveform;
class WaveformTest extends AbstractMediaTestCase
{
public function testFiltersReturnFilters()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$waveform = new Waveform($this->getAudioMock(__FILE__), $driver, $ffprobe, 640, 120);
$this->assertInstanceOf('FFMpeg\Filters\Waveform\WaveformFilters', $waveform->filters());
}
public function testAddFiltersAddsAFilter()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$filters = $this->getMockBuilder('FFMpeg\Filters\FiltersCollection')
->disableOriginalConstructor()
->getMock();
$filter = $this->getMockBuilder('FFMpeg\Filters\Waveform\WaveformFilterInterface')->getMock();
$filters->expects($this->once())
->method('add')
->with($filter);
$waveform = new Waveform($this->getAudioMock(__FILE__), $driver, $ffprobe, 640, 120);
$waveform->setFiltersCollection($filters);
$waveform->addFilter($filter);
}
/**
* @dataProvider provideSaveOptions
*/
public function testSave($commands)
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$pathfile = '/tests/files/Audio.mp3';
array_push($commands, $pathfile);
$driver->expects($this->once())
->method('command')
->with($commands);
$waveform = new Waveform($this->getAudioMock(__FILE__), $driver, $ffprobe, 640, 120, array('#FFFFFF'));
$this->assertSame($waveform, $waveform->save($pathfile));
}
public function provideSaveOptions()
{
return [
[
[
'-y', '-i', null, '-filter_complex',
'showwavespic=colors=#FFFFFF:s=640x120',
'-frames:v', '1',
],
],
];
}
}

View file

@ -1,168 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit;
use Tests\FFMpeg\BaseTestCase;
class TestCase extends BaseTestCase
{
public function getLoggerMock()
{
return $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
}
public function getCacheMock()
{
return $this->getMockBuilder('Psr\Cache\CacheItemPoolInterface')->getMock();
}
public function getTimeCodeMock()
{
return $this->getMockBuilder('FFMpeg\Coordinate\TimeCode')
->disableOriginalConstructor()
->getMock();
}
public function getDimensionMock()
{
return $this->getMockBuilder('FFMpeg\Coordinate\Dimension')
->disableOriginalConstructor()
->getMock();
}
public function getFramerateMock()
{
return $this->getMockBuilder('FFMpeg\Coordinate\Framerate')
->disableOriginalConstructor()
->getMock();
}
public function getFrameMock()
{
return $this->getMockBuilder('FFMpeg\Media\Frame')
->disableOriginalConstructor()
->getMock();
}
public function getWaveformMock()
{
return $this->getMockBuilder('FFMpeg\Media\Waveform')
->disableOriginalConstructor()
->getMock();
}
public function getFFMpegDriverMock()
{
return $this->getMockBuilder('FFMpeg\Driver\FFMpegDriver')
->disableOriginalConstructor()
->getMock();
}
public function getFFProbeDriverMock()
{
return $this->getMockBuilder('FFMpeg\Driver\FFProbeDriver')
->disableOriginalConstructor()
->getMock();
}
public function getFFProbeMock()
{
return $this->getMockBuilder('FFMpeg\FFProbe')
->disableOriginalConstructor()
->getMock();
}
public function getStreamMock()
{
return $this->getMockBuilder('FFMpeg\FFProbe\DataMapping\Stream')
->disableOriginalConstructor()
->getMock();
}
public function getFFProbeParserMock()
{
return $this->getMockBuilder('FFMpeg\FFProbe\OutputParserInterface')->getMock();
}
public function getFFProbeOptionsTesterMock()
{
return $this->getMockBuilder('FFMpeg\FFProbe\OptionsTesterInterface')->getMock();
}
public function getFFProbeMapperMock()
{
return $this->getMockBuilder('FFMpeg\FFProbe\MapperInterface')->getMock();
}
public function getFFProbeOptionsTesterMockWithOptions(array $options)
{
$tester = $this->getFFProbeOptionsTesterMock();
$tester->expects($this->any())
->method('has')
->will($this->returnCallback(function ($option) use ($options) {
return in_array($option, $options);
}));
return $tester;
}
public function getConfigurationMock()
{
return $this->getMockBuilder('Alchemy\BinaryDriver\ConfigurationInterface')->getMock();
}
public function getFormatMock()
{
return $this->getMockBuilder('FFMpeg\FFProbe\DataMapping\Format')
->disableOriginalConstructor()
->getMock();
}
public function getStreamCollectionMock()
{
return $this->getMockBuilder('FFMpeg\FFProbe\DataMapping\StreamCollection')
->disableOriginalConstructor()
->getMock();
}
protected function getAudioMock()
{
return $this->getMockBuilder('FFMpeg\Media\Audio')
->disableOriginalConstructor()
->getMock();
}
protected function getVideoMock($filename = null)
{
$video = $this->getMockBuilder('FFMpeg\Media\Video')
->disableOriginalConstructor()
->getMock();
$video->expects($this->any())
->method('getPathfile')
->will($this->returnValue($filename));
return $video;
}
public function getConcatMock()
{
return $this->getMockBuilder('FFMpeg\Media\Concat')
->disableOriginalConstructor()
->getMock();
}
public function getFormatInterfaceMock()
{
$FormatInterface = $this->getMockBuilder('FFMpeg\Format\FormatInterface')
->disableOriginalConstructor()
->getMock();
$FormatInterface->expects($this->any())
->method('getExtraParams')
->will($this->returnValue([]));
return $FormatInterface;
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,3 +0,0 @@
file './concat-1.mp4'
file 'concat-2.mp4'
#file 'concat-3.mp4'

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -1,512 +0,0 @@
Simple multimedia streams analyzer
usage: ffprobe [OPTIONS] [INPUT_FILE]
Main options:
-L show license
-h topic show help
-? topic show help
-help topic show help
--help topic show help
-version show version
-formats show available formats
-codecs show available codecs
-decoders show available decoders
-encoders show available encoders
-bsfs show available bit stream filters
-protocols show available protocols
-filters show available filters
-pix_fmts show available pixel formats
-layouts show standard channel layouts
-sample_fmts show available audio sample formats
-loglevel loglevel set libav* logging level
-v loglevel set libav* logging level
-report generate a report
-max_alloc bytes set maximum size of a single allocated block
-cpuflags flags force specific cpu flags
-f format force format
-unit show unit of the displayed values
-prefix use SI prefixes for the displayed values
-byte_binary_prefix use binary prefixes for byte units
-sexagesimal use sexagesimal format HOURS:MM:SS.MICROSECONDS for time units
-pretty prettify the format of displayed values, make it more human readable
-print_format format set the output printing format (available formats are: default, compact, csv, flat, ini, json, xml)
-of format alias for -print_format
-select_streams stream_specifier select the specified streams
-sections print sections structure and section information, and exit
-show_data show packets data
-show_error show probing error
-show_format show format/container info
-show_frames show frames info
-show_format_entry entry show a particular entry from the format/container info
-show_entries entry_list show a set of specified entries
-show_packets show packets info
-show_streams show streams info
-count_frames count the number of frames per stream
-count_packets count the number of packets per stream
-show_program_version show ffprobe version
-show_library_versions show library versions
-show_versions show program and library versions
-show_private_data show private data
-private same as show_private_data
-bitexact force bitexact output
-default generic catch all option
-i input_file read specified file
AVFormatContext AVOptions:
-avioflags <flags> ED....
direct ED.... reduce buffering
-probesize <int> .D.... set probing size (from 32 to INT_MAX)
-fflags <flags> ED....
ignidx .D.... ignore index
genpts .D.... generate pts
nofillin .D.... do not fill in missing values that can be exactly calculated
noparse .D.... disable AVParsers, this needs nofillin too
igndts .D.... ignore dts
discardcorrupt .D.... discard corrupted frames
sortdts .D.... try to interleave outputted packets by dts
keepside .D.... dont merge side data
nobuffer .D.... reduce the latency introduced by optional buffering
-seek2any <int> .D.... forces seeking to enable seek to any mode (from 0 to 1)
-analyzeduration <int> .D.... specify how many microseconds are analyzed to probe the input (from 0 to INT_MAX)
-cryptokey <binary> .D.... decryption key
-indexmem <int> .D.... max memory used for timestamp index (per stream) (from 0 to INT_MAX)
-rtbufsize <int> .D.... max memory used for buffering real-time frames (from 0 to INT_MAX)
-fdebug <flags> ED.... print specific debug info
ts ED....
-max_delay <int> ED.... maximum muxing or demuxing delay in microseconds (from -1 to INT_MAX)
-fpsprobesize <int> .D.... number of frames used to probe fps (from -1 to 2.14748e+09)
-f_err_detect <flags> .D.... set error detection flags (deprecated; use err_detect, save via avconv)
crccheck .D.... verify embedded CRCs
bitstream .D.... detect bitstream specification deviations
buffer .D.... detect improper bitstream length
explode .D.... abort decoding on minor error detection
careful .D.... consider things that violate the spec and have not been seen in the wild as errors
compliant .D.... consider all spec non compliancies as errors
aggressive .D.... consider things that a sane encoder shouldnt do as an error
-err_detect <flags> .D.... set error detection flags
crccheck .D.... verify embedded CRCs
bitstream .D.... detect bitstream specification deviations
buffer .D.... detect improper bitstream length
explode .D.... abort decoding on minor error detection
careful .D.... consider things that violate the spec and have not been seen in the wild as errors
compliant .D.... consider all spec non compliancies as errors
aggressive .D.... consider things that a sane encoder shouldnt do as an error
-use_wallclock_as_timestamps <int> .D.... use wallclock as timestamps (from 0 to 2.14748e+09)
-skip_initial_bytes <int> .D.... skip initial bytes (from 0 to 2.14748e+09)
-correct_ts_overflow <int> .D.... correct single timestamp overflows (from 0 to 1)
AVIOContext AVOptions:
URLContext AVOptions:
crypto AVOptions:
-key <binary> .D.... AES decryption key
-iv <binary> .D.... AES decryption initialization vector
ffrtmphttp AVOptions:
-ffrtmphttp_tls <int> .D.... Use a HTTPS tunneling connection (RTMPTS). (from 0 to 1)
file AVOptions:
http AVOptions:
-seekable <int> .D.... control seekability of connection (from -1 to 1)
-headers <string> ED.... set custom HTTP headers, can override built in default headers
-content_type <string> ED.... force a content type
-user-agent <string> .D.... override User-Agent header
-multiple_requests <int> ED.... use persistent connections (from 0 to 1)
-post_data <binary> ED.... set custom HTTP post data
-timeout <int> ED.... set timeout of socket I/O operations (from -1 to INT_MAX)
rtmp AVOptions:
-rtmp_app <string> ED.... Name of application to connect to on the RTMP server
-rtmp_buffer <int> ED.... Set buffer time in milliseconds. The default is 3000. (from 0 to INT_MAX)
-rtmp_conn <string> ED.... Append arbitrary AMF data to the Connect message
-rtmp_flashver <string> ED.... Version of the Flash plugin used to run the SWF player.
-rtmp_live <int> .D.... Specify that the media is a live stream. (from INT_MIN to INT_MAX)
any .D.... both
live .D.... live stream
recorded .D.... recorded stream
-rtmp_pageurl <string> .D.... URL of the web page in which the media was embedded. By default no value will be sent.
-rtmp_playpath <string> ED.... Stream identifier to play or to publish
-rtmp_subscribe <string> .D.... Name of live stream to subscribe to. Defaults to rtmp_playpath.
-rtmp_swfhash <binary> .D.... SHA256 hash of the decompressed SWF file (32 bytes).
-rtmp_swfsize <int> .D.... Size of the decompressed SWF file, required for SWFVerification. (from 0 to INT_MAX)
-rtmp_swfurl <string> ED.... URL of the SWF player. By default no value will be sent
-rtmp_swfverify <string> .D.... URL to player swf file, compute hash/size automatically.
-rtmp_tcurl <string> ED.... URL of the target stream. Defaults to proto://host[:port]/app.
-rtmp_listen <int> .D.... Listen for incoming rtmp connections (from INT_MIN to INT_MAX)
-timeout <int> .D.... Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies -rtmp_listen 1 (from INT_MIN to INT_MAX)
rtmpt AVOptions:
-rtmp_app <string> ED.... Name of application to connect to on the RTMP server
-rtmp_buffer <int> ED.... Set buffer time in milliseconds. The default is 3000. (from 0 to INT_MAX)
-rtmp_conn <string> ED.... Append arbitrary AMF data to the Connect message
-rtmp_flashver <string> ED.... Version of the Flash plugin used to run the SWF player.
-rtmp_live <int> .D.... Specify that the media is a live stream. (from INT_MIN to INT_MAX)
any .D.... both
live .D.... live stream
recorded .D.... recorded stream
-rtmp_pageurl <string> .D.... URL of the web page in which the media was embedded. By default no value will be sent.
-rtmp_playpath <string> ED.... Stream identifier to play or to publish
-rtmp_subscribe <string> .D.... Name of live stream to subscribe to. Defaults to rtmp_playpath.
-rtmp_swfhash <binary> .D.... SHA256 hash of the decompressed SWF file (32 bytes).
-rtmp_swfsize <int> .D.... Size of the decompressed SWF file, required for SWFVerification. (from 0 to INT_MAX)
-rtmp_swfurl <string> ED.... URL of the SWF player. By default no value will be sent
-rtmp_swfverify <string> .D.... URL to player swf file, compute hash/size automatically.
-rtmp_tcurl <string> ED.... URL of the target stream. Defaults to proto://host[:port]/app.
-rtmp_listen <int> .D.... Listen for incoming rtmp connections (from INT_MIN to INT_MAX)
-timeout <int> .D.... Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies -rtmp_listen 1 (from INT_MIN to INT_MAX)
srtp AVOptions:
tcp AVOptions:
-listen <int> ED.... listen on port instead of connecting (from 0 to 1)
-timeout <int> ED.... timeout of socket i/o operations (from 0 to INT_MAX)
-listen_timeout <int> ED.... connection awaiting timeout (from -1 to INT_MAX)
udp AVOptions:
-buffer_size <int> ED.... Socket buffer size in bytes (from 0 to INT_MAX)
-localport <int> ED.... Set local port to bind to (from 0 to INT_MAX)
-localaddr <string> ED.... Choose local IP address
-pkt_size <int> ED.... Set size of UDP packets (from 0 to INT_MAX)
-reuse <int> ED.... Explicitly allow or disallow reusing UDP sockets (from 0 to 1)
-connect <int> ED.... Should connect() be called on socket (from 0 to 1)
-fifo_size <int> .D.... Set the UDP receiving circular buffer size, expressed as a number of packets with size of 188 bytes (from 0 to INT_MAX)
-overrun_nonfatal <int> .D.... Survive in case of UDP receiving circular buffer overrun (from 0 to 1)
-timeout <int> .D.... In read mode: if no data arrived in more than this time interval, raise error (from 0 to INT_MAX)
Artworx Data Format demuxer AVOptions:
-linespeed <int> .D.... set simulated line speed (bytes per second) (from 1 to INT_MAX)
-video_size <string> .D.... set video size, such as 640x480 or hd720.
-framerate <string> .D.... set framerate (frames per second)
aqtdec AVOptions:
-subfps <rational> .D...S set the movie frame rate (from 0 to INT_MAX)
asf demuxer AVOptions:
-no_resync_search <int> .D.... Don't try to resynchronize by looking for a certain optional start code (from 0 to 1)
avi AVOptions:
-use_odml <int> .D.... use odml index (from -1 to 1)
Binary text demuxer AVOptions:
-linespeed <int> .D.... set simulated line speed (bytes per second) (from 1 to INT_MAX)
-video_size <string> .D.... set video size, such as 640x480 or hd720.
-framerate <string> .D.... set framerate (frames per second)
cavsvideo demuxer AVOptions:
-framerate <string> .D....
CDXL demuxer AVOptions:
-sample_rate <int> .D.... (from 1 to INT_MAX)
-framerate <string> .D....
concat demuxer AVOptions:
-safe <int> .D.... enable safe mode (from -1 to 1)
dirac demuxer AVOptions:
-framerate <string> .D....
dnxhd demuxer AVOptions:
-framerate <string> .D....
flvdec AVOptions:
-flv_metadata <int> .D.V.. Allocate streams according the onMetaData array (from 0 to 1)
g729 demuxer AVOptions:
-bit_rate <int> .D.... (from 0 to INT_MAX)
GIF demuxer AVOptions:
-min_delay <int> .D.... minimum valid delay between frames (in hundredths of second) (from 0 to 6000)
-default_delay <int> .D.... default delay between frames (in hundredths of second) (from 0 to 6000)
gsm demuxer AVOptions:
-sample_rate <int> .D.... (from 1 to 6.50753e+07)
h261 demuxer AVOptions:
-framerate <string> .D....
h263 demuxer AVOptions:
-framerate <string> .D....
h264 demuxer AVOptions:
-framerate <string> .D....
iCE Draw File demuxer AVOptions:
-linespeed <int> .D.... set simulated line speed (bytes per second) (from 1 to INT_MAX)
-video_size <string> .D.... set video size, such as 640x480 or hd720.
-framerate <string> .D.... set framerate (frames per second)
image2 demuxer AVOptions:
-framerate <string> .D.... set the video framerate
-loop <int> .D.... force loop over input file sequence (from 0 to 1)
-pattern_type <int> .D.... set pattern type (from 0 to INT_MAX)
glob_sequence .D.... select glob/sequence pattern type
glob .D.... select glob pattern type
sequence .D.... select sequence pattern type
-pixel_format <string> .D.... set video pixel format
-start_number <int> .D.... set first number in the sequence (from 0 to INT_MAX)
-start_number_range <int> .D.... set range for looking at the first sequence number (from 1 to INT_MAX)
-video_size <string> .D.... set video size
-frame_size <int> .D.... force frame size in bytes (from 0 to INT_MAX)
image2pipe demuxer AVOptions:
-framerate <string> .D.... set the video framerate
-loop <int> .D.... force loop over input file sequence (from 0 to 1)
-pattern_type <int> .D.... set pattern type (from 0 to INT_MAX)
glob_sequence .D.... select glob/sequence pattern type
glob .D.... select glob pattern type
sequence .D.... select sequence pattern type
-pixel_format <string> .D.... set video pixel format
-start_number <int> .D.... set first number in the sequence (from 0 to INT_MAX)
-start_number_range <int> .D.... set range for looking at the first sequence number (from 1 to INT_MAX)
-video_size <string> .D.... set video size
-frame_size <int> .D.... force frame size in bytes (from 0 to INT_MAX)
ingenient demuxer AVOptions:
-framerate <string> .D....
m4v demuxer AVOptions:
-framerate <string> .D....
mjpeg demuxer AVOptions:
-framerate <string> .D....
mov,mp4,m4a,3gp,3g2,mj2 AVOptions:
-use_absolute_path <int> .D.V.. allow using absolute path when opening alias, this is a possible security issue (from 0 to 1)
-ignore_editlist <int> .D.V.. (from 0 to 1)
mpegtsraw demuxer AVOptions:
-compute_pcr <int> .D.... Compute exact PCR for each transport stream packet. (from 0 to 1)
mpegvideo demuxer AVOptions:
-framerate <string> .D....
alaw demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
mulaw demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
f64be demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
f64le demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
f32be demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
f32le demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
s32be demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
s32le demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
s24be demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
s24le demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
s16be demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
s16le demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
s8 demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
u32be demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
u32le demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
u24be demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
u24le demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
u16be demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
u16le demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
u8 demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-channels <int> .D.... (from 0 to INT_MAX)
rawvideo demuxer AVOptions:
-video_size <string> .D.... set frame size
-pixel_format <string> .D.... set pixel format
-framerate <string> .D.... set frame rate
RTP demuxer AVOptions:
-rtp_flags <flags> .D.... RTP flags
filter_src .D.... Only receive packets from the negotiated peer IP
listen .D.... Wait for incoming connections
-reorder_queue_size <int> .D.... Number of packets to buffer for handling of reordered packets (from -1 to INT_MAX)
RTSP demuxer AVOptions:
-initial_pause <int> .D.... Don't start playing the stream immediately (from 0 to 1)
-rtsp_transport <flags> ED.... RTSP transport protocols
udp ED.... UDP
tcp ED.... TCP
udp_multicast .D.... UDP multicast
http .D.... HTTP tunneling
-rtsp_flags <flags> .D.... RTSP flags
filter_src .D.... Only receive packets from the negotiated peer IP
listen .D.... Wait for incoming connections
-allowed_media_types <flags> .D.... Media types to accept from the server
video .D.... Video
audio .D.... Audio
data .D.... Data
-min_port <int> ED.... Minimum local UDP port (from 0 to 65535)
-max_port <int> ED.... Maximum local UDP port (from 0 to 65535)
-timeout <int> .D.... Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies flag listen (from INT_MIN to INT_MAX)
-reorder_queue_size <int> .D.... Number of packets to buffer for handling of reordered packets (from -1 to INT_MAX)
sbg_demuxer AVOptions:
-sample_rate <int> .D.... (from 0 to INT_MAX)
-frame_size <int> .D.... (from 0 to INT_MAX)
-max_file_size <int> .D.... (from 0 to INT_MAX)
SDP demuxer AVOptions:
-sdp_flags <flags> .D.... SDP flags
filter_src .D.... Only receive packets from the negotiated peer IP
listen .D.... Wait for incoming connections
custom_io .D.... Use custom IO
-allowed_media_types <flags> .D.... Media types to accept from the server
video .D.... Video
audio .D.... Audio
data .D.... Data
-reorder_queue_size <int> .D.... Number of packets to buffer for handling of reordered packets (from -1 to INT_MAX)
tedcaptions_demuxer AVOptions:
-start_time <int64> .D...S set the start time (offset) of the subtitles, in ms (from I64_MIN to I64_MAX)
TTY demuxer AVOptions:
-chars_per_frame <int> .D.... (from 1 to INT_MAX)
-video_size <string> .D.... A string describing frame size, such as 640x480 or hd720.
-framerate <string> .D....
vc1 demuxer AVOptions:
-framerate <string> .D....
WAV demuxer AVOptions:
-ignore_length <int> .D.... Ignore length (from 0 to 1)
eXtended BINary text (XBIN) demuxer AVOptions:
-linespeed <int> .D.... set simulated line speed (bytes per second) (from 1 to INT_MAX)
-video_size <string> .D.... set video size, such as 640x480 or hd720.
-framerate <string> .D.... set framerate (frames per second)
lavfi indev AVOptions:
-graph <string> .D.... set libavfilter graph
-graph_file <string> .D.... set libavfilter graph filename
-dumpgraph <string> .D.... dump graph to stderr
AIFF muxer AVOptions:
AST muxer AVOptions:
f4v muxer AVOptions:
GIF muxer AVOptions:
hls muxer AVOptions:
image2 muxer AVOptions:
ipod muxer AVOptions:
ismv muxer AVOptions:
LATM/LOAS muxer AVOptions:
mov muxer AVOptions:
MP3 muxer AVOptions:
mp4 muxer AVOptions:
mpeg muxer AVOptions:
vcd muxer AVOptions:
dvd muxer AVOptions:
svcd muxer AVOptions:
vob muxer AVOptions:
MPEGTS muxer AVOptions:
Ogg muxer AVOptions:
psp muxer AVOptions:
RTP muxer AVOptions:
RTSP muxer AVOptions:
-initial_pause <int> .D.... Don't start playing the stream immediately (from 0 to 1)
-rtsp_transport <flags> ED.... RTSP transport protocols
udp ED.... UDP
tcp ED.... TCP
udp_multicast .D.... UDP multicast
http .D.... HTTP tunneling
-rtsp_flags <flags> .D.... RTSP flags
filter_src .D.... Only receive packets from the negotiated peer IP
listen .D.... Wait for incoming connections
-allowed_media_types <flags> .D.... Media types to accept from the server
video .D.... Video
audio .D.... Audio
data .D.... Data
-min_port <int> ED.... Minimum local UDP port (from 0 to 65535)
-max_port <int> ED.... Maximum local UDP port (from 0 to 65535)
-timeout <int> .D.... Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies flag listen (from INT_MIN to INT_MAX)
-reorder_queue_size <int> .D.... Number of packets to buffer for handling of reordered packets (from -1 to INT_MAX)
segment muxer AVOptions:
stream_segment muxer AVOptions:
smooth streaming muxer AVOptions:
spdif AVOptions:
tg2 muxer AVOptions:
tgp muxer AVOptions:
WAV muxer AVOptions:
caca_outdev AVOptions:

View file

@ -1,20 +0,0 @@
{
"format": {
"filename": "Interview5mm4500.mp4",
"nb_streams": 2,
"format_name": "mov,mp4,m4a,3gp,3g2,mj2",
"format_long_name": "QuickTime / MOV",
"start_time": "0.000000",
"duration": "300.011000",
"size": "173833712",
"bit_rate": "4635395",
"tags": {
"major_brand": "isom",
"minor_version": "512",
"compatible_brands": "isomiso2avc1mp41",
"creation_time": "1970-01-01 00:00:00",
"title": "5mm 4500.mp4",
"encoder": "Lavf52.108.0"
}
}
}

View file

@ -1,16 +0,0 @@
[FORMAT]
filename=Interview5mm4500.mp4
nb_streams=2
format_name=mov,mp4,m4a,3gp,3g2,mj2
format_long_name=QuickTime / MOV
start_time=0.000000
duration=300.011000
size=173833712
bit_rate=4635395
TAG:major_brand=isom
TAG:minor_version=512
TAG:compatible_brands=isomiso2avc1mp41
TAG:creation_time=1970-01-01 00:00:00
TAG:title=5mm 4500.mp4
TAG:encoder=Lavf52.108.0
[/FORMAT]

View file

@ -1,88 +0,0 @@
{
"streams": [
{
"index": 0,
"codec_name": "h264",
"codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
"profile": "High",
"codec_type": "video",
"codec_time_base": "1/100",
"codec_tag_string": "avc1",
"codec_tag": "0x31637661",
"width": 960,
"height": 720,
"has_b_frames": 2,
"sample_aspect_ratio": "1:1",
"display_aspect_ratio": "4:3",
"pix_fmt": "yuv420p",
"level": 32,
"r_frame_rate": "50/1",
"avg_frame_rate": "50/1",
"time_base": "1/50000",
"start_pts": 0,
"start_time": "0.000000",
"duration_ts": 15000000,
"duration": "300.000000",
"bit_rate": "4499198",
"nb_frames": "15000",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0
},
"tags": {
"creation_time": "1970-01-01 00:00:00",
"language": "und",
"handler_name": "VideoHandler"
}
},
{
"index": 1,
"codec_name": "aac",
"codec_long_name": "AAC (Advanced Audio Coding)",
"codec_type": "audio",
"codec_time_base": "1/48000",
"codec_tag_string": "mp4a",
"codec_tag": "0x6134706d",
"sample_fmt": "fltp",
"sample_rate": "48000",
"channels": 2,
"bits_per_sample": 0,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/48000",
"start_pts": 0,
"start_time": "0.000000",
"duration_ts": 14400512,
"duration": "300.010667",
"bit_rate": "127973",
"nb_frames": "14063",
"disposition": {
"default": 0,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0
},
"tags": {
"creation_time": "1970-01-01 00:00:00",
"language": "und",
"handler_name": "SoundHandler"
}
}
]
}

View file

@ -1,84 +0,0 @@
[STREAM]
index=0
codec_name=h264
codec_long_name=H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10
profile=High
codec_type=video
codec_time_base=1/100
codec_tag_string=avc1
codec_tag=0x31637661
width=960
height=720
has_b_frames=2
sample_aspect_ratio=1:1
display_aspect_ratio=4:3
pix_fmt=yuv420p
level=32
timecode=N/A
id=N/A
r_frame_rate=50/1
avg_frame_rate=50/1
time_base=1/50000
start_pts=0
start_time=0.000000
duration_ts=15000000
duration=300.000000
bit_rate=4499198
nb_frames=15000
nb_read_frames=N/A
nb_read_packets=N/A
DISPOSITION:default=0
DISPOSITION:dub=0
DISPOSITION:original=0
DISPOSITION:comment=0
DISPOSITION:lyrics=0
DISPOSITION:karaoke=0
DISPOSITION:forced=0
DISPOSITION:hearing_impaired=0
DISPOSITION:visual_impaired=0
DISPOSITION:clean_effects=0
DISPOSITION:attached_pic=0
TAG:creation_time=1970-01-01 00:00:00
TAG:language=und
TAG:handler_name=VideoHandler
[/STREAM]
[STREAM]
index=1
codec_name=aac
codec_long_name=AAC (Advanced Audio Coding)
profile=unknown
codec_type=audio
codec_time_base=1/48000
codec_tag_string=mp4a
codec_tag=0x6134706d
sample_fmt=fltp
sample_rate=48000
channels=2
bits_per_sample=0
id=N/A
r_frame_rate=0/0
avg_frame_rate=0/0
time_base=1/48000
start_pts=0
start_time=0.000000
duration_ts=14400512
duration=300.010667
bit_rate=127973
nb_frames=14063
nb_read_frames=N/A
nb_read_packets=N/A
DISPOSITION:default=0
DISPOSITION:dub=0
DISPOSITION:original=0
DISPOSITION:comment=0
DISPOSITION:lyrics=0
DISPOSITION:karaoke=0
DISPOSITION:forced=0
DISPOSITION:hearing_impaired=0
DISPOSITION:visual_impaired=0
DISPOSITION:clean_effects=0
DISPOSITION:attached_pic=0
TAG:creation_time=1970-01-01 00:00:00
TAG:language=und
TAG:handler_name=SoundHandler
[/STREAM]

View file

@ -1,30 +0,0 @@
<?php
namespace Tests\FFMpeg\Functional;
use FFMpeg\FFMpeg;
use FFMpeg\FFProbe;
use FFMpeg\Media\Spectrum;
class AudioImagingTest extends FunctionalTestCase
{
/**
* Path prefix to avoid conflicts with another tests.
*/
const OUTPUT_PATH_PREFIX = 'output/audio_';
public function testgenerateSpectrumImage()
{
$ffmpeg = FFMpeg::create();
$ffprobe = FFProbe::create();
$audio = $ffmpeg->open(realpath(__DIR__ . '/../files/Audio.mp3'));
$spectrum = new Spectrum($audio, $ffmpeg->getFFMpegDriver(), $ffprobe, 1024, 1024);
$spectrum->setLegend(false)
->setOrientation('horizontal')
->setColor('fiery');
$output = __DIR__ . '/' . self::OUTPUT_PATH_PREFIX . 'spectrum.png';
$spectrum->save($output);
$this->assertFileExists($output);
unlink($output);
}
}

1
tests/Pest.php Normal file
View file

@ -0,0 +1 @@
<?php

View file

@ -1,42 +0,0 @@
<?php
namespace Tests\FFMpeg\Unit\Media;
use FFMpeg\Media\Spectrum;
class SpectrumTest extends AbstractMediaTestCase
{
/**
* @dataProvider provideSaveOptions
*/
public function testSave($commands)
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$pathfile = '/tests/files/Audio.mp3';
array_push($commands, $pathfile);
$driver->expects($this->once())
->method('command')
->with($commands);
$spectrum = new Spectrum($this->getAudioMock(), $driver, $ffprobe, 640, 120);
$this->assertSame($spectrum, $spectrum->save($pathfile));
}
public function provideSaveOptions()
{
return array(
array(
array(
'-y', '-i', NULL, '-filter_complex',
'showspectrumpic=s=640x120',
'-frames:v', '1',
),
),
);
}
}

View file

@ -1,9 +0,0 @@
<?php
$file = __DIR__ . '/../vendor/autoload.php';
if (!file_exists($file)) {
throw new RuntimeException('Install dependencies to run test suite.');
}
$autoload = require_once $file;