@@ -9,6 +9,7 @@ namespace FFMpegCore.Test
99 public class ArgumentBuilderTest
1010 {
1111 private readonly string [ ] _concatFiles = { "1.mp4" , "2.mp4" , "3.mp4" , "4.mp4" } ;
12+ private readonly string [ ] _multiFiles = { "1.mp3" , "2.mp3" , "3.mp3" , "4.mp3" } ;
1213
1314 [ TestMethod ]
1415 public void Builder_BuildString_IO_1 ( )
@@ -571,5 +572,126 @@ public void Builder_BuildString_GifPalette_NullSize_FpsSupplied()
571572 -i "input.mp4" -filter_complex "[{ streamIndex } :v] fps=10,split [a][b];[a] palettegen=max_colors=32 [p];[b][p] paletteuse=dither=bayer" "output.gif"
572573 """ , str ) ;
573574 }
575+
576+ [ TestMethod ]
577+ public void Builder_BuildString_MultiOutput ( )
578+ {
579+ var str = FFMpegArguments . FromFileInput ( "input.mp4" )
580+ . MultiOutput ( args => args
581+ . OutputToFile ( "output.mp4" , overwrite : true , args => args . CopyChannel ( ) )
582+ . OutputToFile ( "output.ts" , overwrite : false , args => args . CopyChannel ( ) . ForceFormat ( "mpegts" ) )
583+ . OutputToUrl ( "http://server/path" , options => options . ForceFormat ( "webm" ) ) )
584+ . Arguments ;
585+ Assert . AreEqual ( $ """
586+ -i "input.mp4" -c:a copy -c:v copy "output.mp4" -y -c:a copy -c:v copy -f mpegts "output.ts" -f webm http://server/path
587+ """ , str ) ;
588+ }
589+
590+ [ TestMethod ]
591+ public void Builder_BuildString_MBROutput ( )
592+ {
593+ var str = FFMpegArguments . FromFileInput ( "input.mp4" )
594+ . MultiOutput ( args => args
595+ . OutputToFile ( "sd.mp4" , overwrite : true , args => args . Resize ( 1200 , 720 ) )
596+ . OutputToFile ( "hd.mp4" , overwrite : false , args => args . Resize ( 1920 , 1080 ) ) )
597+ . Arguments ;
598+ Assert . AreEqual ( $ """
599+ -i "input.mp4" -s 1200x720 "sd.mp4" -y -s 1920x1080 "hd.mp4"
600+ """ , str ) ;
601+ }
602+
603+ [ TestMethod ]
604+ public void Builder_BuildString_TeeOutput ( )
605+ {
606+ var str = FFMpegArguments . FromFileInput ( "input.mp4" )
607+ . OutputToTee ( args => args
608+ . OutputToFile ( "output.mp4" , overwrite : false , args => args . WithFastStart ( ) )
609+ . OutputToUrl ( "http://server/path" , options => options . ForceFormat ( "mpegts" ) . SelectStream ( 0 , channel : Channel . Video ) ) )
610+ . Arguments ;
611+ Assert . AreEqual ( $ """
612+ -i "input.mp4" -f tee "[movflags=faststart]output.mp4|[f=mpegts:select=\'0:v:0\']http://server/path"
613+ """ , str ) ;
614+ }
615+ [ TestMethod ]
616+ public void Builder_BuildString_MultiInput ( )
617+ {
618+ var audioStreams = string . Join ( "" , _multiFiles . Select ( ( item , index ) => $ "[{ index } :0]") ) ;
619+ var mixFilter = $ "{ audioStreams } amix=inputs={ _multiFiles . Length } :duration=longest:dropout_transition=1:normalize=0[final]";
620+ var ffmpegArgs = $ "-filter_complex \" { mixFilter } \" -map \" [final]\" ";
621+ var str = FFMpegArguments
622+ . FromFileInput ( _multiFiles )
623+ . OutputToFile ( "output.mp3" , overwrite : true , options => options
624+ . WithCustomArgument ( ffmpegArgs )
625+ . WithAudioCodec ( AudioCodec . LibMp3Lame ) // Set the audio codec to MP3
626+ . WithAudioBitrate ( 128 ) // Set the bitrate to 128kbps
627+ . WithAudioSamplingRate ( 48000 ) // Set the sample rate to 48kHz
628+ . WithoutMetadata ( ) // Remove metadata
629+ . WithCustomArgument ( "-ac 2 -write_xing 0 -id3v2_version 0" ) ) // Force 2 Channels
630+ . Arguments ;
631+ Assert . AreEqual ( $ "-i \" 1.mp3\" -i \" 2.mp3\" -i \" 3.mp3\" -i \" 4.mp3\" -filter_complex \" [0:0][1:0][2:0][3:0]amix=inputs=4:duration=longest:dropout_transition=1:normalize=0[final]\" -map \" [final]\" -c:a libmp3lame -b:a 128k -ar 48000 -map_metadata -1 -ac 2 -write_xing 0 -id3v2_version 0 \" output.mp3\" -y", str ) ;
632+ }
633+ [ TestMethod ]
634+ public void Pre_VerifyExists_AllFilesExist ( )
635+ {
636+ // Arrange
637+ var filePaths = new List < string >
638+ {
639+ Path . GetTempFileName ( ) ,
640+ Path . GetTempFileName ( ) ,
641+ Path . GetTempFileName ( )
642+ } ;
643+ var argument = new MultiInputArgument ( true , filePaths ) ;
644+ try
645+ {
646+ // Act & Assert
647+ argument . Pre ( ) ; // No exception should be thrown
648+ }
649+ finally
650+ {
651+ // Cleanup
652+ foreach ( var filePath in filePaths )
653+ {
654+ File . Delete ( filePath ) ;
655+ }
656+ }
657+ }
658+
659+ [ TestMethod ]
660+ public void Pre_VerifyExists_SomeFilesNotExist ( )
661+ {
662+ // Arrange
663+ var filePaths = new List < string >
664+ {
665+ Path . GetTempFileName ( ) ,
666+ "file2.mp4" ,
667+ "file3.mp4"
668+ } ;
669+ var argument = new MultiInputArgument ( true , filePaths ) ;
670+ try
671+ {
672+ // Act & Assert
673+ Assert . ThrowsException < FileNotFoundException > ( ( ) => argument . Pre ( ) ) ;
674+ }
675+ finally
676+ {
677+ // Cleanup
678+ File . Delete ( filePaths [ 0 ] ) ;
679+ }
680+ }
681+
682+ [ TestMethod ]
683+ public void Pre_VerifyExists_NoFilesExist ( )
684+ {
685+ // Arrange
686+ var filePaths = new List < string >
687+ {
688+ "file1.mp4" ,
689+ "file2.mp4" ,
690+ "file3.mp4"
691+ } ;
692+ var argument = new MultiInputArgument ( true , filePaths ) ;
693+ // Act & Assert
694+ Assert . ThrowsException < FileNotFoundException > ( ( ) => argument . Pre ( ) ) ;
695+ }
574696 }
575697}
0 commit comments