From 70ca5bf0501a97a45664b874b876cadbe7b18ab1 Mon Sep 17 00:00:00 2001 From: Jason Dove Date: Mon, 31 Jan 2022 14:07:12 -0600 Subject: [PATCH] fix bug with watermark and short content (#608) --- .../FFmpeg/WatermarkCalculatorTests.cs | 26 +++++ ErsatzTV.Core/FFmpeg/FFmpegProcessBuilder.cs | 101 ++++++++++-------- 2 files changed, 84 insertions(+), 43 deletions(-) create mode 100644 ErsatzTV.Core.Tests/FFmpeg/WatermarkCalculatorTests.cs diff --git a/ErsatzTV.Core.Tests/FFmpeg/WatermarkCalculatorTests.cs b/ErsatzTV.Core.Tests/FFmpeg/WatermarkCalculatorTests.cs new file mode 100644 index 000000000..c5fa2aa47 --- /dev/null +++ b/ErsatzTV.Core.Tests/FFmpeg/WatermarkCalculatorTests.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using ErsatzTV.Core.FFmpeg; +using FluentAssertions; +using NUnit.Framework; +using static LanguageExt.Prelude; + +namespace ErsatzTV.Core.Tests.FFmpeg; + +[TestFixture] +public class WatermarkCalculatorTests +{ + [Test] + public void EntireVideoBetweenWatermarks_ShouldReturn_EmptyFadePointList() + { + List actual = WatermarkCalculator.CalculateFadePoints( + new DateTimeOffset(2022, 01, 31, 13, 34, 00, TimeSpan.FromHours(-5)), + TimeSpan.Zero, + TimeSpan.FromMinutes(5), + None, + 15, + 10); + + actual.Should().HaveCount(0); + } +} diff --git a/ErsatzTV.Core/FFmpeg/FFmpegProcessBuilder.cs b/ErsatzTV.Core/FFmpeg/FFmpegProcessBuilder.cs index 7aeddbd3d..2b941df3a 100644 --- a/ErsatzTV.Core/FFmpeg/FFmpegProcessBuilder.cs +++ b/ErsatzTV.Core/FFmpeg/FFmpegProcessBuilder.cs @@ -219,34 +219,43 @@ namespace ErsatzTV.Core.FFmpeg Option> maybeFadePoints, IDisplaySize resolution) { - foreach (WatermarkOptions options in watermarkOptions) + ChannelWatermarkMode maybeWatermarkMode = watermarkOptions.Map(wmo => wmo.Watermark.Map(wm => wm.Mode)).Flatten() + .IfNone(ChannelWatermarkMode.None); + + // skip watermark if intermittent and no fade points + if (maybeWatermarkMode != ChannelWatermarkMode.None && + (maybeWatermarkMode != ChannelWatermarkMode.Intermittent || + maybeFadePoints.Map(fp => fp.Count > 0).IfNone(false))) { - foreach (string path in options.ImagePath) + foreach (WatermarkOptions options in watermarkOptions) { - if (options.IsAnimated) - { - _arguments.Add("-ignore_loop"); - _arguments.Add("0"); - } - - // when we have fade points, we need to loop the static watermark image - else if (maybeFadePoints.Map(fp => fp.Count).IfNone(0) > 0) + foreach (string path in options.ImagePath) { - _arguments.Add("-stream_loop"); - _arguments.Add("-1"); + if (options.IsAnimated) + { + _arguments.Add("-ignore_loop"); + _arguments.Add("0"); + } + + // when we have fade points, we need to loop the static watermark image + else if (maybeFadePoints.Map(fp => fp.Count).IfNone(0) > 0) + { + _arguments.Add("-stream_loop"); + _arguments.Add("-1"); + } + + _arguments.Add("-i"); + _arguments.Add(path); + + _complexFilterBuilder = _complexFilterBuilder.WithWatermark( + options.Watermark, + maybeFadePoints, + resolution, + options.ImageStreamIndex); } - - _arguments.Add("-i"); - _arguments.Add(path); - - _complexFilterBuilder = _complexFilterBuilder.WithWatermark( - options.Watermark, - maybeFadePoints, - resolution, - options.ImageStreamIndex); } } - + return this; } @@ -400,27 +409,7 @@ namespace ErsatzTV.Core.FFmpeg public FFmpegProcessBuilder WithHls(string channelNumber, Option mediaVersion, long ptsOffset, Option maybeTimeScale) { const int SEGMENT_SECONDS = 4; - - var frameRate = 24; - - foreach (MediaVersion version in mediaVersion) - { - if (!int.TryParse(version.RFrameRate, out int fr)) - { - string[] split = (version.RFrameRate ?? string.Empty).Split("/"); - if (int.TryParse(split[0], out int left) && int.TryParse(split[1], out int right)) - { - fr = (int)Math.Round(left / (double)right); - } - else - { - _logger.LogInformation("Unable to detect framerate, using {FrameRate}", 24); - fr = 24; - } - } - - frameRate = fr; - } + int frameRate = GetFrameRateFromMediaVersion(mediaVersion); foreach (int timescale in maybeTimeScale) { @@ -701,5 +690,31 @@ namespace ErsatzTV.Core.FFmpeg StartInfo = startInfo }; } + + private int GetFrameRateFromMediaVersion(Option mediaVersion) + { + var frameRate = 24; + + foreach (MediaVersion version in mediaVersion) + { + if (!int.TryParse(version.RFrameRate, out int fr)) + { + string[] split = (version.RFrameRate ?? string.Empty).Split("/"); + if (int.TryParse(split[0], out int left) && int.TryParse(split[1], out int right)) + { + fr = (int)Math.Round(left / (double)right); + } + else + { + _logger.LogInformation("Unable to detect framerate, using {FrameRate}", 24); + fr = 24; + } + } + + frameRate = fr; + } + + return frameRate; + } } }