diff --git a/.gitignore b/.gitignore index 7d052cb..4f3f707 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ composer.phar composer.lock phpunit.xml sami.phar +.idea/ \ No newline at end of file diff --git a/README.md b/README.md index e826dbb..79259d4 100644 --- a/README.md +++ b/README.md @@ -159,13 +159,13 @@ You can generate a waveform of an audio file using the `FFMpeg\Media\Audio::wave method. This code returns a `FFMpeg\Media\Waveform` instance. -You can optionally pass dimensions as arguments, see dedicated +You can optionally pass dimensions as the first two arguments and an array of hex string colors for ffmpeg to use for the waveform, see dedicated documentation below for more information. The ouput file MUST use the PNG extension. ```php -$waveform = $audio->waveform(640, 120); +$waveform = $audio->waveform(640, 120, array('#00FF00')); $waveform->save('waveform.png'); ``` diff --git a/src/FFMpeg/Media/Audio.php b/src/FFMpeg/Media/Audio.php index 29d2c89..c8fddb4 100644 --- a/src/FFMpeg/Media/Audio.php +++ b/src/FFMpeg/Media/Audio.php @@ -132,10 +132,11 @@ class Audio extends AbstractStreamableMedia * * @param integer $width * @param integer $height + * @param array $colors Array of colors for ffmpeg to use. Color format is #000000 (RGB hex string with #) * @return Waveform */ - public function waveform($width = 640, $height = 120) + public function waveform($width = 640, $height = 120, $colors = array(Waveform::DEFAULT_COLOR)) { - return new Waveform($this, $this->driver, $this->ffprobe, $width, $height); + return new Waveform($this, $this->driver, $this->ffprobe, $width, $height, $colors); } } diff --git a/src/FFMpeg/Media/Waveform.php b/src/FFMpeg/Media/Waveform.php index 0954c00..94f1907 100644 --- a/src/FFMpeg/Media/Waveform.php +++ b/src/FFMpeg/Media/Waveform.php @@ -12,6 +12,7 @@ namespace FFMpeg\Media; use Alchemy\BinaryDriver\Exception\ExecutionFailureException; +use FFMpeg\Exception\InvalidArgumentException; use FFMpeg\Filters\Waveform\WaveformFilterInterface; use FFMpeg\Filters\Waveform\WaveformFilters; use FFMpeg\Driver\FFMpegDriver; @@ -20,17 +21,26 @@ use FFMpeg\Exception\RuntimeException; class Waveform extends AbstractMediaType { - /** @var Video */ - private $audio; - private $width; - private $height; + const DEFAULT_COLOR = '#000000'; - public function __construct(Audio $audio, FFMpegDriver $driver, FFProbe $ffprobe, $width, $height) + /** @var Video */ + protected $audio; + protected $width; + protected $height; + + /** + * @var array + */ + protected $colors; + + public function __construct(Audio $audio, FFMpegDriver $driver, FFProbe $ffprobe, $width, $height, $colors = array(self::DEFAULT_COLOR)) { parent::__construct($audio->getPathfile(), $driver, $ffprobe); $this->audio = $audio; $this->width = $width; $this->height = $height; + + $this->setColors($colors); } /** @@ -65,6 +75,55 @@ class Waveform extends AbstractMediaType return $this; } + /** + * Parameter should be an array containing at least one valid color represented as a HTML color string. For + * example #FFFFFF or #000000. By default the color is set to black. Keep in mind that if you save the waveform + * as jpg file, it will appear completely black and to avoid this you can set the waveform color to white (#FFFFFF). + * Saving waveforms to png is strongly suggested. + * + * @param array $colors + */ + public function setColors(array $colors) + { + foreach ($colors as $row => $value) + { + if (!preg_match('/^#(?:[0-9a-fA-F]{6})$/', $value)) + { + //invalid color + //unset($colors[$row]); + + throw new InvalidArgumentException("The provided color '$value' is invalid"); + } + } + + if (count($colors)) + { + $this->colors = $colors; + } + } + + /** + * Returns an array of colors that will be passed to ffmpeg to use for waveform generation. Colors are applied ONLY + * to the waveform. Background cannot be controlled that easily and it is probably easier to save the waveform + * as a transparent png file and then add background of choice. + * + * @return array + */ + public function getColors() + { + return $this->colors; + } + + /** + * Compiles the selected colors into a string, using a pipe separator. + * + * @return string + */ + protected function compileColors() + { + return implode('|', $this->colors); + } + /** * Saves the waveform in the given filename. * @@ -81,8 +140,8 @@ class Waveform extends AbstractMediaType * @see http://ffmpeg.org/ffmpeg.html#Main-options */ $commands = array( - '-i', $this->pathfile, '-filter_complex', - 'showwavespic=s='.$this->width.'x'.$this->height, + '-y', '-i', $this->pathfile, '-filter_complex', + 'showwavespic=colors='.$this->compileColors().':s='.$this->width.'x'.$this->height, '-frames:v', '1' ); diff --git a/tests/Unit/Media/WaveformTest.php b/tests/Unit/Media/WaveformTest.php index cd4f08f..5d13c2e 100644 --- a/tests/Unit/Media/WaveformTest.php +++ b/tests/Unit/Media/WaveformTest.php @@ -52,7 +52,7 @@ class WaveformTest extends AbstractMediaTestCase ->method('command') ->with($commands); - $waveform = new Waveform($this->getAudioMock(__FILE__), $driver, $ffprobe, 640, 120); + $waveform = new Waveform($this->getAudioMock(__FILE__), $driver, $ffprobe, 640, 120, ['#FFFFFF']); $this->assertSame($waveform, $waveform->save($pathfile)); } @@ -61,8 +61,8 @@ class WaveformTest extends AbstractMediaTestCase return array( array( array( - '-i', NULL, '-filter_complex', - 'showwavespic=s=640x120', + '-y', '-i', NULL, '-filter_complex', + 'showwavespic=colors=#FFFFFF:s=640x120', '-frames:v', '1', ), ),