From 5a33a99cb08ab6b5831fdf72e6796a997d153221 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Fri, 25 May 2012 16:21:16 +0200 Subject: [PATCH] Logger is now required --- src/FFMpeg/AdapterInterface.php | 12 ++- src/FFMpeg/Binary.php | 37 +++++----- ...ption.php => InvalidArgumentException.php} | 2 +- src/FFMpeg/FFMpeg.php | 74 ++++++++++++------- src/FFMpeg/FFProbe.php | 32 +++++--- src/FFMpeg/Format/AudioFormat.php | 15 ++++ src/FFMpeg/Format/DefaultAudioFormat.php | 26 ++++--- src/FFMpeg/Format/DefaultVideoFormat.php | 50 +++++++------ src/FFMpeg/Format/VideoFormat.php | 30 ++++++++ tests/src/FFMpeg/BinaryTest.php | 17 ++++- tests/src/FFMpeg/FFMpegTest.php | 11 ++- tests/src/FFMpeg/FFProbeTest.php | 9 ++- 12 files changed, 217 insertions(+), 98 deletions(-) rename src/FFMpeg/Exception/{InvalidFileArgumentException.php => InvalidArgumentException.php} (73%) diff --git a/src/FFMpeg/AdapterInterface.php b/src/FFMpeg/AdapterInterface.php index bbd542a..84fc007 100644 --- a/src/FFMpeg/AdapterInterface.php +++ b/src/FFMpeg/AdapterInterface.php @@ -11,8 +11,18 @@ namespace FFMpeg; +use Monolog\Logger; + +/** + * FFMpeg Adapter interface + * + * @author Romain Neutron imprec@gmail.com + */ interface AdapterInterface { - public static function load(\Monolog\Logger $logger); + /** + * Loads the adapter + */ + public static function load(Logger $logger); } diff --git a/src/FFMpeg/Binary.php b/src/FFMpeg/Binary.php index 1038836..c6221a5 100644 --- a/src/FFMpeg/Binary.php +++ b/src/FFMpeg/Binary.php @@ -11,7 +11,9 @@ namespace FFMpeg; -use \Symfony\Component\Process\ExecutableFinder; +use FFMpeg\Exception\BinaryNotFoundException; +use Monolog\Logger; +use Symfony\Component\Process\ExecutableFinder; /** * Binary abstract class @@ -24,7 +26,7 @@ abstract class Binary implements AdapterInterface /** * - * @var \Monolog\Logger + * @var Logger */ protected $logger; @@ -32,28 +34,31 @@ abstract class Binary implements AdapterInterface * Binary constructor * * @param type $binary The path file to the binary - * @param \Monolog\Logger $logger A logger + * @param Logger $logger A logger */ - public function __construct($binary, \Monolog\Logger $logger) + public function __construct($binary, Logger $logger) { $this->binary = $binary; - - if ( ! $logger) { - $logger = new \Monolog\Logger('default'); - $logger->pushHandler(new \Monolog\Handler\NullHandler()); - } - $this->logger = $logger; } /** - * Load the static binary + * Destructor + */ + public function __destruct() + { + $this->binary = $binary = $this->logger = null; + } + + /** + * {@inheritdoc} + * + * @param Logger $logger A logger + * @return Binary The binary * - * @param \Monolog\Logger $logger A logger - * @return \FFMpeg\Binary The binary * @throws Exception\BinaryNotFoundException */ - public static function load(\Monolog\Logger $logger) + public static function load(Logger $logger) { $finder = new ExecutableFinder(); $binary = null; @@ -65,7 +70,7 @@ abstract class Binary implements AdapterInterface } if (null === $binary) { - throw new Exception\BinaryNotFoundException('Binary not found'); + throw new BinaryNotFoundException('Binary not found'); } return new static($binary, $logger); @@ -73,8 +78,6 @@ abstract class Binary implements AdapterInterface /** * Return the binary name - * - * @throws \Exception */ protected static function getBinaryName() { diff --git a/src/FFMpeg/Exception/InvalidFileArgumentException.php b/src/FFMpeg/Exception/InvalidArgumentException.php similarity index 73% rename from src/FFMpeg/Exception/InvalidFileArgumentException.php rename to src/FFMpeg/Exception/InvalidArgumentException.php index f6dd0a1..0cd2f91 100644 --- a/src/FFMpeg/Exception/InvalidFileArgumentException.php +++ b/src/FFMpeg/Exception/InvalidArgumentException.php @@ -11,7 +11,7 @@ namespace FFMpeg\Exception; -class InvalidFileArgumentException extends \InvalidArgumentException implements Exception +class InvalidArgumentException extends \InvalidArgumentException implements Exception { } diff --git a/src/FFMpeg/FFMpeg.php b/src/FFMpeg/FFMpeg.php index 2649a9a..006b743 100644 --- a/src/FFMpeg/FFMpeg.php +++ b/src/FFMpeg/FFMpeg.php @@ -11,7 +11,12 @@ namespace FFMpeg; -use \Symfony\Component\Process\Process; +use FFMpeg\Exception\InvalidArgumentException; +use FFMpeg\Exception\LogicException; +use FFMpeg\Exception\RuntimeException; +use FFMpeg\Format\AudioFormat; +use FFMpeg\Format\VideoFormat; +use Symfony\Component\Process\Process; /** * FFMpeg driver @@ -25,16 +30,16 @@ class FFMpeg extends Binary /** * Opens a file in order to be processed * - * @param string $pathfile + * @param string $pathfile A pathfile * @return \FFMpeg\FFMpeg - * @throws Exception\InvalidFileArgumentException + * @throws InvalidArgumentException */ public function open($pathfile) { if ( ! file_exists($pathfile)) { - $this->logger->addError(sprintf('Request to open %s failed', $pathfile)); + $this->logger->addError(sprintf('FFmpeg failed to open %s', $pathfile)); - throw new Exception\InvalidFileArgumentException(sprintf('File %s does not exists', $pathfile)); + throw new InvalidArgumentException(sprintf('File %s does not exists', $pathfile)); } $this->logger->addInfo(sprintf('FFmpeg opens %s', $pathfile)); @@ -51,6 +56,8 @@ class FFMpeg extends Binary */ public function close() { + $this->logger->addInfo(sprintf('FFmpeg closes %s', $this->pathfile)); + $this->pathfile = null; return $this; @@ -61,13 +68,13 @@ class FFMpeg extends Binary * @param integer $time The time in second where to take the snapshot * @param string $output The pathfile where to write * @return \FFMpeg\FFMpeg - * @throws Exception\RuntimeException - * @throws Exception\LogicException + * @throws RuntimeException + * @throws LogicException */ public function extractImage($time, $output) { if ( ! $this->pathfile) { - throw new Exception\LogicException('No file open'); + throw new LogicException('No file open'); } $cmd = $this->binary @@ -75,7 +82,7 @@ class FFMpeg extends Binary . ' -vframes 1 -ss ' . $time . ' -f image2 ' . escapeshellarg($output); - $this->logger->addInfo(sprintf('Executing command %s', $cmd)); + $this->logger->addInfo(sprintf('FFmpeg executes command %s', $cmd)); $process = new Process($cmd); @@ -86,14 +93,14 @@ class FFMpeg extends Binary } if ( ! $process->isSuccessful()) { - $this->logger->addError(sprintf('Command failed :: %s', $process->getErrorOutput())); + $this->logger->addError(sprintf('FFmpeg command failed : %s', $process->getErrorOutput())); $this->cleanupTemporaryFile($output); - throw new Exception\RuntimeException('Failed to extract image'); + throw new RuntimeException('Failed to extract image'); } - $this->logger->addInfo('Command run with success'); + $this->logger->addInfo(sprintf('FFmpeg command successful')); return $this; } @@ -101,27 +108,27 @@ class FFMpeg extends Binary /** * Encode the file to the specified format * - * @param Format\AudioFormat $format The output format + * @param AudioFormat $format The output format * @param string $outputPathfile The pathfile where to write * @param integer $threads The number of threads to use * @return \FFMpeg\FFMpeg - * @throws Exception\RuntimeException - * @throws Exception\LogicException + * @throws RuntimeException + * @throws LogicException */ - public function encode(Format\AudioFormat $format, $outputPathfile, $threads = 1) + public function encode(AudioFormat $format, $outputPathfile, $threads = 1) { if ( ! $this->pathfile) { - throw new Exception\LogicException('No file open'); + throw new LogicException('No file open'); } $threads = max(min($threads, 64), 1); switch (true) { - case $format instanceof Format\VideoFormat: + case $format instanceof VideoFormat: $this->encodeVideo($format, $outputPathfile, $threads); break; default: - case $format instanceof Format\AudioFormat: + case $format instanceof AudioFormat: $this->encodeAudio($format, $outputPathfile, $threads); break; } @@ -132,13 +139,13 @@ class FFMpeg extends Binary /** * Encode to audio * - * @param Format\AudioFormat $format The output format + * @param AudioFormat $format The output format * @param string $outputPathfile The pathfile where to write * @param integer $threads The number of threads to use * @return \FFMpeg\FFMpeg - * @throws Exception\RuntimeException + * @throws RuntimeException */ - protected function encodeAudio(Format\AudioFormat $format, $outputPathfile, $threads) + protected function encodeAudio(AudioFormat $format, $outputPathfile, $threads) { $cmd = $this->binary . ' -y -i ' @@ -152,6 +159,8 @@ class FFMpeg extends Binary $process = new Process($cmd); + $this->logger->addInfo(sprintf('FFmpeg executes command %s', $cmd)); + try { $process->run(); } catch (\RuntimeException $e) { @@ -159,22 +168,25 @@ class FFMpeg extends Binary } if ( ! $process->isSuccessful()) { - throw new Exception\RuntimeException(sprintf('Encoding failed : %s', $process->getErrorOutput())); + $this->logger->addInfo(sprintf('FFmpeg command failed')); + throw new RuntimeException(sprintf('Encoding failed : %s', $process->getErrorOutput())); } + $this->logger->addInfo(sprintf('FFmpeg command successful')); + return $this; } /** * Encode to video * - * @param Format\VideoFormat $format The output format + * @param VideoFormat $format The output format * @param string $outputPathfile The pathfile where to write * @param integer $threads The number of threads to use * @return \FFMpeg\FFMpeg - * @throws Exception\RuntimeException + * @throws RuntimeException */ - protected function encodeVideo(Format\VideoFormat $format, $outputPathfile, $threads) + protected function encodeVideo(VideoFormat $format, $outputPathfile, $threads) { $cmd_part1 = $this->binary . ' -y -i ' @@ -205,6 +217,9 @@ class FFMpeg extends Binary $process = null; foreach ($passes as $pass) { + + $this->logger->addInfo(sprintf('FFmpeg executes command %s', $pass)); + $process = new Process($pass); try { @@ -219,9 +234,12 @@ class FFMpeg extends Binary $this->cleanupTemporaryFile(getcwd() . '/ffmpeg2pass-0.log.mbtree'); if ( ! $process->isSuccessful()) { - throw new Exception\RuntimeException(sprintf('Encoding failed : %s', $process->getErrorOutput())); + $this->logger->addInfo(sprintf('FFmpeg command failed')); + throw new RuntimeException(sprintf('Encoding failed : %s', $process->getErrorOutput())); } + $this->logger->addInfo(sprintf('FFmpeg command successful')); + return $this; } @@ -238,7 +256,7 @@ class FFMpeg extends Binary } /** - * Return the binary name + * {@inheritdoc} * * @return string */ diff --git a/src/FFMpeg/FFProbe.php b/src/FFMpeg/FFProbe.php index 3827c11..17f3572 100644 --- a/src/FFMpeg/FFProbe.php +++ b/src/FFMpeg/FFProbe.php @@ -11,7 +11,9 @@ namespace FFMpeg; -use \Symfony\Component\Process\Process; +use FFMpeg\Exception\InvalidArgumentException; +use FFMpeg\Exception\RuntimeException; +use Symfony\Component\Process\Process; /** * FFProbe driver @@ -26,13 +28,13 @@ class FFProbe extends Binary * * @param string $pathfile * @return string - * @throws Exception\InvalidFileArgumentException - * @throws Exception\RuntimeException + * @throws InvalidArgumentException + * @throws RuntimeException */ public function probeFormat($pathfile) { if ( ! is_file($pathfile)) { - throw new Exception\InvalidFileArgumentException($pathfile); + throw new InvalidArgumentException($pathfile); } $cmd = $this->binary . ' ' . $pathfile . ' -show_format'; @@ -45,13 +47,13 @@ class FFProbe extends Binary * * @param string $pathfile * @return string - * @throws Exception\InvalidFileArgumentException - * @throws Exception\RuntimeException + * @throws InvalidArgumentException + * @throws RuntimeException */ public function probeStreams($pathfile) { if ( ! is_file($pathfile)) { - throw new Exception\InvalidFileArgumentException($pathfile); + throw new InvalidArgumentException($pathfile); } $cmd = $this->binary . ' ' . $pathfile . ' -show_streams'; @@ -63,27 +65,35 @@ class FFProbe extends Binary * * @param string $command * @return string - * @throws Exception\RuntimeException + * @throws RuntimeException */ protected function executeProbe($command) { + $this->logger->addInfo(sprintf('FFprobe executes command %s', $command)); + try { $process = new Process($command); $process->run(); } catch (\RuntimeException $e) { - throw new Exception\RuntimeException(sprintf('Failed to run the given command %s', $command)); + $this->logger->addInfo('FFprobe command failed'); + + throw new RuntimeException(sprintf('Failed to run the given command %s', $command)); } if ( ! $process->isSuccessful()) { - throw new Exception\RuntimeException(sprintf('Failed to probe %s', $command)); + $this->logger->addInfo('FFprobe command failed'); + + throw new RuntimeException(sprintf('Failed to probe %s', $command)); } + $this->logger->addInfo('FFprobe command successful'); + return $process->getOutput(); } /** - * Return the binary name + * {@inheritdoc} * * @return string */ diff --git a/src/FFMpeg/Format/AudioFormat.php b/src/FFMpeg/Format/AudioFormat.php index f2cfd34..efb42d8 100644 --- a/src/FFMpeg/Format/AudioFormat.php +++ b/src/FFMpeg/Format/AudioFormat.php @@ -14,10 +14,25 @@ namespace FFMpeg\Format; interface AudioFormat { + /** + * Returns the audio codec + * + * @return string + */ public function getAudioCodec(); + /** + * Get the audio sample rate + * + * @return integer + */ public function getAudioSampleRate(); + /** + * Get the kiloBitrate value + * + * @return integer + */ public function getKiloBitrate(); /** diff --git a/src/FFMpeg/Format/DefaultAudioFormat.php b/src/FFMpeg/Format/DefaultAudioFormat.php index e45a261..69bb81c 100644 --- a/src/FFMpeg/Format/DefaultAudioFormat.php +++ b/src/FFMpeg/Format/DefaultAudioFormat.php @@ -11,6 +11,8 @@ namespace FFMpeg\Format; +use FFMpeg\Exception\InvalidArgumentException; + /** * The abstract default Audio format * @@ -33,9 +35,7 @@ abstract class DefaultAudioFormat implements AudioFormat } /** - * Returns the audio codec - * - * @return string + * {@inheritdoc} */ public function getAudioCodec() { @@ -52,19 +52,19 @@ abstract class DefaultAudioFormat implements AudioFormat public function setAudioCodec($audioCodec) { if ( ! in_array($audioCodec, $this->getAvailableAudioCodecs())) { - throw new \InvalidArgumentException(sprintf( + throw new InvalidArgumentException(sprintf( 'Wrong audiocodec value for %s, available formats are %s' , $audioCodec, implode(', ', $this->getAvailableAudioCodecs()) )); } $this->audioCodec = $audioCodec; + + return $this; } /** - * Get the audio sample rate - * - * @return type + * {@inheritdoc} */ public function getAudioSampleRate() { @@ -80,16 +80,16 @@ abstract class DefaultAudioFormat implements AudioFormat public function setAudioSampleRate($audioSampleRate) { if ($audioSampleRate < 1) { - throw new \InvalidArgumentException('Wrong audio sample rate value'); + throw new InvalidArgumentException('Wrong audio sample rate value'); } $this->audioSampleRate = (int) $audioSampleRate; + + return $this; } /** - * Get the kiloBitrate value - * - * @return int + * {@inheritdoc} */ public function getKiloBitrate() { @@ -105,9 +105,11 @@ abstract class DefaultAudioFormat implements AudioFormat public function setKiloBitrate($kiloBitrate) { if ($kiloBitrate < 1) { - throw new \InvalidArgumentException('Wrong kiloBitrate value'); + throw new InvalidArgumentException('Wrong kiloBitrate value'); } $this->kiloBitrate = (int) $kiloBitrate; + + return $this; } } diff --git a/src/FFMpeg/Format/DefaultVideoFormat.php b/src/FFMpeg/Format/DefaultVideoFormat.php index 52da3f9..974d20c 100644 --- a/src/FFMpeg/Format/DefaultVideoFormat.php +++ b/src/FFMpeg/Format/DefaultVideoFormat.php @@ -11,6 +11,8 @@ namespace FFMpeg\Format; +use FFMpeg\Exception\InvalidArgumentException; + /** * The abstract default Video format * @@ -25,15 +27,19 @@ abstract class DefaultVideoFormat extends DefaultAudioFormat implements VideoFor protected $GOPsize = 25; protected $kiloBitrate = 1000; + /** + * Constructor + * + * @param integer $width + * @param integer $height The height of the video format + */ public function __construct($width, $height) { $this->setDimensions($width, $height); } /** - * Returns the width - * - * @return int + * {@inheritdoc} */ public function getWidth() { @@ -41,9 +47,7 @@ abstract class DefaultVideoFormat extends DefaultAudioFormat implements VideoFor } /** - * Returns the height - * - * @return int + * {@inheritdoc} */ public function getHeight() { @@ -60,20 +64,20 @@ abstract class DefaultVideoFormat extends DefaultAudioFormat implements VideoFor public function setDimensions($width, $height) { if ($width < 1) { - throw new \InvalidArgumentException('Wrong width value'); + throw new InvalidArgumentException('Wrong width value'); } if ($height < 1) { - throw new \InvalidArgumentException('Wrong height value'); + throw new InvalidArgumentException('Wrong height value'); } $this->width = $this->getMultiple($width, 16); $this->height = $this->getMultiple($height, 16); + + return $this; } /** - * Returns the framerate - * - * @return int + * {@inheritdoc} */ public function getFrameRate() { @@ -84,21 +88,22 @@ abstract class DefaultVideoFormat extends DefaultAudioFormat implements VideoFor * Set the framerate * * @param integer $frameRate + * * @throws \InvalidArgumentException */ public function setFrameRate($frameRate) { if ($frameRate < 1) { - throw new \InvalidArgumentException('Wrong framerate value'); + throw new InvalidArgumentException('Wrong framerate value'); } $this->frameRate = (int) $frameRate; + + return $this; } /** - * Returns the video codec - * - * @return string + * {@inheritdoc} */ public function getVideoCodec() { @@ -115,19 +120,19 @@ abstract class DefaultVideoFormat extends DefaultAudioFormat implements VideoFor public function setVideoCodec($videoCodec) { if ( ! in_array($videoCodec, $this->getAvailableVideoCodecs())) { - throw new \InvalidArgumentException(sprintf( + throw new InvalidArgumentException(sprintf( 'Wrong videocodec value for %s, available formats are %s' , $videoCodec, implode(', ', $this->getAvailableVideoCodecs()) )); } $this->videoCodec = $videoCodec; + + return $this; } /** - * Returns the GOP size - * - * @return int + * {@inheritdoc} */ public function getGOPsize() { @@ -138,15 +143,18 @@ abstract class DefaultVideoFormat extends DefaultAudioFormat implements VideoFor * Set the GOP size * * @param integer $GOPsize + * * @throws \InvalidArgumentException */ public function setGOPsize($GOPsize) { if ($GOPsize < 1) { - throw new \InvalidArgumentException('Wrong GOP size value'); + throw new InvalidArgumentException('Wrong GOP size value'); } $this->GOPsize = (int) $GOPsize; + + return $this; } /** @@ -154,7 +162,7 @@ abstract class DefaultVideoFormat extends DefaultAudioFormat implements VideoFor * * @param integer $value * @param integer $multiple - * @return int + * @return integer */ protected function getMultiple($value, $multiple) { diff --git a/src/FFMpeg/Format/VideoFormat.php b/src/FFMpeg/Format/VideoFormat.php index 38be13f..b838a3d 100644 --- a/src/FFMpeg/Format/VideoFormat.php +++ b/src/FFMpeg/Format/VideoFormat.php @@ -11,17 +11,47 @@ namespace FFMpeg\Format; +/** + * The video format interface + * + * @author Romain Neutron imprec@gmail.com + */ interface VideoFormat extends AudioFormat { + /** + * Returns the width + * + * @return integer + */ public function getWidth(); + /** + * Returns the height + * + * @return integer + */ public function getHeight(); + /** + * Returns the frame rate + * + * @return integer + */ public function getFrameRate(); + /** + * Returns the video codec + * + * @return string + */ public function getVideoCodec(); + /** + * Returns the GOP size + * + * @return integer + */ public function getGOPSize(); /** diff --git a/tests/src/FFMpeg/BinaryTest.php b/tests/src/FFMpeg/BinaryTest.php index 54a29e2..9711dbb 100644 --- a/tests/src/FFMpeg/BinaryTest.php +++ b/tests/src/FFMpeg/BinaryTest.php @@ -2,6 +2,9 @@ namespace FFMpeg; +use Monolog\Logger; +use Monolog\Handler\NullHandler; + class BinaryTest extends \PHPUnit_Framework_TestCase { @@ -9,14 +12,20 @@ class BinaryTest extends \PHPUnit_Framework_TestCase * @var Binary */ protected $object; + protected $logger; + + public function setUp() + { + $this->logger = new Logger('tests'); + $this->logger->pushHandler(new NullHandler()); + } /** * @covers FFMpeg\Binary::__construct */ public function testConstruct() { - $binary = new BinaryTester('pretty_binary'); - $binary = new BinaryTester('pretty_binary', new \Monolog\Logger('test')); + $binary = new BinaryTester('pretty_binary', $this->logger); } /** @@ -24,7 +33,7 @@ class BinaryTest extends \PHPUnit_Framework_TestCase */ public function testLoad() { - BinaryTester::load(); + BinaryTester::load($this->logger); } /** @@ -33,7 +42,7 @@ class BinaryTest extends \PHPUnit_Framework_TestCase */ public function testLoadWrongBinary() { - BinaryTesterWrongBinary::load(); + BinaryTesterWrongBinary::load($this->logger); } } diff --git a/tests/src/FFMpeg/FFMpegTest.php b/tests/src/FFMpeg/FFMpegTest.php index 00fa3c7..01a6801 100644 --- a/tests/src/FFMpeg/FFMpegTest.php +++ b/tests/src/FFMpeg/FFMpegTest.php @@ -2,6 +2,9 @@ namespace FFMpeg; +use Monolog\Logger; +use Monolog\Handler\NullHandler; + class FFMpegTest extends \PHPUnit_Framework_TestCase { @@ -14,11 +17,15 @@ class FFMpegTest extends \PHPUnit_Framework_TestCase * @var FFProbe */ protected $probe; + protected $logger; public function setUp() { - $this->object = FFMpeg::load(); - $this->probe = FFProbe::load(); + $this->logger = new Logger('tests'); + $this->logger->pushHandler(new NullHandler()); + + $this->object = FFMpeg::load($this->logger); + $this->probe = FFProbe::load($this->logger); } /** diff --git a/tests/src/FFMpeg/FFProbeTest.php b/tests/src/FFMpeg/FFProbeTest.php index 0af9e4b..26df48c 100644 --- a/tests/src/FFMpeg/FFProbeTest.php +++ b/tests/src/FFMpeg/FFProbeTest.php @@ -2,6 +2,9 @@ namespace FFMpeg; +use Monolog\Logger; +use Monolog\Handler\NullHandler; + class FFProbeTest extends \PHPUnit_Framework_TestCase { @@ -10,10 +13,14 @@ class FFProbeTest extends \PHPUnit_Framework_TestCase * @var FFProbe */ protected $object; + protected $logger; public function setUp() { - $this->object = FFProbe::load(); + $this->logger = new Logger('tests'); + $this->logger->pushHandler(new NullHandler()); + + $this->object = FFProbe::load($this->logger); } /**