* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ use DanielSiepmann\Videcutting\Cutting; use DanielSiepmann\Videcutting\VideoInfo; use PHPUnit\Framework\TestCase; use Symfony\Component\Process\Process; /** * @covers DanielSiepmann\Videcutting\Cutting */ class CuttingTest extends TestCase { /** * @test */ public function instanceCanBeCreated(): void { $video = $this->createStub(VideoInfo::class); $subject = new Cutting( $video ); static::assertInstanceOf(Cutting::class, $subject); } /** * @test */ public function generatesCommandsForCuttingWithoutAds(): void { $video = $this->createStub(VideoInfo::class); $video->method('getStart')->willReturn('10.05.20'); $video->method('getEnd')->willReturn('13.10.25'); $video->method('getAds')->willReturn([]); $video->method('getOriginalFilename')->willReturn('Some-Video.mp4'); $video->method('getOriginalFilenameWithSuffix')->willReturn('Some-Video-cut-1.mp4'); $subject = new Cutting( $video ); $commands = []; foreach ($subject->getCommandsForCutting() as $command) { $commands[] = $command; } static::assertCount(1, $commands); static::assertSame( "ffmpeg -y -ss '10.05.20' -to '13.10.25' -i 'Some-Video.mp4' -c copy '" . sys_get_temp_dir() . "/Some-Video-cut-1.mp4'", $commands[0]->getCommandLine() ); } /** * @test */ public function generatesCommandsForCuttingWithAds(): void { $video = $this->createStub(VideoInfo::class); $video->method('getStart')->willReturn('1:05.20'); $video->method('getEnd')->willReturn('13:10.25'); $video->method('getAds')->willReturn([ ['2:10', '3:05'], ['10:07', '11:10'], ]); $video->method('getOriginalFilename')->willReturn('Some-Video.mp4'); $video->method('getOriginalFilenameWithSuffix')->willReturnOnConsecutiveCalls( 'Some-Video-cut-1.mp4', 'Some-Video-cut-2.mp4', 'Some-Video-cut-3.mp4', ); $subject = new Cutting( $video ); $commands = []; foreach ($subject->getCommandsForCutting() as $command) { $commands[] = $command; } static::assertCount(3, $commands, 'Did not get expected number of cutting commands'); static::assertSame( "ffmpeg -y -ss '1:05.20' -to '2:10' -i 'Some-Video.mp4' -c copy '" . sys_get_temp_dir() . "/Some-Video-cut-1.mp4'", $commands[0]->getCommandLine() ); static::assertSame( "ffmpeg -y -ss '3:05' -to '10:07' -i 'Some-Video.mp4' -c copy '" . sys_get_temp_dir() . "/Some-Video-cut-2.mp4'", $commands[1]->getCommandLine() ); static::assertSame( "ffmpeg -y -ss '11:10' -to '13:10.25' -i 'Some-Video.mp4' -c copy '" . sys_get_temp_dir() . "/Some-Video-cut-3.mp4'", $commands[2]->getCommandLine() ); } /** * @test */ public function generatesCommandForGeneratingMetadata(): void { $video = $this->createStub(VideoInfo::class); $video->method('getOriginalFilename')->willReturn('Some-Video.mp4'); $video->method('getOriginalFilenameWithSuffix')->willReturn('Some-Video-metadata.mp4'); $subject = new Cutting( $video ); $command = $subject->getCommandForGeneratingMetadata(); static::assertSame( "ffmpeg -y -i 'Some-Video.mp4' -f ffmetadata '" . sys_get_temp_dir() . "/Some-Video-metadata.txt'", $command->getCommandLine() ); } /** * @test */ public function throwsExceptionForGeneratingConcatInputFileIfNoConcatIsAvailable(): void { $video = $this->createStub(VideoInfo::class); $subject = new Cutting( $video ); $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('No temp files for concat available. Did you call "getCommandsForCutting()" before?'); $this->expectExceptionCode(1601455216); $subject->getCommandForGeneratingConcatInputFile(); } /** * @test */ public function generatesCommandsForGeneratingConcatInputFileWithNoAds(): void { $video = $this->createStub(VideoInfo::class); $video->method('getStart')->willReturn('10.05.20'); $video->method('getEnd')->willReturn('13.10.25'); $video->method('getAds')->willReturn([]); $video->method('getOriginalFilename')->willReturn('Some-Video.mp4'); $video->method('getOriginalFilenameWithSuffix')->willReturnOnConsecutiveCalls( 'Some-Video-cut-1.mp4', 'Some-Video-concat.mp4' ); $subject = new Cutting( $video ); foreach ($subject->getCommandsForCutting() as $command) { // Just generate all commands to have proper internal state } $command = $subject->getCommandForGeneratingConcatInputFile(); static::assertSame( "printf 'file " . sys_get_temp_dir() . "/Some-Video-cut-1.mp4' > " . sys_get_temp_dir() . "/Some-Video-concat.txt", $command->getCommandLine() ); } /** * @test */ public function generatesCommandsForGeneratingConcatInputFileWithAds(): void { $video = $this->createStub(VideoInfo::class); $video->method('getStart')->willReturn('10.05.20'); $video->method('getEnd')->willReturn('13.10.25'); $video->method('getAds')->willReturn([ ['2:10', '3:05'], ['10:07', '11:10'], ]); $video->method('getOriginalFilename')->willReturn('Some-Video.mp4'); $video->method('getOriginalFilenameWithSuffix')->willReturnOnConsecutiveCalls( 'Some-Video-cut-1.mp4', 'Some-Video-cut-2.mp4', 'Some-Video-cut-3.mp4', 'Some-Video-concat.mp4' ); $subject = new Cutting( $video ); foreach ($subject->getCommandsForCutting() as $command) { // Just generate all commands to have proper internal state } $command = $subject->getCommandForGeneratingConcatInputFile(); static::assertSame( 'printf \'file ' . sys_get_temp_dir() . '/Some-Video-cut-1.mp4\nfile ' . sys_get_temp_dir() . '/Some-Video-cut-2.mp4\nfile ' . sys_get_temp_dir() . '/Some-Video-cut-3.mp4\'' . ' > ' . sys_get_temp_dir() . '/Some-Video-concat.txt', $command->getCommandLine() ); } /** * @test */ public function generatesCommandForGeneratingVideoWithCustomTitle(): void { $video = $this->createStub(VideoInfo::class); $video->method('getTargetFilePath')->willReturn('Series-Name/Series-01/10-episode title.mp4'); $video->method('getOriginalFilenameWithSuffix')->willReturnOnConsecutiveCalls( 'Series-Name_Series-01_episode-title-01-concat.mp4', 'Series-Name_Series-01_episode-title-01-metadata.mp4' ); $video->method('getTitleForHumans')->willReturn('01 - Episode Title'); $subject = new Cutting( $video ); $command = $subject->getCommandForGeneratingVideo(); static::assertSame( 'ffmpeg -y -f concat -safe 0 -i \'' . sys_get_temp_dir() . '/Series-Name_Series-01_episode-title-01-concat.txt\' -c copy' . ' -f ffmetadata -i \'' . sys_get_temp_dir() . '/Series-Name_Series-01_episode-title-01-metadata.txt\' -c copy -map_metadata 1' . ' -metadata Title=\'01 - Episode Title\'' . ' \'Series-Name/Series-01/10-episode title.mp4\'', $command->getCommandLine() ); } /** * @test */ public function generatesCommandForCleanup(): void { $video = $this->createStub(VideoInfo::class); $video->method('getTargetFilePath')->willReturn('Series-Name/Series-01/10-episode title.mp4'); $video->method('getOriginalFilenameWithSuffix')->willReturnOnConsecutiveCalls( 'Series-Name_Series-01_episode-title-01-concat.mp4', 'Series-Name_Series-01_episode-title-01-metadata.mp4' ); $subject = new Cutting( $video ); $command = $subject->getCommandForCleanup(); static::assertSame( 'rm \'' . sys_get_temp_dir() . '/Series-Name_Series-01_episode-title-01-concat.txt\' \'' . sys_get_temp_dir() . '/Series-Name_Series-01_episode-title-01-metadata.txt\'', $command->getCommandLine() ); } /** * @test */ public function generatesCommandForCleanupWithSingleTempFile(): void { $video = $this->createStub(VideoInfo::class); $video->method('getStart')->willReturn('10.05.20'); $video->method('getEnd')->willReturn('13.10.25'); $video->method('getAds')->willReturn([]); $video->method('getOriginalFilename')->willReturn('Some-Video.mp4'); $video->method('getTargetFilePath')->willReturn('Series-Name/Series-01/10-episode title.mp4'); $video->method('getOriginalFilenameWithSuffix')->willReturnOnConsecutiveCalls( 'Some-Video-cut-1.mp4', 'Series-Name_Series-01_episode-title-01-concat.mp4', 'Series-Name_Series-01_episode-title-01-metadata.mp4' ); $subject = new Cutting( $video ); foreach ($subject->getCommandsForCutting() as $command) { // Just generate all commands to have proper internal state } $command = $subject->getCommandForCleanup(); static::assertSame( 'rm \'' . sys_get_temp_dir() . '/Some-Video-cut-1.mp4\' \'' . sys_get_temp_dir() . '/Series-Name_Series-01_episode-title-01-concat.txt\' \'' . sys_get_temp_dir() . '/Series-Name_Series-01_episode-title-01-metadata.txt\'', $command->getCommandLine() ); } }