🔥 Replace all other files with 💀
This commit is contained in:
parent
001f55939b
commit
d187e02d24
124 changed files with 345 additions and 8227 deletions
|
|
@ -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';
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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'];
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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
5
tests/ExampleTest.php
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
|
||||
it('can test', function () {
|
||||
expect(true)->toBeTrue();
|
||||
});
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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')));
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -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']);
|
||||
}
|
||||
}
|
||||
|
|
@ -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']);
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
{
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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', ],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -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']))],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -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()],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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'));
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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']],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -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]']],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\FFMpeg\Unit\Media;
|
||||
|
||||
use Tests\FFMpeg\Unit\TestCase;
|
||||
|
||||
abstract class AbstractMediaTestCase extends TestCase
|
||||
{
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\FFMpeg\Unit\Media;
|
||||
|
||||
use FFMpeg\Format\AudioInterface;
|
||||
use FFMpeg\Format\ProgressableInterface;
|
||||
|
||||
abstract class AudioProg implements ProgressableInterface, AudioInterface
|
||||
{
|
||||
}
|
||||
|
|
@ -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';
|
||||
}
|
||||
}
|
||||
|
|
@ -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', ],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -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]',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -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', '-', ],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -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',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\FFMpeg\Unit\Media;
|
||||
|
||||
use FFMpeg\Format\ProgressableInterface;
|
||||
use FFMpeg\Format\VideoInterface;
|
||||
|
||||
abstract class Prog implements ProgressableInterface, VideoInterface
|
||||
{
|
||||
}
|
||||
|
|
@ -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';
|
||||
}
|
||||
}
|
||||
|
|
@ -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',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -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.
Binary file not shown.
Binary file not shown.
|
|
@ -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 |
|
|
@ -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:
|
||||
|
||||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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]
|
||||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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]
|
||||
|
|
@ -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
1
tests/Pest.php
Normal file
|
|
@ -0,0 +1 @@
|
|||
<?php
|
||||
|
|
@ -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',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
Loading…
Add table
Add a link
Reference in a new issue