From 475d1a508a5360c96324c59858fb151c73514a33 Mon Sep 17 00:00:00 2001 From: sylvainv Date: Mon, 28 Jul 2014 17:27:12 +0800 Subject: [PATCH] Added watermark functionality and unit tests --- src/FFMpeg/Filters/Video/VideoFilters.php | 13 +++ src/FFMpeg/Filters/Video/WatermarkFilter.php | 81 ++++++++++++++++++ .../Filters/Video/WatermarkFilterTest.php | 63 ++++++++++++++ tests/files/waternark.png | Bin 0 -> 3244 bytes 4 files changed, 157 insertions(+) create mode 100644 src/FFMpeg/Filters/Video/WatermarkFilter.php create mode 100644 tests/FFMpeg/Tests/Filters/Video/WatermarkFilterTest.php create mode 100644 tests/files/waternark.png diff --git a/src/FFMpeg/Filters/Video/VideoFilters.php b/src/FFMpeg/Filters/Video/VideoFilters.php index 88f6207..91c929d 100644 --- a/src/FFMpeg/Filters/Video/VideoFilters.php +++ b/src/FFMpeg/Filters/Video/VideoFilters.php @@ -103,4 +103,17 @@ class VideoFilters extends AudioFilters return $this; } + + /** + * @param string $imagePath + * @param array $coordinates + * + * @return $this + */ + public function watermark($imagePath, array $coordinates = array()) + { + $this->media->addFilter(new WatermarkFilter($imagePath, $coordinates)); + + return $this; + } } diff --git a/src/FFMpeg/Filters/Video/WatermarkFilter.php b/src/FFMpeg/Filters/Video/WatermarkFilter.php new file mode 100644 index 0000000..065f177 --- /dev/null +++ b/src/FFMpeg/Filters/Video/WatermarkFilter.php @@ -0,0 +1,81 @@ + + * + * 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\Format\VideoInterface; +use FFMpeg\Media\Video; +use FFMpeg\Coordinate\TimeCode; + +class WatermarkFilter implements VideoFilterInterface +{ + /** @var string */ + private $watermarkPath; + /** @var array */ + private $coordinates; + /** @var integer */ + private $priority; + + + public function __construct($watermarkPath, array $coordinates = array(), $priority = 0) + { + $this->watermarkPath = $watermarkPath; + $this->coordinates = $coordinates; + $this->priority = $priority; + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return $this->priority; + } + + /** + * {@inheritdoc} + */ + public function apply(Video $video, VideoInterface $format) + { + $position = isset($this->coordinates['position']) ? $this->coordinates['position'] : 'absolute'; + + switch($position) { + case 'relative': + if (isset($this->coordinates['top'])) { + $y = $this->coordinates['top']; + } + elseif (isset($this->coordinates['bottom'])) { + $y = sprintf('main_h - %d - overlay_h', $this->coordinates['bottom']); + } + else { + $y = 0; + } + + if (isset($this->coordinates['left'])) { + $x = $this->coordinates['left']; + } + elseif (isset($this->coordinates['right'])) { + $x = sprintf('main_w - %d - overlay_w', $this->coordinates['right']); + } + else { + $x = 0; + } + + break; + default: + $x = isset($this->coordinates['x']) ? $this->coordinates['x'] : 0; + $y = isset($this->coordinates['y']) ? $this->coordinates['y'] : 0; + break; + } + + return array('-vf', sprintf('overlay %s:%s', $x, $y)); + } +} diff --git a/tests/FFMpeg/Tests/Filters/Video/WatermarkFilterTest.php b/tests/FFMpeg/Tests/Filters/Video/WatermarkFilterTest.php new file mode 100644 index 0000000..82fb3e1 --- /dev/null +++ b/tests/FFMpeg/Tests/Filters/Video/WatermarkFilterTest.php @@ -0,0 +1,63 @@ + 320, 'height' => 240, 'codec_type' => 'video')); + $streams = new StreamCollection(array($stream)); + + $video = $this->getVideoMock(); + + $format = $this->getMock('FFMpeg\Format\VideoInterface'); + + $filter = new WatermarkFilter(__DIR__ . '/../../files/watermark.png'); + $this->assertEquals(array('-vf', 'overlay 0:0'), $filter->apply($video, $format)); + + // check size of video is unchanged + $this->assertEquals(320, $stream->get('width')); + $this->assertEquals(240, $stream->get('height')); + } + + public function testDifferentCoordinaates() + { + $video = $this->getVideoMock(); + $format = $this->getMock('FFMpeg\Format\VideoInterface'); + + // test position absolute + $filter = new WatermarkFilter(__DIR__ . '/../../files/watermark.png', array( + 'position' => 'absolute', + 'x' => 10, 'y' => 5 + )); + $this->assertEquals(array('-vf', 'overlay 10:5'), $filter->apply($video, $format)); + + // test position relative + $filter = new WatermarkFilter(__DIR__ . '/../../files/watermark.png', array( + 'position' => 'relative', + 'bottom' => 10, 'left' => 5 + )); + $this->assertEquals(array('-vf', 'overlay 5:main_h - 10 - overlay_h'), $filter->apply($video, $format)); + + // test position relative + $filter = new WatermarkFilter(__DIR__ . '/../../files/watermark.png', array( + 'position' => 'relative', + 'bottom' => 5, 'right' => 4 + )); + $this->assertEquals(array('-vf', 'overlay main_w - 4 - overlay_w:main_h - 5 - overlay_h'), $filter->apply($video, $format)); + + // test position relative + $filter = new WatermarkFilter(__DIR__ . '/../../files/watermark.png', array( + 'position' => 'relative', + 'left' => 5, 'top' => 11 + )); + $this->assertEquals(array('-vf', 'overlay 5:11'), $filter->apply($video, $format)); + } +} diff --git a/tests/files/waternark.png b/tests/files/waternark.png new file mode 100644 index 0000000000000000000000000000000000000000..0c96e5480efee31b2caa19d3da9d371351c56252 GIT binary patch literal 3244 zcmc&xYg7{l8XcMuMo5Q=g7Qk8;1jh1$_gftFa!~NP<*YZED#=|(k^1Ap@A*pq$Z%$ z(29acWKfF_TmmWz76ri-6&YqN8nl`c6*4M_6pPk!mYx~+)b*dI$8+|anRDiw@4NSY z_kOvN5eq-Gce4io;KT5+kmUei^PGJlTL1uBZ~e3b001xHz>00tgNS(KY~P$3B15|NZs4elr3J-;BIF z`f-%UtWIr zr-c4k|J`?cH%JiueiL~&)wgm-@VDzfLGeBz?>phQyuRC_|DU6{-1<@<7Ztm-^ppA8 z=^tf)cJqq@V>9`y>Wc$qnS6pO3fvzk%i#Mx-!M{EpDO*}AKihKrRD95^)@#$>qcJW zk#mlYl(#3aWj$9`#U5#Q(A(U|s2)k@6V%hI&((dtLE_Z%_Ol=H2cdY@zkI$Ju`tyA;q4YqDZN1+_#;4TCD}!YzBF3+~5$>>b zc@YuH%8sBlm0C~c)60~kKw%VO$tzUmGJa+sB;J2&5PlMy*H<%<`IMq0ClZW8Y${); zj&s#57T`^3_iU*Luci_aVYa?qQrlt#Z<@Vk^k7kBC_S*yzJ8b>SCkqB7C+f1BIa-x z=~&VOco7k9mG>JJm0x%=hZC&Az(kgEvZVi+h!xy;Tdhm?t{u7~z;B!!giWmL!&U@2 zqzrSyj<{Do@|kW55a8$H!!*lW*9Oy%b{$(BnqcpWwM_7THpYR7h`x}O=#;fSn0{2u z3(jl8B0bhizvfV zHI<;AMfZy&CSL*G>DqJroo}RL9&eA+mBP;*n7>McIFFZ}0ku`+TWvJb^ zojWx9AhA==HRPXl;#^WbS!LeX-A2_42>52F`p6!uWUv_$uS~KU#(D2z7dd*JlGLz^ zlnHcuj{eKC7!Iq1 z#9$XXHf3I1E-6PU-Kq;_K+YjcKXv$sy&Q+Tei8h=72v7XAD%p_~xl&syBQ)hJWt9BbUt z-0lO3C-neM{vHJ(v}oSyg3Wsbm@dLa;9AI1i{q_dMzhA4Ji`m$*oW--Xje)9gMk$e z1Z>z6u*n0KdouJqQ{gM?IZp!S`S{$BX@Vg!zX{yXu;f3UOqV_|=2j3ba*u5tYH9a^ z&Mj=r_9%I*=jqu`GWxT}x*54B!>3+`WewfI=!;aQU2lzsY+k1_D;x4}r`Tb-v%U4! z?x|xD{AIR$)vo~^5CPlO4Hf88bSSgAK=G}V&)Y^ehnLGA%(>@4!10#v96({H<;mUJ z;h7&0@Tqy5oeMQPQD*bF)d%mV)gYj7obTE(y7MXokGf7}da$|*XGyo_Lq7F z(W1$^26I{z0t%Na=eK?yh~P}Njk89AGIZ`YQzMq%CrHgv^*$R=81Fiek}UJjCgtg& zQkR|}6cXbb4_BkX&{7^HC>zz2DUCjkfXB36jumsIdL|QhTZGU@etYBfh%zcgpY)E$I-2>MO*$BI` zmmHeO4NaWgSN|j1i?~uX_;;4OR<3=m+sOaMaX*KnkO6TKhg%}BTgS@r972j$a&kDb zj9sMBUT~r346A>_$$}QM!({fy#vL5q{!aY$?q4X@Rb$$$qVigxE&&HsvZDVV{7apz z!kB=+ST?btgxz0xnj^^dc(s;0PyY2XO)5A2mARpqyGmH^CTUNpf%T5oRH#kf>0JML z)(a?(|6-Q6_xw@7v#kt}P4WN&1|Tu}pnue_f4#2XjG)Z_jJzL6;!p#?1DbwIs+VVl RR|5b5gfEB)sSJ)Ieh1?P-