HLSPlaylistExporterTest.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. <?php
  2. namespace Pbmedia\LaravelFFMpeg\Tests;
  3. use FFMpeg\Filters\Audio\SimpleFilter;
  4. use FFMpeg\Format\AudioInterface;
  5. use FFMpeg\Media\Audio;
  6. use Mockery;
  7. use Pbmedia\LaravelFFMpeg\HLSPlaylistExporter;
  8. use Pbmedia\LaravelFFMpeg\Media;
  9. use Pbmedia\LaravelFFMpeg\SegmentedExporter;
  10. class HLSPlaylistExporterTest extends TestCase
  11. {
  12. public function testSortingFormats()
  13. {
  14. $file = $this->getVideoMedia()->getFile();
  15. $media = Mockery::mock(Media::class);
  16. $media->shouldReceive('getFile')->once()->andReturn($file);
  17. $formatA = new \FFMpeg\Format\Video\X264;
  18. $formatB = new \FFMpeg\Format\Video\X264;
  19. $formatC = new \FFMpeg\Format\Video\X264;
  20. $formatA->setKiloBitrate(1024);
  21. $formatB->setKiloBitrate(64);
  22. $formatC->setKiloBitrate(256);
  23. $exporter = new HLSPlaylistExporter($media);
  24. $exporter->addFormat($formatA)
  25. ->addFormat($formatB)
  26. ->addFormat($formatC);
  27. $this->assertEquals($formatB, $exporter->getFormatsSorted()[0]); // 64
  28. $this->assertEquals($formatC, $exporter->getFormatsSorted()[1]); // 256
  29. $this->assertEquals($formatA, $exporter->getFormatsSorted()[2]); // 1024
  30. }
  31. public function testSegmentExporters()
  32. {
  33. $file = $this->getVideoMedia()->getFile();
  34. $media = Mockery::mock(Media::class);
  35. $media->shouldReceive('getFile')->once()->andReturn($file);
  36. $playlist = 'MyPlaylist.m3u8';
  37. $formatA = (new \FFMpeg\Format\Video\X264)->setKiloBitrate(384);
  38. $formatB = (new \FFMpeg\Format\Video\X264)->setKiloBitrate(512);
  39. $exporter = new HLSPlaylistExporter($media);
  40. $exporter->addFormat($formatA)
  41. ->addFormat($formatB)
  42. ->setPlaylistPath($playlist)
  43. ->setSegmentLength(15);
  44. $segmentedExporters = $exporter->getSegmentedExporters();
  45. $this->assertCount(2, $segmentedExporters);
  46. $this->assertInstanceOf(SegmentedExporter::class, $segmentedExporters[0]);
  47. $this->assertInstanceOf(SegmentedExporter::class, $segmentedExporters[1]);
  48. $this->assertEquals($formatA, $segmentedExporters[0]->getFormat());
  49. $this->assertEquals($formatB, $segmentedExporters[1]->getFormat());
  50. $this->assertEquals(15, $segmentedExporters[1]->getFilter()->getSegmentLength());
  51. $this->assertEquals(15, $segmentedExporters[1]->getFilter()->getSegmentLength());
  52. }
  53. public function testProgressCallbackOfSegmentExporters()
  54. {
  55. $file = $this->getVideoMedia()->getFile();
  56. $media = Mockery::mock(Media::class);
  57. $media->shouldReceive('getFile')->once()->andReturn($file);
  58. $playlist = 'MyPlaylist.m3u8';
  59. $formatA = (new \FFMpeg\Format\Video\X264)->setKiloBitrate(384);
  60. $formatB = (new \FFMpeg\Format\Video\X264)->setKiloBitrate(512);
  61. $totalPercentage = 0;
  62. $HLSExporter = new HLSPlaylistExporter($media);
  63. $segmentedExporters = $HLSExporter->addFormat($formatA)
  64. ->addFormat($formatB)
  65. ->onProgress(function ($percentage) use (&$totalPercentage) {
  66. $totalPercentage = $percentage;
  67. })
  68. ->prepareSegmentedExporters()
  69. ->getSegmentedExporters();
  70. $segmentedExporters[0]->getFormat()->emit('progress', [
  71. $file, $formatA, 30,
  72. ]);
  73. $this->assertEquals(15, $totalPercentage);
  74. $segmentedExporters[1]->getFormat()->emit('progress', [
  75. $file, $formatA, 60,
  76. ]);
  77. $this->assertEquals(80, $totalPercentage);
  78. }
  79. public function testSegmentExportersWithCallback()
  80. {
  81. $media = $this->getVideoMedia();
  82. $formatA = (new \FFMpeg\Format\Video\X264)->setKiloBitrate(384);
  83. $formatB = (new \FFMpeg\Format\Video\X264)->setKiloBitrate(512);
  84. $exporter = new HLSPlaylistExporter($media);
  85. $exporter->addFormat($formatA)
  86. ->addFormat($formatB, function ($media) {
  87. $this->assertInstanceOf(Media::class, $media);
  88. $media->addFilter(['-i', '0']);
  89. });
  90. $segmentedExporters = $exporter->getSegmentedExporters();
  91. $this->assertEquals($formatA, $segmentedExporters[0]->getFormat());
  92. $this->assertEquals($formatB, $segmentedExporters[1]->getFormat());
  93. $this->assertCount(0, $segmentedExporters[0]->getMedia()->getFiltersCollection());
  94. $this->assertCount(1, $segmentedExporters[1]->getMedia()->getFiltersCollection());
  95. $filter = $segmentedExporters[1]->getMedia()->getFiltersCollection()->getIterator()[0];
  96. $this->assertInstanceOf(SimpleFilter::class, $filter);
  97. $this->assertEquals(['-i', 0], $filter->apply(
  98. Mockery::mock(Audio::class),
  99. Mockery::mock(AudioInterface::class)
  100. ));
  101. }
  102. public function testCreationOfPlaylist()
  103. {
  104. $file = $this->getVideoMedia()->getFile();
  105. $media = Mockery::mock(Media::class);
  106. $media->shouldReceive('getFile')->once()->andReturn($file);
  107. $playlist = 'MyPlaylist.m3u8';
  108. $formatA = (new \FFMpeg\Format\Video\X264)->setKiloBitrate(384);
  109. $formatB = (new \FFMpeg\Format\Video\X264)->setKiloBitrate(512);
  110. $media->shouldReceive('addFilter')->once();
  111. $media->shouldReceive('save')->once()->withArgs([
  112. $formatA, $this->srcDir . '/MyPlaylist_384_%05d.ts',
  113. ]);
  114. $media->shouldReceive('save')->once()->withArgs([
  115. $formatB, $this->srcDir . '/MyPlaylist_512_%05d.ts',
  116. ]);
  117. $exporter = new HLSPlaylistExporter($media);
  118. $exporter->addFormat($formatA)
  119. ->addFormat($formatB)
  120. ->setPlaylistPath($playlist)
  121. ->setSegmentLength(15);
  122. $exporter->toDisk('local')->save($playlist);
  123. $this->assertEquals(file_get_contents($this->srcDir . '/MyPlaylist.m3u8'),
  124. '#EXTM3U' . PHP_EOL .
  125. '#EXT-X-STREAM-INF:BANDWIDTH=384000' . PHP_EOL .
  126. 'MyPlaylist_384.m3u8' . PHP_EOL .
  127. '#EXT-X-STREAM-INF:BANDWIDTH=512000' . PHP_EOL .
  128. 'MyPlaylist_512.m3u8'
  129. );
  130. @unlink($this->srcDir . '/MyPlaylist.m3u8');
  131. }
  132. public function testDisableSortingOfFormats()
  133. {
  134. $file = $this->getVideoMedia()->getFile();
  135. $media = Mockery::mock(Media::class);
  136. $media->shouldReceive('getFile')->once()->andReturn($file);
  137. $playlist = 'MyPlaylist.m3u8';
  138. $formatA = (new \FFMpeg\Format\Video\X264)->setKiloBitrate(384);
  139. $formatB = (new \FFMpeg\Format\Video\X264)->setKiloBitrate(512);
  140. $media->shouldReceive('addFilter')->once();
  141. $media->shouldReceive('save')->once()->withArgs([
  142. $formatA, $this->srcDir . '/MyPlaylist_384_%05d.ts',
  143. ]);
  144. $media->shouldReceive('save')->once()->withArgs([
  145. $formatB, $this->srcDir . '/MyPlaylist_512_%05d.ts',
  146. ]);
  147. $exporter = new HLSPlaylistExporter($media);
  148. $exporter->addFormat($formatB)
  149. ->addFormat($formatA)
  150. ->dontSortFormats()
  151. ->setPlaylistPath($playlist)
  152. ->setSegmentLength(15);
  153. $exporter->toDisk('local')->save($playlist);
  154. $this->assertEquals(file_get_contents($this->srcDir . '/MyPlaylist.m3u8'),
  155. '#EXTM3U' . PHP_EOL .
  156. '#EXT-X-STREAM-INF:BANDWIDTH=512000' . PHP_EOL .
  157. 'MyPlaylist_512.m3u8' . PHP_EOL .
  158. '#EXT-X-STREAM-INF:BANDWIDTH=384000' . PHP_EOL .
  159. 'MyPlaylist_384.m3u8'
  160. );
  161. @unlink($this->srcDir . '/MyPlaylist.m3u8');
  162. }
  163. }