@ -4,6 +4,7 @@ using ErsatzTV.Core.FFmpeg;
@@ -4,6 +4,7 @@ using ErsatzTV.Core.FFmpeg;
using FluentAssertions ;
using LanguageExt ;
using NUnit.Framework ;
using static LanguageExt . Prelude ;
namespace ErsatzTV.Core.Tests.FFmpeg
{
@ -113,6 +114,161 @@ namespace ErsatzTV.Core.Tests.FFmpeg
@@ -113,6 +114,161 @@ namespace ErsatzTV.Core.Tests.FFmpeg
} ) ;
}
[Test]
[ TestCase (
false ,
false ,
false ,
ChannelWatermarkLocation . BottomLeft ,
false ,
1 0 0 ,
"[0:0][1:v]overlay=x=134:y=H-h-54[v]" ,
"0:1" ,
"[v]" ) ]
[ TestCase (
false ,
false ,
false ,
ChannelWatermarkLocation . BottomRight ,
false ,
1 0 0 ,
"[0:0][1:v]overlay=x=W-w-134:y=H-h-54[v]" ,
"0:1" ,
"[v]" ) ]
[ TestCase (
false ,
false ,
false ,
ChannelWatermarkLocation . TopLeft ,
false ,
1 0 0 ,
"[0:0][1:v]overlay=x=134:y=54[v]" ,
"0:1" ,
"[v]" ) ]
[ TestCase (
false ,
false ,
false ,
ChannelWatermarkLocation . TopRight ,
false ,
1 0 0 ,
"[0:0][1:v]overlay=x=W-w-134:y=54[v]" ,
"0:1" ,
"[v]" ) ]
[ TestCase (
false ,
false ,
true ,
ChannelWatermarkLocation . TopLeft ,
false ,
1 0 0 ,
"[0:0][1:v]overlay=x=134:y=54:enable='lt(mod(mod(time(0),60*60),10*60),15)'[v]" ,
"0:1" ,
"[v]" ) ]
[ TestCase (
false ,
false ,
false ,
ChannelWatermarkLocation . TopLeft ,
true ,
1 0 0 ,
"[1:v]scale=384:-1[wmp];[0:0][wmp]overlay=x=134:y=54[v]" ,
"0:1" ,
"[v]" ) ]
[ TestCase (
false ,
false ,
false ,
ChannelWatermarkLocation . TopLeft ,
false ,
9 0 ,
"[1:v]format=yuva420p|yuva444p|yuva422p|rgba|abgr|bgra|gbrap|ya8,colorchannelmixer=aa=0.90[wmp];[0:0][wmp]overlay=x=134:y=54[v]" ,
"0:1" ,
"[v]" ) ]
[ TestCase (
false ,
true ,
false ,
ChannelWatermarkLocation . TopLeft ,
false ,
1 0 0 ,
"[0:0]yadif=1[vt];[vt][1:v]overlay=x=134:y=54[v]" ,
"0:1" ,
"[v]" ) ]
[ TestCase (
false ,
true ,
false ,
ChannelWatermarkLocation . TopLeft ,
true ,
1 0 0 ,
"[0:0]yadif=1[vt];[1:v]scale=384:-1[wmp];[vt][wmp]overlay=x=134:y=54[v]" ,
"0:1" ,
"[v]" ) ]
[ TestCase (
true ,
true ,
false ,
ChannelWatermarkLocation . TopLeft ,
false ,
1 0 0 ,
"[0:1]apad=whole_dur=3300000ms[a];[0:0]yadif=1[vt];[vt][1:v]overlay=x=134:y=54[v]" ,
"[a]" ,
"[v]" ) ]
[ TestCase (
true ,
false ,
false ,
ChannelWatermarkLocation . TopLeft ,
false ,
1 0 0 ,
"[0:1]apad=whole_dur=3300000ms[a];[0:0][1:v]overlay=x=134:y=54[v]" ,
"[a]" ,
"[v]" ) ]
public void Should_Return_Watermark (
bool alignAudio ,
bool deinterlace ,
bool intermittent ,
ChannelWatermarkLocation location ,
bool scaled ,
int opacity ,
string expectedVideoFilter ,
string expectedAudioLabel ,
string expectedVideoLabel )
{
FFmpegComplexFilterBuilder builder = new FFmpegComplexFilterBuilder ( )
. WithWatermark (
Some (
new ChannelWatermark
{
Mode = intermittent
? ChannelWatermarkMode . Intermittent
: ChannelWatermarkMode . Permanent ,
DurationSeconds = intermittent ? 1 5 : 0 ,
FrequencyMinutes = intermittent ? 1 0 : 0 ,
Location = location ,
Size = scaled ? ChannelWatermarkSize . Scaled : ChannelWatermarkSize . ActualSize ,
WidthPercent = scaled ? 2 0 : 0 ,
Opacity = opacity ,
HorizontalMarginPercent = 7 ,
VerticalMarginPercent = 5
} ) ,
new Resolution { Width = 1 9 2 0 , Height = 1 0 8 0 } )
. WithDeinterlace ( deinterlace )
. WithAlignedAudio ( alignAudio ? Some ( TimeSpan . FromMinutes ( 5 5 ) ) : None ) ;
Option < FFmpegComplexFilter > result = builder . Build ( 0 , 1 ) ;
result . IsSome . Should ( ) . BeTrue ( ) ;
result . IfSome (
filter = >
{
filter . ComplexFilter . Should ( ) . Be ( expectedVideoFilter ) ;
filter . AudioLabel . Should ( ) . Be ( expectedAudioLabel ) ;
filter . VideoLabel . Should ( ) . Be ( expectedVideoLabel ) ;
} ) ;
}
[Test]
[TestCase(true, false, false, "[0:0] deinterlace_qsv [ v ] ", " [ v ] ")]
[ TestCase (