From d83c7e271f8748bf4a39e638ff822319b618610a Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 11 Jan 2017 10:01:09 -0300 Subject: [PATCH 01/16] Creation of a filter to extract multiple frames from a video --- .../Frame/ExtractMultipleFramesFilter.php | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 src/FFMpeg/Filters/Frame/ExtractMultipleFramesFilter.php diff --git a/src/FFMpeg/Filters/Frame/ExtractMultipleFramesFilter.php b/src/FFMpeg/Filters/Frame/ExtractMultipleFramesFilter.php new file mode 100644 index 0000000..2a291b3 --- /dev/null +++ b/src/FFMpeg/Filters/Frame/ExtractMultipleFramesFilter.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FFMpeg\Filters\Frame; + +use FFMpeg\Exception\RuntimeException; +use FFMpeg\Media\Frame; + +class ExtractMultipleFramesFilter extends AbstractMediaType implements FrameFilterInterface +{ + /** will extract a frame every second */ + const FRAMERATE_EVERY_SEC = '1/1'; + /** will extract a frame every 2 seconds */ + const FRAMERATE_EVERY_2SEC = '1/2'; + /** will extract a frame every 5 seconds */ + const FRAMERATE_EVERY_5SEC = '1/5'; + /** will extract a frame every 10 seconds */ + const FRAMERATE_EVERY_10SEC = '1/10'; + /** will extract a frame every 30 seconds */ + const FRAMERATE_EVERY_10SEC = '1/30'; + /** will extract a frame every minute */ + const FRAMERATE_EVERY_10SEC = '1/60'; +{ + /** @var integer */ + private $priority; + private $frameRate; + private $destinationFolder; + + public function __construct($frameRate = self::FRAMERATE_EVERY_SEC, $destinationFolder = __DIR__, $priority = 0) + { + $this->priority = $priority; + $this->frameRate = $frameRate; + $this->destinationFolder = $destinationFolder; + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return $this->priority; + } + + /** + * {@inheritdoc} + */ + public function getFrameRate() + { + return $this->frameRate; + } + + /** + * {@inheritdoc} + */ + public function getDestinationFolder() + { + return $this->destinationFolder; + } + + /** + * {@inheritdoc} + */ + public function apply(Frame $frame) + { + $dimensions = null; + $commands = array(); + + foreach ($frame->getVideo()->getStreams() as $stream) { + if ($stream->isVideo()) { + try { + // Get the duration of the video + $duration = $this->getFormat()->get('duration'); + + // Get the number of frames per second we have to extract. + if(preg_match('/(\d+)(?:\s*)([\+\-\*\/])(?:\s*)(\d+)/', $this->frameRate, $matches) !== FALSE){ + $operator = $matches[2]; + + switch($operator){ + case '/': + $nbFramesPerSecond = $matches[1] / $matches[3]; + break; + + default: + throw new InvalidArgumentException('The frame rate is not a proper division: ' . $this->frameRate); + break; + } + } + + // Set the number of digits to use in the exported filenames + $nbDigitsInFileNames = ceil( $duration * $nbFramesPerSecond ); + + // Set the parameters + $commands[] = '-vf'; + $commands[] = 'fps=' . $this->frameRate; + $commands[] = $this->destinationFolder . 'frame-%0'.$nbDigitsInFileNames.'d.jpg'; + break; + } + catch (RuntimeException $e) { + + } + } + } + + return $commands; + } +} From b3155f9622764b5f85c210985960ac4dda7d0213 Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 11 Jan 2017 10:06:17 -0300 Subject: [PATCH 02/16] Creation of the method to add the filter --- src/FFMpeg/Filters/Frame/FrameFilters.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/FFMpeg/Filters/Frame/FrameFilters.php b/src/FFMpeg/Filters/Frame/FrameFilters.php index e4b9614..f599ba6 100644 --- a/src/FFMpeg/Filters/Frame/FrameFilters.php +++ b/src/FFMpeg/Filters/Frame/FrameFilters.php @@ -36,4 +36,19 @@ class FrameFilters return $this; } + + /** + * Fixes the display ratio of the output frame. + * + * In case the sample ratio and display ratio are different, image may be + * anamorphozed. This filter fixes this by specifying the output size. + * + * @return FrameFilters + */ + public function extractMultipleFrames($frameRate = ExtractMultipleFramesFilter::FRAMERATE_EVERY_2SEC, $destinationFolder = __DIR__) + { + $this->frame->addFilter(new ExtractMultipleFramesFilter($frameRate, $destinationFolder)); + + return $this; + } } From 3aa13c09d30665aac6b7725288effa2a33d44832 Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 11 Jan 2017 10:17:21 -0300 Subject: [PATCH 03/16] This filter is a video filter, not a frame filter --- .../Frame/ExtractMultipleFramesFilter.php | 114 ------------------ src/FFMpeg/Filters/Frame/FrameFilters.php | 15 --- .../Video/ExtractMultipleFramesFilter.php | 109 +++++++++++++++++ src/FFMpeg/Filters/Video/VideoFilters.php | 13 ++ 4 files changed, 122 insertions(+), 129 deletions(-) delete mode 100644 src/FFMpeg/Filters/Frame/ExtractMultipleFramesFilter.php create mode 100644 src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php diff --git a/src/FFMpeg/Filters/Frame/ExtractMultipleFramesFilter.php b/src/FFMpeg/Filters/Frame/ExtractMultipleFramesFilter.php deleted file mode 100644 index 2a291b3..0000000 --- a/src/FFMpeg/Filters/Frame/ExtractMultipleFramesFilter.php +++ /dev/null @@ -1,114 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace FFMpeg\Filters\Frame; - -use FFMpeg\Exception\RuntimeException; -use FFMpeg\Media\Frame; - -class ExtractMultipleFramesFilter extends AbstractMediaType implements FrameFilterInterface -{ - /** will extract a frame every second */ - const FRAMERATE_EVERY_SEC = '1/1'; - /** will extract a frame every 2 seconds */ - const FRAMERATE_EVERY_2SEC = '1/2'; - /** will extract a frame every 5 seconds */ - const FRAMERATE_EVERY_5SEC = '1/5'; - /** will extract a frame every 10 seconds */ - const FRAMERATE_EVERY_10SEC = '1/10'; - /** will extract a frame every 30 seconds */ - const FRAMERATE_EVERY_10SEC = '1/30'; - /** will extract a frame every minute */ - const FRAMERATE_EVERY_10SEC = '1/60'; -{ - /** @var integer */ - private $priority; - private $frameRate; - private $destinationFolder; - - public function __construct($frameRate = self::FRAMERATE_EVERY_SEC, $destinationFolder = __DIR__, $priority = 0) - { - $this->priority = $priority; - $this->frameRate = $frameRate; - $this->destinationFolder = $destinationFolder; - } - - /** - * {@inheritdoc} - */ - public function getPriority() - { - return $this->priority; - } - - /** - * {@inheritdoc} - */ - public function getFrameRate() - { - return $this->frameRate; - } - - /** - * {@inheritdoc} - */ - public function getDestinationFolder() - { - return $this->destinationFolder; - } - - /** - * {@inheritdoc} - */ - public function apply(Frame $frame) - { - $dimensions = null; - $commands = array(); - - foreach ($frame->getVideo()->getStreams() as $stream) { - if ($stream->isVideo()) { - try { - // Get the duration of the video - $duration = $this->getFormat()->get('duration'); - - // Get the number of frames per second we have to extract. - if(preg_match('/(\d+)(?:\s*)([\+\-\*\/])(?:\s*)(\d+)/', $this->frameRate, $matches) !== FALSE){ - $operator = $matches[2]; - - switch($operator){ - case '/': - $nbFramesPerSecond = $matches[1] / $matches[3]; - break; - - default: - throw new InvalidArgumentException('The frame rate is not a proper division: ' . $this->frameRate); - break; - } - } - - // Set the number of digits to use in the exported filenames - $nbDigitsInFileNames = ceil( $duration * $nbFramesPerSecond ); - - // Set the parameters - $commands[] = '-vf'; - $commands[] = 'fps=' . $this->frameRate; - $commands[] = $this->destinationFolder . 'frame-%0'.$nbDigitsInFileNames.'d.jpg'; - break; - } - catch (RuntimeException $e) { - - } - } - } - - return $commands; - } -} diff --git a/src/FFMpeg/Filters/Frame/FrameFilters.php b/src/FFMpeg/Filters/Frame/FrameFilters.php index f599ba6..e4b9614 100644 --- a/src/FFMpeg/Filters/Frame/FrameFilters.php +++ b/src/FFMpeg/Filters/Frame/FrameFilters.php @@ -36,19 +36,4 @@ class FrameFilters return $this; } - - /** - * Fixes the display ratio of the output frame. - * - * In case the sample ratio and display ratio are different, image may be - * anamorphozed. This filter fixes this by specifying the output size. - * - * @return FrameFilters - */ - public function extractMultipleFrames($frameRate = ExtractMultipleFramesFilter::FRAMERATE_EVERY_2SEC, $destinationFolder = __DIR__) - { - $this->frame->addFilter(new ExtractMultipleFramesFilter($frameRate, $destinationFolder)); - - return $this; - } } diff --git a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php new file mode 100644 index 0000000..48323ce --- /dev/null +++ b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php @@ -0,0 +1,109 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FFMpeg\Filters\Video; + +use FFMpeg\Exception\InvalidArgumentException; + +class ExtractMultipleFramesFilter implements VideoFilterInterface +{ + /** will extract a frame every second */ + const FRAMERATE_EVERY_SEC = '1/1'; + /** will extract a frame every 2 seconds */ + const FRAMERATE_EVERY_2SEC = '1/2'; + /** will extract a frame every 5 seconds */ + const FRAMERATE_EVERY_5SEC = '1/5'; + /** will extract a frame every 10 seconds */ + const FRAMERATE_EVERY_10SEC = '1/10'; + /** will extract a frame every 30 seconds */ + const FRAMERATE_EVERY_10SEC = '1/30'; + /** will extract a frame every minute */ + const FRAMERATE_EVERY_10SEC = '1/60'; +{ + /** @var integer */ + private $priority; + private $frameRate; + private $destinationFolder; + + public function __construct($frameRate = self::FRAMERATE_EVERY_SEC, $destinationFolder = __DIR__, $priority = 0) + { + $this->priority = $priority; + $this->frameRate = $frameRate; + $this->destinationFolder = $destinationFolder; + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return $this->priority; + } + + /** + * {@inheritdoc} + */ + public function getFrameRate() + { + return $this->frameRate; + } + + /** + * {@inheritdoc} + */ + public function getDestinationFolder() + { + return $this->destinationFolder; + } + + /** + * {@inheritdoc} + */ + public function apply(Video $video, VideoInterface $format) + { + $dimensions = null; + $commands = array(); + + try { + // Get the duration of the video + $duration = $this->getFormat()->get('duration'); + + // Get the number of frames per second we have to extract. + if(preg_match('/(\d+)(?:\s*)([\+\-\*\/])(?:\s*)(\d+)/', $this->frameRate, $matches) !== FALSE){ + $operator = $matches[2]; + + switch($operator){ + case '/': + $nbFramesPerSecond = $matches[1] / $matches[3]; + break; + + default: + throw new InvalidArgumentException('The frame rate is not a proper division: ' . $this->frameRate); + break; + } + } + + // Set the number of digits to use in the exported filenames + $nbDigitsInFileNames = ceil( $duration * $nbFramesPerSecond ); + + // Set the parameters + $commands[] = '-vf'; + $commands[] = 'fps=' . $this->frameRate; + $commands[] = $this->destinationFolder . 'frame-%0'.$nbDigitsInFileNames.'d.jpg'; + break; + } + catch (RuntimeException $e) { + throw new RuntimeException('An error occured while extracting the frames: ' . $e->getCode() . ' The message: '$e->getMessage()); + } + + return $commands; + } +} diff --git a/src/FFMpeg/Filters/Video/VideoFilters.php b/src/FFMpeg/Filters/Video/VideoFilters.php index 00a99d9..27371d1 100644 --- a/src/FFMpeg/Filters/Video/VideoFilters.php +++ b/src/FFMpeg/Filters/Video/VideoFilters.php @@ -132,4 +132,17 @@ class VideoFilters extends AudioFilters return $this; } + + /** + * @param string $frameRate + * @param string $destinationFolder + * + * @return $this + */ + public function extractMultipleFrames($frameRate = ExtractMultipleFramesFilter::FRAMERATE_EVERY_2SEC, $destinationFolder = __DIR__) + { + $this->frame->addFilter(new ExtractMultipleFramesFilter($frameRate, $destinationFolder)); + + return $this; + } } From 6aeec7d337691dd6e66778aafc362ff500e4f77e Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 11 Jan 2017 10:21:14 -0300 Subject: [PATCH 04/16] We make sure that the destination folder has a trailing slash --- src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php index 48323ce..004e263 100644 --- a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php +++ b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php @@ -37,6 +37,12 @@ class ExtractMultipleFramesFilter implements VideoFilterInterface { $this->priority = $priority; $this->frameRate = $frameRate; + + // Make sure that the destination folder has a trailing slash + if(strcmp( substr($destinationFolder, -1), "/") != 0) + $destinationFolder .= "/"; + + // Set the destination folder $this->destinationFolder = $destinationFolder; } From cbb4c35ef047f4fc212cee163a0cfb338974d9f0 Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 11 Jan 2017 10:31:18 -0300 Subject: [PATCH 05/16] We remove a bracket which has nothing to do there. --- src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php index 004e263..8f18d7c 100644 --- a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php +++ b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php @@ -27,7 +27,7 @@ class ExtractMultipleFramesFilter implements VideoFilterInterface const FRAMERATE_EVERY_10SEC = '1/30'; /** will extract a frame every minute */ const FRAMERATE_EVERY_10SEC = '1/60'; -{ + /** @var integer */ private $priority; private $frameRate; From 8ac67679ab8529a1eca065b8f007b222413b06ea Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 11 Jan 2017 10:35:29 -0300 Subject: [PATCH 06/16] Fixing a bug when throwing an exception --- src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php index 8f18d7c..2f61101 100644 --- a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php +++ b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php @@ -107,7 +107,7 @@ class ExtractMultipleFramesFilter implements VideoFilterInterface break; } catch (RuntimeException $e) { - throw new RuntimeException('An error occured while extracting the frames: ' . $e->getCode() . ' The message: '$e->getMessage()); + throw new RuntimeException('An error occured while extracting the frames: ' . $e->getMessage() . '. The code: ' . $e->getCode()); } return $commands; From 2f47c45093ccd2ee029adc9cdaa400cc545bd66e Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 11 Jan 2017 10:41:01 -0300 Subject: [PATCH 07/16] Fixing the names of the constants --- src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php index 2f61101..6133396 100644 --- a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php +++ b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php @@ -24,9 +24,9 @@ class ExtractMultipleFramesFilter implements VideoFilterInterface /** will extract a frame every 10 seconds */ const FRAMERATE_EVERY_10SEC = '1/10'; /** will extract a frame every 30 seconds */ - const FRAMERATE_EVERY_10SEC = '1/30'; + const FRAMERATE_EVERY_30SEC = '1/30'; /** will extract a frame every minute */ - const FRAMERATE_EVERY_10SEC = '1/60'; + const FRAMERATE_EVERY_60SEC = '1/60'; /** @var integer */ private $priority; From 223118db4e6df322b7200da2ae323245cc0e680d Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 11 Jan 2017 10:43:30 -0300 Subject: [PATCH 08/16] We remove a break instruction inacurrately copied-pasted. --- src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php index 6133396..96346b9 100644 --- a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php +++ b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php @@ -104,7 +104,6 @@ class ExtractMultipleFramesFilter implements VideoFilterInterface $commands[] = '-vf'; $commands[] = 'fps=' . $this->frameRate; $commands[] = $this->destinationFolder . 'frame-%0'.$nbDigitsInFileNames.'d.jpg'; - break; } catch (RuntimeException $e) { throw new RuntimeException('An error occured while extracting the frames: ' . $e->getMessage() . '. The code: ' . $e->getCode()); From c7df2b17e63e719c3f5c18f9925c65d7027814a9 Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 11 Jan 2017 10:49:37 -0300 Subject: [PATCH 09/16] Fixing the way we apply for the filter. --- .../Video/ExtractMultipleFramesFilter.php | 2 ++ src/FFMpeg/Filters/Video/VideoFilters.php | 28 ++++++++++--------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php index 96346b9..b0998ff 100644 --- a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php +++ b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php @@ -12,6 +12,8 @@ namespace FFMpeg\Filters\Video; use FFMpeg\Exception\InvalidArgumentException; +use FFMpeg\Media\Video; +use FFMpeg\Format\VideoInterface; class ExtractMultipleFramesFilter implements VideoFilterInterface { diff --git a/src/FFMpeg/Filters/Video/VideoFilters.php b/src/FFMpeg/Filters/Video/VideoFilters.php index 27371d1..0f33b4e 100644 --- a/src/FFMpeg/Filters/Video/VideoFilters.php +++ b/src/FFMpeg/Filters/Video/VideoFilters.php @@ -57,6 +57,21 @@ class VideoFilters extends AudioFilters return $this; } + /** + * Extract multiple frames from the video + * + * @param string $frameRate + * @param string $destinationFolder + * + * @return $this + */ + public function extractMultipleFrames($frameRate = ExtractMultipleFramesFilter::FRAMERATE_EVERY_2SEC, $destinationFolder = __DIR__) + { + $this->media->addFilter(new ExtractMultipleFramesFilter($frameRate, $destinationFolder)); + + return $this; + } + /** * Synchronizes audio and video. * @@ -132,17 +147,4 @@ class VideoFilters extends AudioFilters return $this; } - - /** - * @param string $frameRate - * @param string $destinationFolder - * - * @return $this - */ - public function extractMultipleFrames($frameRate = ExtractMultipleFramesFilter::FRAMERATE_EVERY_2SEC, $destinationFolder = __DIR__) - { - $this->frame->addFilter(new ExtractMultipleFramesFilter($frameRate, $destinationFolder)); - - return $this; - } } From 8bdc839e911be0ae0cc0cc37f25b9b3e03e9d9e7 Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 11 Jan 2017 10:55:49 -0300 Subject: [PATCH 10/16] We remove a useless variable. --- src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php index b0998ff..2c4b9cb 100644 --- a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php +++ b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php @@ -77,7 +77,6 @@ class ExtractMultipleFramesFilter implements VideoFilterInterface */ public function apply(Video $video, VideoInterface $format) { - $dimensions = null; $commands = array(); try { From ca8eea7ec60f3f8a6e46961d964299c8a2c28ebd Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 11 Jan 2017 10:59:22 -0300 Subject: [PATCH 11/16] We fix the usage of --- src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php index 2c4b9cb..bb26bc9 100644 --- a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php +++ b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php @@ -81,7 +81,7 @@ class ExtractMultipleFramesFilter implements VideoFilterInterface try { // Get the duration of the video - $duration = $this->getFormat()->get('duration'); + $duration = $format()->get('duration'); // Get the number of frames per second we have to extract. if(preg_match('/(\d+)(?:\s*)([\+\-\*\/])(?:\s*)(\d+)/', $this->frameRate, $matches) !== FALSE){ From 5ff0b24230a170ecfcf6c53c7ce8d76668629a6e Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 11 Jan 2017 11:15:22 -0300 Subject: [PATCH 12/16] Here is the stable version of the filter, all bugs fixed. --- src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php index bb26bc9..e3db5b9 100644 --- a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php +++ b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php @@ -11,6 +11,7 @@ namespace FFMpeg\Filters\Video; +use FFMpeg\FFProbe; use FFMpeg\Exception\InvalidArgumentException; use FFMpeg\Media\Video; use FFMpeg\Format\VideoInterface; @@ -81,7 +82,11 @@ class ExtractMultipleFramesFilter implements VideoFilterInterface try { // Get the duration of the video - $duration = $format()->get('duration'); + foreach ($video->getStreams()->videos() as $stream) { + if ($stream->has('duration')) { + $duration = $stream->get('duration'); + } + } // Get the number of frames per second we have to extract. if(preg_match('/(\d+)(?:\s*)([\+\-\*\/])(?:\s*)(\d+)/', $this->frameRate, $matches) !== FALSE){ From 4d76b26d1dc90be7672dbfc8fa084df8a412562d Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 11 Jan 2017 11:17:47 -0300 Subject: [PATCH 13/16] We improve the way we pass the number of digits in the filename --- src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php index e3db5b9..21f6746 100644 --- a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php +++ b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php @@ -105,11 +105,13 @@ class ExtractMultipleFramesFilter implements VideoFilterInterface // Set the number of digits to use in the exported filenames $nbDigitsInFileNames = ceil( $duration * $nbFramesPerSecond ); + if($nbDigitsInFileNames < 10) + $nbDigitsInFileNames = '0' . (string)$nbDigitsInFileNames; // Set the parameters $commands[] = '-vf'; $commands[] = 'fps=' . $this->frameRate; - $commands[] = $this->destinationFolder . 'frame-%0'.$nbDigitsInFileNames.'d.jpg'; + $commands[] = $this->destinationFolder . 'frame-%'.$nbDigitsInFileNames.'d.jpg'; } catch (RuntimeException $e) { throw new RuntimeException('An error occured while extracting the frames: ' . $e->getMessage() . '. The code: ' . $e->getCode()); From 580765386adcf33d15c57e411c3ffec2cb705e99 Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 11 Jan 2017 11:49:34 -0300 Subject: [PATCH 14/16] We change the way we deal with the number of digits in the filename --- .../Filters/Video/ExtractMultipleFramesFilter.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php index 21f6746..18b8225 100644 --- a/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php +++ b/src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php @@ -104,9 +104,14 @@ class ExtractMultipleFramesFilter implements VideoFilterInterface } // Set the number of digits to use in the exported filenames - $nbDigitsInFileNames = ceil( $duration * $nbFramesPerSecond ); - if($nbDigitsInFileNames < 10) - $nbDigitsInFileNames = '0' . (string)$nbDigitsInFileNames; + $nbImages = ceil( $duration * $nbFramesPerSecond ); + + if($nbImages < 100) + $nbDigitsInFileNames = "02"; + elseif($nbImages < 1000) + $nbDigitsInFileNames = "03"; + else + $nbDigitsInFileNames = "06"; // Set the parameters $commands[] = '-vf'; From c90f26724cceb5804f7d0ef8e07ea640a797248a Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 11 Jan 2017 12:03:54 -0300 Subject: [PATCH 15/16] Creation of the tests for the ExtractMultipleFramesFilter class --- .../Video/ExtractMultipleFramesFilterTest.php | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 tests/Unit/Filters/Video/ExtractMultipleFramesFilterTest.php diff --git a/tests/Unit/Filters/Video/ExtractMultipleFramesFilterTest.php b/tests/Unit/Filters/Video/ExtractMultipleFramesFilterTest.php new file mode 100644 index 0000000..6619df7 --- /dev/null +++ b/tests/Unit/Filters/Video/ExtractMultipleFramesFilterTest.php @@ -0,0 +1,51 @@ +getVideoMock(); + $pathfile = '/path/to/file'.mt_rand(); + + $format = $this->getMock('FFMpeg\Format\VideoInterface'); + $format->expects($this->any()) + ->method('getModulus') + ->will($this->returnValue($modulus)); + + $streams = new StreamCollection(array( + new Stream(array( + 'codec_type' => 'video', + 'duration' => $duration, + )) + )); + + $video->expects($this->once()) + ->method('getStreams') + ->will($this->returnValue($streams)); + + $filter = new ExtractMultipleFramesFilter($frameRate, $destinationFolder); + $this->assertEquals($expected, $filter->apply($video, $format)); + } + + public function provideFrameRates() + { + return array( + array(ExtractMultipleFramesFilter::FRAMERATE_EVERY_SEC, '/', 100, 2, array('-vf', 'fps=1/1', '/frame-%03d.jpg')), + array(ExtractMultipleFramesFilter::FRAMERATE_EVERY_2SEC, '/', 100, 2, array('-vf', 'fps=1/2', '/frame-%02d.jpg')), + array(ExtractMultipleFramesFilter::FRAMERATE_EVERY_5SEC, '/', 100, 2, array('-vf', 'fps=1/5', '/frame-%02d.jpg')), + array(ExtractMultipleFramesFilter::FRAMERATE_EVERY_10SEC, '/', 100, 2, array('-vf', 'fps=1/10', '/frame-%02d.jpg')), + array(ExtractMultipleFramesFilter::FRAMERATE_EVERY_30SEC, '/', 100, 2, array('-vf', 'fps=1/30', '/frame-%02d.jpg')), + array(ExtractMultipleFramesFilter::FRAMERATE_EVERY_60SEC, '/', 100, 2, array('-vf', 'fps=1/60', '/frame-%02d.jpg')), + ); + } +} From ba17ad273a3a91d79cce1189d1e55463e1db38b5 Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 11 Jan 2017 12:13:59 -0300 Subject: [PATCH 16/16] We update the README with this new filter --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 3f7cc1f..c204cd8 100644 --- a/README.md +++ b/README.md @@ -145,6 +145,18 @@ $frame = $video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(42)); $frame->save('image.jpg'); ``` +If you want to extract multiple images from your video, you can use the following filter: + +```php +$video + ->filters() + ->extractMultipleFrames(FFMpeg\Filters\Video\ExtractMultipleFramesFilter::FRAMERATE_EVERY_10SEC, . '/path/to/destination/folder/') + ->synchronize(); + +$video + ->save(new FFMpeg\Format\Video\X264(), '/path/to/new/file'); +``` + ##### Generate a waveform You can generate a waveform of an audio file using the `FFMpeg\Media\Audio::waveform`