Add support for video to audio transcoding

This commit is contained in:
Romain Neutron 2013-10-10 15:09:10 +02:00
commit d3e97c974e
11 changed files with 127 additions and 59 deletions

View file

@ -3,6 +3,9 @@ CHANGELOG
* 0.4.0 (xx-xx-xxxx)
* Add support for video to audio transcoding
* BC Break : Add FormatInterface::getPasses and FormatInterface::getExtraParams
* 0.3.5 (xx-xx-2013)
* Add vorbis audio format (@jacobbudin).

View file

@ -103,4 +103,12 @@ abstract class DefaultAudio extends EventEmitter implements AudioInterface, Prog
return array($listener);
}
/**
* {@inheritDoc}
*/
public function getPasses()
{
return 1;
}
}

View file

@ -19,13 +19,6 @@ interface AudioInterface extends FormatInterface
*/
public function getAudioKiloBitrate();
/**
* Returns an array of extra parameters to add to ffmpeg commandline.
*
* @return array()
*/
public function getExtraParams();
/**
* Returns the audio codec.
*

View file

@ -12,4 +12,17 @@ namespace FFMpeg\Format;
interface FormatInterface
{
/**
* Returns the number of passes.
*
* @return string
*/
public function getPasses();
/**
* Returns an array of extra parameters to add to ffmpeg commandline.
*
* @return array()
*/
public function getExtraParams();
}

View file

@ -86,14 +86,6 @@ abstract class DefaultVideo extends DefaultAudio implements VideoInterface
return $this;
}
/**
* {@inheritDoc}
*/
public function getPasses()
{
return 1;
}
/**
* @return integer
*/

View file

@ -20,13 +20,6 @@ interface VideoInterface extends AudioInterface
*/
public function getKiloBitrate();
/**
* Returns the number of passes.
*
* @return string
*/
public function getPasses();
/**
* Returns the modulus used by the Resizable video.
*

View file

@ -20,6 +20,8 @@ use FFMpeg\Filters\Video\VideoFilters;
use FFMpeg\Filters\FilterInterface;
use FFMpeg\Format\FormatInterface;
use FFMpeg\Format\ProgressableInterface;
use FFMpeg\Format\AudioInterface;
use FFMpeg\Format\VideoInterface;
use FFMpeg\Media\Frame;
use Neutron\TemporaryFilesystem\Manager as FsManager;
@ -67,43 +69,51 @@ class Video extends Audio
if ($this->driver->getConfiguration()->has('ffmpeg.threads')) {
$filters->add(new SimpleFilter(array('-threads', $this->driver->getConfiguration()->get('ffmpeg.threads'))));
}
if (null !== $format->getVideoCodec()) {
$filters->add(new SimpleFilter(array('-vcodec', $format->getVideoCodec())));
if ($format instanceOf VideoInterface) {
if (null !== $format->getVideoCodec()) {
$filters->add(new SimpleFilter(array('-vcodec', $format->getVideoCodec())));
}
}
if (null !== $format->getAudioCodec()) {
$filters->add(new SimpleFilter(array('-acodec', $format->getAudioCodec())));
if ($format instanceOf AudioInterface) {
if (null !== $format->getAudioCodec()) {
$filters->add(new SimpleFilter(array('-acodec', $format->getAudioCodec())));
}
}
foreach ($filters as $filter) {
$commands = array_merge($commands, $filter->apply($this, $format));
}
$commands[] = '-b:v';
$commands[] = $format->getKiloBitrate() . 'k';
$commands[] = '-refs';
$commands[] = '6';
$commands[] = '-coder';
$commands[] = '1';
$commands[] = '-sc_threshold';
$commands[] = '40';
$commands[] = '-flags';
$commands[] = '+loop';
$commands[] = '-me_range';
$commands[] = '16';
$commands[] = '-subq';
$commands[] = '7';
$commands[] = '-i_qfactor';
$commands[] = '0.71';
$commands[] = '-qcomp';
$commands[] = '0.6';
$commands[] = '-qdiff';
$commands[] = '4';
$commands[] = '-trellis';
$commands[] = '1';
if ($format instanceOf VideoInterface) {
$commands[] = '-b:v';
$commands[] = $format->getKiloBitrate() . 'k';
$commands[] = '-refs';
$commands[] = '6';
$commands[] = '-coder';
$commands[] = '1';
$commands[] = '-sc_threshold';
$commands[] = '40';
$commands[] = '-flags';
$commands[] = '+loop';
$commands[] = '-me_range';
$commands[] = '16';
$commands[] = '-subq';
$commands[] = '7';
$commands[] = '-i_qfactor';
$commands[] = '0.71';
$commands[] = '-qcomp';
$commands[] = '0.6';
$commands[] = '-qdiff';
$commands[] = '4';
$commands[] = '-trellis';
$commands[] = '1';
}
if (null !== $format->getAudioKiloBitrate()) {
$commands[] = '-b:a';
$commands[] = $format->getAudioKiloBitrate() . 'k';
if ($format instanceOf AudioInterface) {
if (null !== $format->getAudioKiloBitrate()) {
$commands[] = '-b:a';
$commands[] = $format->getAudioKiloBitrate() . 'k';
}
}
$fs = FsManager::create();

View file

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

View file

@ -333,7 +333,3 @@ class AudioTest extends AbstractStreamableTestCase
return 'FFMpeg\Media\Audio';
}
}
abstract class AudioProg implements ProgressableInterface, AudioInterface
{
}

View file

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

View file

@ -259,6 +259,20 @@ class VideoTest extends AbstractStreamableTestCase
->method('getPasses')
->will($this->returnValue(2));
$audioFormat = $this->getMock('FFMpeg\Format\AudioInterface');
$audioFormat->expects($this->any())
->method('getExtraParams')
->will($this->returnValue(array()));
$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('getPasses')
->will($this->returnValue(1));
$audioVideoFormat = $this->getMock('FFMpeg\Format\VideoInterface');
$audioVideoFormat->expects($this->any())
->method('getExtraParams')
@ -333,6 +347,24 @@ class VideoTest extends AbstractStreamableTestCase
->method('getPasses')
->will($this->returnValue(2));
$progressableAudioFormat = $this->getMockBuilder('FFMpeg\Tests\Media\AudioProg')
->disableOriginalConstructor()->getMock();
$progressableAudioFormat->expects($this->any())
->method('getExtraParams')
->will($this->returnValue(array()));
$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('getPasses')
->will($this->returnValue(1));
return array(
array(false, array(array(
'-y', '-i', __FILE__, '-b:v', '663k',
@ -451,6 +483,18 @@ class VideoTest extends AbstractStreamableTestCase
'-qdiff', '4', '-trellis', '1', '-b:a', '92k', '-pass', '2', '-passlogfile',
'/target/file',
)), $listeners, $progressableFormat),
array(true, array(array(
'-y', '-i', __FILE__,
'-threads', 24, '-acodec', 'patati-patata-audio',
'-b:a', '92k',
'/target/file',
)), null, $audioFormat),
array(true, array(array(
'-y', '-i', __FILE__,
'-threads', 24, '-acodec', 'patati-patata-audio',
'-b:a', '92k',
'/target/file',
)), $listeners, $progressableAudioFormat),
);
}
@ -555,7 +599,3 @@ class VideoTest extends AbstractStreamableTestCase
return 'FFMpeg\Media\Video';
}
}
abstract class Prog implements ProgressableInterface, VideoInterface
{
}