From 010b3b8a6d936476cea13ede8a4e85fbe6048be1 Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Thu, 10 Nov 2016 12:19:17 -0300 Subject: [PATCH 01/12] Creation of a setPasses method for the X264 format. --- .../API/API/FFMpeg/Format/Video/X264.html | 43 +++++++++++++++++-- src/FFMpeg/Format/Video/X264.php | 16 ++++++- 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/docs/source/API/API/FFMpeg/Format/Video/X264.html b/docs/source/API/API/FFMpeg/Format/Video/X264.html index 399b173..bcf7d52 100644 --- a/docs/source/API/API/FFMpeg/Format/Video/X264.html +++ b/docs/source/API/API/FFMpeg/Format/Video/X264.html @@ -119,7 +119,17 @@ - string + integer + + + setPasses(integer $passes) +

Sets the number of passes.

+ + + + + + integer getPasses() @@ -499,12 +509,37 @@ + + + +

+
in X264 at line 68
+ public integer + setPasses(integer $passes) +

+
+

Sets the number of passes.

+

+

+
+ +

Parameters

+ + + + + + +
integer$passes
+ + +

-
at line 68
- public string +
in X264 at line 79
+ public integer getPasses()

@@ -517,7 +552,7 @@ - + diff --git a/src/FFMpeg/Format/Video/X264.php b/src/FFMpeg/Format/Video/X264.php index 5f8e8d9..c945167 100644 --- a/src/FFMpeg/Format/Video/X264.php +++ b/src/FFMpeg/Format/Video/X264.php @@ -19,6 +19,9 @@ class X264 extends DefaultVideo /** @var boolean */ private $bframesSupport = true; + /** @var integer */ + private $passes = 2; + public function __construct($audioCodec = 'libfaac', $videoCodec = 'libx264') { $this @@ -62,12 +65,23 @@ class X264 extends DefaultVideo return array('libx264'); } + /** + * @param $passes + * + * @return X264 + */ + public function setPasses($passes) + { + $this->passes = $passes; + return $this; + } + /** * {@inheritDoc} */ public function getPasses() { - return 2; + return $this->passes; } /** From b7a8be46aa72a0193ef41ff8a912614891906021 Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Tue, 15 Nov 2016 16:54:46 -0300 Subject: [PATCH 02/12] First implemtation of the waveform feature --- .../Waveform/WaveformFilterInterface.php | 20 ++++ .../Filters/Waveform/WaveformFilters.php | 39 +++++++ .../Waveform/WaveformRatioFixerFilter.php | 69 ++++++++++++ src/FFMpeg/Media/Waveform.php | 101 ++++++++++++++++++ tests/Unit/Media/WaveformTest.php | 71 ++++++++++++ 5 files changed, 300 insertions(+) create mode 100644 src/FFMpeg/Filters/Waveform/WaveformFilterInterface.php create mode 100644 src/FFMpeg/Filters/Waveform/WaveformFilters.php create mode 100644 src/FFMpeg/Filters/Waveform/WaveformRatioFixerFilter.php create mode 100644 src/FFMpeg/Media/Waveform.php create mode 100644 tests/Unit/Media/WaveformTest.php diff --git a/src/FFMpeg/Filters/Waveform/WaveformFilterInterface.php b/src/FFMpeg/Filters/Waveform/WaveformFilterInterface.php new file mode 100644 index 0000000..7cabdd3 --- /dev/null +++ b/src/FFMpeg/Filters/Waveform/WaveformFilterInterface.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FFMpeg\Filters\Waveform; + +use FFMpeg\Filters\FilterInterface; +use FFMpeg\Media\Waveform; + +interface WaveformFilterInterface extends FilterInterface +{ + public function apply(Waveform $waveform); +} diff --git a/src/FFMpeg/Filters/Waveform/WaveformFilters.php b/src/FFMpeg/Filters/Waveform/WaveformFilters.php new file mode 100644 index 0000000..6ef4043 --- /dev/null +++ b/src/FFMpeg/Filters/Waveform/WaveformFilters.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FFMpeg\Filters\Waveform; + +use FFMpeg\Media\Waveform; + +class WaveformFilters +{ + private $waveform; + + public function __construct(Waveform $waveform) + { + $this->waveform = $waveform; + } + + /** + * 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 fixDisplayRatio() + { + $this->frame->addFilter(new DisplayRatioFixerFilter()); + + return $this; + } +} diff --git a/src/FFMpeg/Filters/Waveform/WaveformRatioFixerFilter.php b/src/FFMpeg/Filters/Waveform/WaveformRatioFixerFilter.php new file mode 100644 index 0000000..61d558b --- /dev/null +++ b/src/FFMpeg/Filters/Waveform/WaveformRatioFixerFilter.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FFMpeg\Filters\Waveform; + +use FFMpeg\Exception\RuntimeException; +use FFMpeg\Media\Waveform; + +class WaveformRatioFixerFilter implements WaveformFilterInterface +{ + /** @var boolean */ + private $downmix; + + // By default, the downmix value is set to FALSE. + public function __construct($downmix = FALSE) + { + $this->downmix = $downmix; + } + + /** + * {@inheritdoc} + */ + public function getDownmix() + { + return $this->downmix; + } + + /** + * {@inheritdoc} + */ + public function apply(Waveform $waveform) + { + $dimensions = null; + $commands = array(); + + foreach ($waveform->getVideo()->getStreams() as $stream) { + if ($stream->isVideo()) { + try { + + // Get the dimensions of the video + $dimensions = $stream->getDimensions(); + + // If the downmix parameter is set to TRUE, we add an option to the FFMPEG command + if(!$this->downmix) { + $commands[] = '"showwavespic=s=' . $dimensions->getWidth() . 'x' . $dimensions->getHeight().'"'; + } + else { + $commands[] = '"aformat=channel_layouts=mono,showwavespic=s=' . $dimensions->getWidth() . 'x' . $dimensions->getHeight().'"'; + } + + break; + + } catch (RuntimeException $e) { + + } + } + } + + return $commands; + } +} diff --git a/src/FFMpeg/Media/Waveform.php b/src/FFMpeg/Media/Waveform.php new file mode 100644 index 0000000..8adf2be --- /dev/null +++ b/src/FFMpeg/Media/Waveform.php @@ -0,0 +1,101 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FFMpeg\Media; + +use Alchemy\BinaryDriver\Exception\ExecutionFailureException; +use FFMpeg\Filters\Waveform\WaveformFilterInterface; +use FFMpeg\Filters\Waveform\WaveformFilters; +use FFMpeg\Driver\FFMpegDriver; +use FFMpeg\FFProbe; +use FFMpeg\Exception\RuntimeException; +use FFMpeg\Coordinate\TimeCode; + +class Waveform extends AbstractMediaType +{ + /** @var Video */ + private $video; + + public function __construct(Video $video, FFMpegDriver $driver, FFProbe $ffprobe) + { + parent::__construct($video->getPathfile(), $driver, $ffprobe); + $this->video = $video; + } + + /** + * Returns the video related to the waveform. + * + * @return Video + */ + public function getVideo() + { + return $this->video; + } + + /** + * {@inheritdoc} + * + * @return WaveformFilters + */ + public function filters() + { + return new WaveformFilters($this); + } + + /** + * {@inheritdoc} + * + * @return Waveform + */ + public function addFilter(WaveformFilterInterface $filter) + { + $this->filters->add($filter); + + return $this; + } + + /** + * Saves the waveform in the given filename. + * + * @param string $pathfile + * + * @return Waveform + * + * @throws RuntimeException + */ + public function save($pathfile) + { + /** + * might be optimized with http://ffmpeg.org/trac/ffmpeg/wiki/Seeking%20with%20FFmpeg + * @see http://ffmpeg.org/ffmpeg.html#Main-options + */ + $commands = array( + '-i', 'input', '-filter_complex', + '-frames:v', '1', + $this->pathfile + ); + + foreach ($this->filters as $filter) { + $commands = array_merge($commands, $filter->apply($this)); + } + + $commands = array_merge($commands, array($pathfile)); + + try { + $this->driver->command($commands); + } catch (ExecutionFailureException $e) { + $this->cleanupTemporaryFile($pathfile); + throw new RuntimeException('Unable to save waveform', $e->getCode(), $e); + } + + return $this; + } +} diff --git a/tests/Unit/Media/WaveformTest.php b/tests/Unit/Media/WaveformTest.php new file mode 100644 index 0000000..d88da55 --- /dev/null +++ b/tests/Unit/Media/WaveformTest.php @@ -0,0 +1,71 @@ +getFFMpegDriverMock(); + $ffprobe = $this->getFFProbeMock(); + + $waveform = new Waveform($this->getVideoMock(__FILE__), $driver, $ffprobe); + $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->getMock('FFMpeg\Filters\Waveform\WaveformFilterInterface'); + + $filters->expects($this->once()) + ->method('add') + ->with($filter); + + $waveform = new Waveform($this->getVideoMock(__FILE__), $driver, $ffprobe); + $waveform->setFiltersCollection($filters); + $waveform->addFilter($filter); + } + + /** + * @dataProvider provideSaveOptions + */ + public function testSave($commands) + { + $driver = $this->getFFMpegDriverMock(); + $ffprobe = $this->getFFProbeMock(); + + $pathfile = '/target/destination'; + + array_push($commands, $pathfile); + + $driver->expects($this->once()) + ->method('command') + ->with($commands); + + $waveform = new Waveform($this->getVideoMock(__FILE__), $driver, $ffprobe); + $this->assertSame($waveform, $waveform->save($pathfile)); + } + + public function provideSaveOptions() + { + return array( + array( + array( + '-i', 'input', '-filter_complex', + '-frames:v', '1', + __FILE__ + ), + ), + ); + } +} From 9f970c5d5a90ee9303a5e86af5dc5dca0458594a Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 16 Nov 2016 12:29:56 -0300 Subject: [PATCH 03/12] Creation of a waveform method in FFMpeg\Media\Video --- .../Filters/Waveform/WaveformFilterInterface.php | 2 +- src/FFMpeg/Filters/Waveform/WaveformFilters.php | 8 ++++---- .../Filters/Waveform/WaveformRatioFixerFilter.php | 2 +- src/FFMpeg/Media/Video.php | 10 ++++++++++ 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/FFMpeg/Filters/Waveform/WaveformFilterInterface.php b/src/FFMpeg/Filters/Waveform/WaveformFilterInterface.php index 7cabdd3..51e69bc 100644 --- a/src/FFMpeg/Filters/Waveform/WaveformFilterInterface.php +++ b/src/FFMpeg/Filters/Waveform/WaveformFilterInterface.php @@ -3,7 +3,7 @@ /* * This file is part of PHP-FFmpeg. * - * (c) Alchemy + * (c) Strime * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/FFMpeg/Filters/Waveform/WaveformFilters.php b/src/FFMpeg/Filters/Waveform/WaveformFilters.php index 6ef4043..703220f 100644 --- a/src/FFMpeg/Filters/Waveform/WaveformFilters.php +++ b/src/FFMpeg/Filters/Waveform/WaveformFilters.php @@ -3,7 +3,7 @@ /* * This file is part of PHP-FFmpeg. * - * (c) Alchemy + * (c) Strime * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -23,16 +23,16 @@ class WaveformFilters } /** - * Fixes the display ratio of the output frame. + * Fixes the display ratio of the output waveform. * * 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 + * @return WaveformFilters */ public function fixDisplayRatio() { - $this->frame->addFilter(new DisplayRatioFixerFilter()); + $this->waveform->addFilter(new DisplayRatioFixerFilter()); return $this; } diff --git a/src/FFMpeg/Filters/Waveform/WaveformRatioFixerFilter.php b/src/FFMpeg/Filters/Waveform/WaveformRatioFixerFilter.php index 61d558b..ec40205 100644 --- a/src/FFMpeg/Filters/Waveform/WaveformRatioFixerFilter.php +++ b/src/FFMpeg/Filters/Waveform/WaveformRatioFixerFilter.php @@ -3,7 +3,7 @@ /* * This file is part of PHP-FFmpeg. * - * (c) Alchemy + * (c) Strime * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/FFMpeg/Media/Video.php b/src/FFMpeg/Media/Video.php index 9200f49..3338b51 100644 --- a/src/FFMpeg/Media/Video.php +++ b/src/FFMpeg/Media/Video.php @@ -181,4 +181,14 @@ class Video extends Audio { return new Frame($this, $this->driver, $this->ffprobe, $at); } + + /** + * Gets the waveform of the video. + * + * @return Waveform + */ + public function waveform() + { + return new Waveform($this, $this->driver, $this->ffprobe); + } } From 18845d406e1d4839886b2e010ff51a1c7bc97480 Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 16 Nov 2016 12:43:40 -0300 Subject: [PATCH 04/12] We add a missing parameter to the ffmpeg command --- src/FFMpeg/Media/Video.php | 6 ++++-- src/FFMpeg/Media/Waveform.php | 7 ++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/FFMpeg/Media/Video.php b/src/FFMpeg/Media/Video.php index 3338b51..d6852a2 100644 --- a/src/FFMpeg/Media/Video.php +++ b/src/FFMpeg/Media/Video.php @@ -185,10 +185,12 @@ class Video extends Audio /** * Gets the waveform of the video. * + * @param integer $width + * @param integer $height * @return Waveform */ - public function waveform() + public function waveform($width = 640, $height = 120) { - return new Waveform($this, $this->driver, $this->ffprobe); + return new Waveform($this, $this->driver, $this->ffprobe, $width, $height); } } diff --git a/src/FFMpeg/Media/Waveform.php b/src/FFMpeg/Media/Waveform.php index 8adf2be..062d006 100644 --- a/src/FFMpeg/Media/Waveform.php +++ b/src/FFMpeg/Media/Waveform.php @@ -23,11 +23,15 @@ class Waveform extends AbstractMediaType { /** @var Video */ private $video; + private $width; + private $height; - public function __construct(Video $video, FFMpegDriver $driver, FFProbe $ffprobe) + public function __construct(Video $video, FFMpegDriver $driver, FFProbe $ffprobe, $width, $height) { parent::__construct($video->getPathfile(), $driver, $ffprobe); $this->video = $video; + $this->width = $width; + $this->height = $height; } /** @@ -79,6 +83,7 @@ class Waveform extends AbstractMediaType */ $commands = array( '-i', 'input', '-filter_complex', + 'showwavespic=s='.$this->width.'x'.$this->height, '-frames:v', '1', $this->pathfile ); From 4c0b6f35959acd6c04352179bda8b520605bbb48 Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 16 Nov 2016 12:49:33 -0300 Subject: [PATCH 05/12] Fixed a bug in the way the input file is passed to the waveform request --- src/FFMpeg/Media/Waveform.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/FFMpeg/Media/Waveform.php b/src/FFMpeg/Media/Waveform.php index 062d006..feb26b3 100644 --- a/src/FFMpeg/Media/Waveform.php +++ b/src/FFMpeg/Media/Waveform.php @@ -82,10 +82,9 @@ class Waveform extends AbstractMediaType * @see http://ffmpeg.org/ffmpeg.html#Main-options */ $commands = array( - '-i', 'input', '-filter_complex', + '-i', $this->pathfile, '-filter_complex', 'showwavespic=s='.$this->width.'x'.$this->height, - '-frames:v', '1', - $this->pathfile + '-frames:v', '1' ); foreach ($this->filters as $filter) { From 7ce571119a192f797d1a0c4071f4391455160258 Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 16 Nov 2016 12:55:48 -0300 Subject: [PATCH 06/12] The waveform filter can only be applied to audio files --- src/FFMpeg/Media/Audio.php | 12 ++++++++++++ src/FFMpeg/Media/Video.php | 12 ------------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/FFMpeg/Media/Audio.php b/src/FFMpeg/Media/Audio.php index 25c8961..19f3478 100644 --- a/src/FFMpeg/Media/Audio.php +++ b/src/FFMpeg/Media/Audio.php @@ -102,4 +102,16 @@ class Audio extends AbstractStreamableMedia return $this; } + + /** + * Gets the waveform of the video. + * + * @param integer $width + * @param integer $height + * @return Waveform + */ + public function waveform($width = 640, $height = 120) + { + return new Waveform($this, $this->driver, $this->ffprobe, $width, $height); + } } diff --git a/src/FFMpeg/Media/Video.php b/src/FFMpeg/Media/Video.php index d6852a2..9200f49 100644 --- a/src/FFMpeg/Media/Video.php +++ b/src/FFMpeg/Media/Video.php @@ -181,16 +181,4 @@ class Video extends Audio { return new Frame($this, $this->driver, $this->ffprobe, $at); } - - /** - * Gets the waveform of the video. - * - * @param integer $width - * @param integer $height - * @return Waveform - */ - public function waveform($width = 640, $height = 120) - { - return new Waveform($this, $this->driver, $this->ffprobe, $width, $height); - } } From dab2ae5a8c0719f79d9b0ecd2d71b95f785cfc5c Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 16 Nov 2016 13:15:27 -0300 Subject: [PATCH 07/12] Improvements in the way we deal with filters for the waveform --- .../Filters/Waveform/WaveformRatioFixerFilter.php | 14 ++++---------- src/FFMpeg/Media/Waveform.php | 2 +- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/FFMpeg/Filters/Waveform/WaveformRatioFixerFilter.php b/src/FFMpeg/Filters/Waveform/WaveformRatioFixerFilter.php index ec40205..368b6bd 100644 --- a/src/FFMpeg/Filters/Waveform/WaveformRatioFixerFilter.php +++ b/src/FFMpeg/Filters/Waveform/WaveformRatioFixerFilter.php @@ -41,19 +41,13 @@ class WaveformRatioFixerFilter implements WaveformFilterInterface $dimensions = null; $commands = array(); - foreach ($waveform->getVideo()->getStreams() as $stream) { - if ($stream->isVideo()) { + foreach ($waveform->getAudio()->getStreams() as $stream) { + if ($stream->isAudio()) { try { - // Get the dimensions of the video - $dimensions = $stream->getDimensions(); - // If the downmix parameter is set to TRUE, we add an option to the FFMPEG command - if(!$this->downmix) { - $commands[] = '"showwavespic=s=' . $dimensions->getWidth() . 'x' . $dimensions->getHeight().'"'; - } - else { - $commands[] = '"aformat=channel_layouts=mono,showwavespic=s=' . $dimensions->getWidth() . 'x' . $dimensions->getHeight().'"'; + if($this->downmix == TRUE) { + $commands[] = '"aformat=channel_layouts=mono"'; } break; diff --git a/src/FFMpeg/Media/Waveform.php b/src/FFMpeg/Media/Waveform.php index feb26b3..e34f564 100644 --- a/src/FFMpeg/Media/Waveform.php +++ b/src/FFMpeg/Media/Waveform.php @@ -26,7 +26,7 @@ class Waveform extends AbstractMediaType private $width; private $height; - public function __construct(Video $video, FFMpegDriver $driver, FFProbe $ffprobe, $width, $height) + public function __construct(Audio $audio, FFMpegDriver $driver, FFProbe $ffprobe, $width, $height) { parent::__construct($video->getPathfile(), $driver, $ffprobe); $this->video = $video; From a32fa06ac46db16413ab23ce9a4dcab9f315da6c Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 16 Nov 2016 13:19:05 -0300 Subject: [PATCH 08/12] Fixed an error in a variable and method of the waveform Class --- src/FFMpeg/Media/Waveform.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/FFMpeg/Media/Waveform.php b/src/FFMpeg/Media/Waveform.php index e34f564..b1ca160 100644 --- a/src/FFMpeg/Media/Waveform.php +++ b/src/FFMpeg/Media/Waveform.php @@ -22,26 +22,26 @@ use FFMpeg\Coordinate\TimeCode; class Waveform extends AbstractMediaType { /** @var Video */ - private $video; + private $audio; private $width; private $height; public function __construct(Audio $audio, FFMpegDriver $driver, FFProbe $ffprobe, $width, $height) { parent::__construct($video->getPathfile(), $driver, $ffprobe); - $this->video = $video; + $this->audio = $audio; $this->width = $width; $this->height = $height; } /** - * Returns the video related to the waveform. + * Returns the audio related to the waveform. * - * @return Video + * @return Audio */ - public function getVideo() + public function getAudio() { - return $this->video; + return $this->audio; } /** From a331632725a2af91fb74de6b2e8cc890f50300d2 Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 16 Nov 2016 13:20:48 -0300 Subject: [PATCH 09/12] Fixed an error in a variable and method of the waveform Class --- src/FFMpeg/Media/Waveform.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FFMpeg/Media/Waveform.php b/src/FFMpeg/Media/Waveform.php index b1ca160..1794890 100644 --- a/src/FFMpeg/Media/Waveform.php +++ b/src/FFMpeg/Media/Waveform.php @@ -28,7 +28,7 @@ class Waveform extends AbstractMediaType public function __construct(Audio $audio, FFMpegDriver $driver, FFProbe $ffprobe, $width, $height) { - parent::__construct($video->getPathfile(), $driver, $ffprobe); + parent::__construct($audio->getPathfile(), $driver, $ffprobe); $this->audio = $audio; $this->width = $width; $this->height = $height; From e1625f1f949fa00fa515fc2df81b5a2bea50637f Mon Sep 17 00:00:00 2001 From: Romain Biard Date: Wed, 16 Nov 2016 14:11:11 -0300 Subject: [PATCH 10/12] Modification of the filters --- README.md | 38 +- docs/source/API/API/FFMpeg/Media/Audio.html | 63 ++ .../source/API/API/FFMpeg/Media/Waveform.html | 621 ++++++++++++++++++ sami.phar | Bin 0 -> 2213889 bytes ...erFilter.php => WaveformDownmixFilter.php} | 16 +- .../Filters/Waveform/WaveformFilters.php | 9 +- .../Waveform/WaveformDownmixFilterTest.php | 28 + .../Filters/Waveform/WaveformFiltersTest.php | 21 + tests/Unit/Media/WaveformTest.php | 12 +- 9 files changed, 794 insertions(+), 14 deletions(-) create mode 100644 docs/source/API/API/FFMpeg/Media/Waveform.html create mode 100644 sami.phar rename src/FFMpeg/Filters/Waveform/{WaveformRatioFixerFilter.php => WaveformDownmixFilter.php} (79%) create mode 100644 tests/Unit/Filters/Waveform/WaveformDownmixFilterTest.php create mode 100644 tests/Unit/Filters/Waveform/WaveformFiltersTest.php diff --git a/README.md b/README.md index a8a0f12..3f7cc1f 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,7 @@ below for more informations. You can extract a frame at any timecode using the `FFMpeg\Media\Video::frame` method. -This code return a `FFMpeg\Media\Frame` instance corresponding to the second 42. +This code returns a `FFMpeg\Media\Frame` instance corresponding to the second 42. You can pass any `FFMpeg\Coordinate\TimeCode` as argument, see dedicated documentation below for more information. @@ -145,6 +145,42 @@ $frame = $video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(42)); $frame->save('image.jpg'); ``` +##### Generate a waveform + +You can generate a waveform of an audio file using the `FFMpeg\Media\Audio::waveform` +method. + +This code returns a `FFMpeg\Media\Waveform` instance. +You can optionally pass dimensions as arguments, see dedicated +documentation below for more information. + +The ouput file MUST use the PNG extension. + +```php +$waveform = $audio->waveform(640, 120); +$waveform->save('waveform.png'); +``` + +If you want to get a waveform from a video, convert it in an audio file first. + +```php +// Open your video file +$video = $ffmpeg->open( 'video.mp4' ); + +// Set an audio format +$audio_format = new FFMpeg\Format\Audio\Mp3(); + +// Extract the audio into a new file +$video->save('audio.mp3'); + +// Set the audio file +$audio = $ffmpeg->open( 'audio.mp3' ); + +// Create the waveform +$waveform = $audio->waveform(); +$waveform->save( 'waveform.png' ); +``` + ##### Filters You can apply filters on `FFMpeg\Media\Video` with the `FFMpeg\Media\Video::addFilter` diff --git a/docs/source/API/API/FFMpeg/Media/Audio.html b/docs/source/API/API/FFMpeg/Media/Audio.html index 3a8be2c..afdb3fe 100644 --- a/docs/source/API/API/FFMpeg/Media/Audio.html +++ b/docs/source/API/API/FFMpeg/Media/Audio.html @@ -171,6 +171,16 @@

Exports the audio in the desired format, applies registered filters.

+ + + + +
stringinteger
+ Audio + + waveform(integer $width, integer $height) +

Generates an image file representing the waveform of the audio file.

+
@@ -609,6 +619,59 @@
+

+
at line 113
+ public Audio + save(FormatInterface $format, string $outputPathfile) +

+
+

Exports the audio in the desired format, applies registered filters.

+

+

+
+

Parameters

+ + + + + + + + + + + + +
FormatInterface$format +
string$outputPathfile +
+ + +

Return Value

+ + + + + + +
Audio +
+ + +

Exceptions

+ + + + + + +
RuntimeException +
+ + +
+
+