AudioVideoTest.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. <?php
  2. namespace Pbmedia\LaravelFFMpeg\Tests;
  3. use FFMpeg\Coordinate\Dimension;
  4. use FFMpeg\Coordinate\TimeCode;
  5. use FFMpeg\Driver\FFMpegDriver;
  6. use FFMpeg\Filters\Audio\SimpleFilter;
  7. use FFMpeg\Filters\Video\ClipFilter;
  8. use FFMpeg\Format\AudioInterface;
  9. use FFMpeg\Media\Audio;
  10. use FFMpeg\Media\Video;
  11. use Illuminate\Config\Repository as ConfigRepository;
  12. use Illuminate\Contracts\Filesystem\Factory as Filesystems;
  13. use Illuminate\Contracts\Filesystem\Filesystem;
  14. use Illuminate\Filesystem\FilesystemAdapter;
  15. use Illuminate\Log\Logger as Writer;
  16. use Illuminate\Support\Fluent;
  17. use League\Flysystem\AdapterInterface;
  18. use League\Flysystem\FilesystemInterface;
  19. use Mockery;
  20. use Monolog\Logger;
  21. use Pbmedia\LaravelFFMpeg\Disk;
  22. use Pbmedia\LaravelFFMpeg\FFMpeg;
  23. use Pbmedia\LaravelFFMpeg\File;
  24. use Pbmedia\LaravelFFMpeg\Media;
  25. use Pbmedia\LaravelFFMpeg\MediaExporter;
  26. class AudioVideoTest extends TestCase
  27. {
  28. public function testInstantiationOfService()
  29. {
  30. $service = $this->getService();
  31. $this->assertInstanceOf(Filesystems::class, $service->getFilesystems());
  32. }
  33. public function testMediaClass()
  34. {
  35. $media = $this->getGuitarMedia();
  36. $this->assertInstanceOf(Media::class, $media);
  37. $this->assertFalse($media->isFrame());
  38. }
  39. public function testFileClass()
  40. {
  41. $media = $this->getGuitarMedia();
  42. $file = $media->getFile();
  43. $this->assertInstanceOf(File::class, $file);
  44. $this->assertEquals($file->getPath(), 'guitar.m4a');
  45. $this->assertEquals($file->getFullPath(), $this->srcDir . '/guitar.m4a');
  46. }
  47. public function testDurationInSeconds()
  48. {
  49. $media = $this->getGuitarMedia();
  50. $this->assertEquals(4, $media->getDurationInSeconds());
  51. }
  52. public function testDurationInMiliseconds()
  53. {
  54. $media = $this->getGuitarMedia();
  55. $this->assertEquals(4053.3330000000001, $media->getDurationInMiliseconds());
  56. }
  57. public function testDiskClass()
  58. {
  59. $media = $this->getGuitarMedia();
  60. $file = $media->getFile();
  61. $disk = $file->getDisk();
  62. $this->assertInstanceOf(Disk::class, $disk);
  63. $this->assertEquals($disk->getPath(), $this->srcDir . '/');
  64. }
  65. public function testAddingAFilterWithAClosure()
  66. {
  67. $media = $this->getVideoMedia();
  68. $this->assertCount(0, $media->getFiltersCollection());
  69. $media->addFilter(function ($filters) {
  70. $filters->resize(new Dimension(640, 480));
  71. });
  72. $this->assertCount(1, $media->getFiltersCollection());
  73. }
  74. public function testAddingAFilterWithAnObject()
  75. {
  76. $media = $this->getVideoMedia();
  77. $this->assertCount(0, $media->getFiltersCollection());
  78. $media->addFilter(new ClipFilter(TimeCode::fromSeconds(5)));
  79. $this->assertCount(1, $media->getFiltersCollection());
  80. }
  81. public function testAddingASimpleFilterWithStringArguments()
  82. {
  83. $media = $this->getVideoMedia();
  84. $this->assertCount(0, $media->getFiltersCollection());
  85. $media->addFilter('-i', '0');
  86. $this->assertCount(1, $media->getFiltersCollection());
  87. $filter = $media->getFiltersCollection()->getIterator()[0];
  88. $this->assertInstanceOf(SimpleFilter::class, $filter);
  89. $this->assertEquals(['-i', 0], $filter->apply(
  90. Mockery::mock(Audio::class),
  91. Mockery::mock(AudioInterface::class)
  92. ));
  93. }
  94. public function testAddingASimpleFilterWithArrayArgument()
  95. {
  96. $media = $this->getVideoMedia();
  97. $this->assertCount(0, $media->getFiltersCollection());
  98. $media->addFilter(['-i', '0']);
  99. $this->assertCount(1, $media->getFiltersCollection());
  100. $filter = $media->getFiltersCollection()->getIterator()[0];
  101. $this->assertInstanceOf(SimpleFilter::class, $filter);
  102. $this->assertEquals(['-i', 0], $filter->apply(
  103. Mockery::mock(Audio::class),
  104. Mockery::mock(AudioInterface::class)
  105. ));
  106. }
  107. public function testMultipleSimpleFiltersCanBeApplied()
  108. {
  109. $media = $this->getGuitarMedia()
  110. ->addFilter('-some_simple')
  111. ->addFilter('added_filter');
  112. $media->setFFMpegDriver($driver = Mockery::mock(FFMpegDriver::class));
  113. $driver->shouldReceive('getConfiguration')->andReturn(new Fluent);
  114. $driver->shouldReceive('command')->with([
  115. 0 => '-y',
  116. 1 => '-i',
  117. 2 => $this->srcDir . '/guitar.m4a',
  118. 3 => '-some_simple',
  119. 4 => 'added_filter',
  120. 5 => '-threads',
  121. 6 => null,
  122. 7 => '-acodec',
  123. 8 => 'libfdk_aac',
  124. 9 => '-b:a',
  125. 10 => '128k',
  126. 11 => 'example.aac',
  127. ], false, \Mockery::type('array'));
  128. $media->save(new \FFMpeg\Format\Audio\Aac, 'example.aac');
  129. }
  130. public function testExportingToLocalDisk()
  131. {
  132. $media = $this->getGuitarMedia();
  133. $exporter = $media->export();
  134. $this->assertInstanceOf(MediaExporter::class, $exporter);
  135. $file = $media->getFile();
  136. $format = new \FFMpeg\Format\Audio\Aac;
  137. $media = Mockery::mock(Media::class);
  138. $media->shouldReceive('getFile')->once()->andReturn($file);
  139. $media->shouldReceive('isFrame')->once()->andReturn(false);
  140. $media->shouldReceive('save')->once()->withArgs([
  141. $format, $this->srcDir . '/guitar_aac.aac',
  142. ]);
  143. $exporter = new MediaExporter($media);
  144. $exporter->inFormat($format)->toDisk('local')->save('guitar_aac.aac');
  145. }
  146. public function testOpeningFromRemoteDisk()
  147. {
  148. $filesystems = Mockery::mock(Filesystems::class);
  149. $config = Mockery::mock(ConfigRepository::class);
  150. $logger = new Writer(new Logger('ffmpeg'));
  151. $adapter = Mockery::mock(AdapterInterface::class);
  152. $driver = Mockery::mock(FilesystemInterface::class);
  153. $driver->shouldReceive('getAdapter')->andReturn($adapter);
  154. $remoteDisk = Mockery::mock(FilesystemAdapter::class);
  155. $remoteDisk->shouldReceive('getDriver')->andReturn($driver);
  156. $remoteDisk->shouldReceive('read')->with('remote_guitar.m4a')->andReturn(
  157. $videoContents = file_get_contents(__DIR__ . '/src/guitar.m4a')
  158. );
  159. $localDisk = $this->getLocalAdapter();
  160. $filesystems->shouldReceive('disk')->once()->with('s3')->andReturn($remoteDisk);
  161. $filesystems->shouldReceive('disk')->once()->with('local')->andReturn($localDisk);
  162. $config->shouldReceive('get')->once()->with('laravel-ffmpeg')->andReturn(array_merge($this->getDefaultConfig(), ['default_disk' => 's3']));
  163. $config->shouldReceive('get')->once()->with('filesystems.default')->andReturn('s3');
  164. $service = new FFMpeg($filesystems, $config, $logger);
  165. $media = $service->open('remote_guitar.m4a');
  166. $format = new \FFMpeg\Format\Audio\Aac;
  167. $media->export()
  168. ->inFormat($format)
  169. ->toDisk('local')
  170. ->save('local_guitar.m4a');
  171. $this->assertFileExists(__DIR__ . '/src/local_guitar.m4a');
  172. @unlink($this->srcDir . '/local_guitar.m4a');
  173. }
  174. public function testExportingToRemoteDisk()
  175. {
  176. $this->remoteFilesystem = true;
  177. $guitarFile = $this->getGuitarMedia()->getFile();
  178. $baseMedia = Mockery::mock(Video::class);
  179. $baseMedia->shouldReceive('save')->once();
  180. $media = new Media($guitarFile, $baseMedia);
  181. $exporter = new MediaExporter($media);
  182. $mockedRemoteDisk = Mockery::mock(Disk::class);
  183. $remoteFile = new File($mockedRemoteDisk, 'guitar_aac.aac');
  184. $remoteFileMocked = Mockery::mock(File::class);
  185. $remoteFileMocked->shouldReceive('getPath')->once()->andReturn($remoteFile->getPath());
  186. $remoteFileMocked->shouldReceive('getDisk')->once()->andReturn($remoteFile->getDisk());
  187. $remoteFileMocked->shouldReceive('getExtension')->once()->andReturn($remoteFile->getExtension());
  188. $remoteFileMocked->shouldReceive('put')->once()->andReturn(true);
  189. $mockedRemoteDisk->shouldReceive('isLocal')->once()->andReturn(false);
  190. $mockedRemoteDisk->shouldReceive('newFile')->once()->withArgs(['guitar_aac.aac'])->andReturn($remoteFileMocked);
  191. $format = new \FFMpeg\Format\Audio\Aac;
  192. $exporter->inFormat($format)->toDisk($mockedRemoteDisk)->save('guitar_aac.aac');
  193. }
  194. public function testExportingToRemoteDiskWithPublicVisibility()
  195. {
  196. $this->remoteFilesystem = true;
  197. $guitarFile = $this->getGuitarMedia()->getFile();
  198. $baseMedia = Mockery::mock(Video::class);
  199. $baseMedia->shouldReceive('save')->once();
  200. $media = new Media($guitarFile, $baseMedia);
  201. $exporter = new MediaExporter($media);
  202. $mockedRemoteDisk = Mockery::mock(Disk::class);
  203. $remoteFile = new File($mockedRemoteDisk, 'guitar_aac.aac');
  204. $remoteFileMocked = Mockery::mock(File::class);
  205. $remoteFileMocked->shouldReceive('getPath')->once()->andReturn($remoteFile->getPath());
  206. $remoteFileMocked->shouldReceive('getDisk')->once()->andReturn($remoteFile->getDisk());
  207. $remoteFileMocked->shouldReceive('getExtension')->once()->andReturn($remoteFile->getExtension());
  208. $remoteFileMocked->shouldReceive('put')->once()->andReturn(true);
  209. $mockedRemoteDisk->shouldReceive('isLocal')->once()->andReturn(false);
  210. $mockedRemoteDisk->shouldReceive('newFile')->once()->withArgs(['guitar_aac.aac'])->andReturn($remoteFileMocked);
  211. $mockedRemoteDisk->shouldReceive('setVisibility')->once()->withArgs(['guitar_aac.aac', Filesystem::VISIBILITY_PUBLIC]);
  212. $format = new \FFMpeg\Format\Audio\Aac;
  213. $exporter->inFormat($format)
  214. ->toDisk($mockedRemoteDisk)
  215. ->withVisibility(Filesystem::VISIBILITY_PUBLIC)
  216. ->save('guitar_aac.aac');
  217. }
  218. public function testCreatingAndUnlinkingOfTemporaryFiles()
  219. {
  220. $newTemporaryFile = FFMpeg::newTemporaryFile();
  221. file_put_contents($newTemporaryFile, 'test');
  222. $this->assertFileExists($newTemporaryFile);
  223. $this->assertEquals('test', file_get_contents($newTemporaryFile));
  224. $service = $this->getService()->cleanupTemporaryFiles();
  225. $this->assertFileNotExists($newTemporaryFile);
  226. }
  227. }