diff --git a/.github/workflows/artifacts.yml b/.github/workflows/artifacts.yml index 88f0791f7..da918bd50 100644 --- a/.github/workflows/artifacts.yml +++ b/.github/workflows/artifacts.yml @@ -203,7 +203,7 @@ jobs: - name: Install dependencies run: dotnet restore -r "${{ matrix.target }}" - - uses: suisei-cn/actions-download-file@v1 + - uses: suisei-cn/actions-download-file@v1.3.0 if: ${{ matrix.kind == 'windows' }} id: downloadffmpeg name: Download ffmpeg diff --git a/CHANGELOG.md b/CHANGELOG.md index 79a597553..0e719265d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Fix fallback filler looping - Fix bug where some libraries would never scan - Fix filler ordering so post-roll is properly scheduled after padded mid-roll +- Fix pre/post-roll filler padding when used with mid-roll + - This caused overlapping schedule items, fallback filler that was too long, etc. ### Changed - Merge generated `Other Video` folder tags with tags from sidecar NFO diff --git a/ErsatzTV.Application/ErsatzTV.Application.csproj b/ErsatzTV.Application/ErsatzTV.Application.csproj index 0835a37aa..234ab9198 100644 --- a/ErsatzTV.Application/ErsatzTV.Application.csproj +++ b/ErsatzTV.Application/ErsatzTV.Application.csproj @@ -12,7 +12,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj b/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj index 05ee1dcbf..9a1badcf6 100644 --- a/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj +++ b/ErsatzTV.Core.Tests/ErsatzTV.Core.Tests.csproj @@ -10,14 +10,14 @@ - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerBaseTests.cs b/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerBaseTests.cs index f402dc10e..12bbc7703 100644 --- a/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerBaseTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/PlayoutModeSchedulerBaseTests.cs @@ -460,6 +460,110 @@ public class PlayoutModeSchedulerBaseTests : SchedulerTestBase playoutItems[4].MediaItemId.Should().Be(5); playoutItems[4].StartOffset.Should().Be(startState.CurrentTime + TimeSpan.FromMinutes(55)); } + + [Test] + public void Should_Schedule_Padded_Post_Roll_After_Mid_Roll_Count() + { + // content 45 min, mid roll 5 min, post roll pad to 60 + // content + mid = 50 min, post roll will add two 5 min items + // content + mid + post = 60 min + + Collection collectionOne = TwoItemCollection(1, 2, TimeSpan.FromMinutes(45)); + Collection collectionTwo = TwoItemCollection(3, 4, TimeSpan.FromMinutes(5)); + Collection collectionThree = TwoItemCollection(5, 6, TimeSpan.FromMinutes(5)); + + var scheduleItem = new ProgramScheduleItemOne + { + Id = 1, + Index = 1, + Collection = collectionOne, + CollectionId = collectionOne.Id, + StartTime = null, + PlaybackOrder = PlaybackOrder.Chronological, + TailFiller = null, + FallbackFiller = null, + MidRollFiller = new FillerPreset + { + FillerKind = FillerKind.MidRoll, + FillerMode = FillerMode.Count, + Count = 1, + CollectionId = 2, + Collection = collectionTwo + }, + PostRollFiller = new FillerPreset + { + FillerKind = FillerKind.PostRoll, + FillerMode = FillerMode.Pad, + PadToNearestMinute = 60, + CollectionId = 3, + Collection = collectionThree + } + }; + + var scheduleItemsEnumerator = new OrderedScheduleItemsEnumerator( + new List { scheduleItem }, + new CollectionEnumeratorState()); + + var enumerator = new ChronologicalMediaCollectionEnumerator( + collectionOne.MediaItems, + new CollectionEnumeratorState()); + + var midRollFillerEnumerator = new ChronologicalMediaCollectionEnumerator( + collectionTwo.MediaItems, + new CollectionEnumeratorState()); + + var postRollFillerEnumerator = new ChronologicalMediaCollectionEnumerator( + collectionThree.MediaItems, + new CollectionEnumeratorState()); + + PlayoutBuilderState startState = StartState(scheduleItemsEnumerator); + + Dictionary enumerators = CollectionEnumerators( + scheduleItem, + enumerator); + + enumerators.Add(CollectionKey.ForFillerPreset(scheduleItem.MidRollFiller), midRollFillerEnumerator); + enumerators.Add(CollectionKey.ForFillerPreset(scheduleItem.PostRollFiller), postRollFillerEnumerator); + + List playoutItems = Scheduler() + .AddFiller( + startState, + enumerators, + scheduleItem, + new PlayoutItem + { + MediaItemId = 1, + Start = startState.CurrentTime.UtcDateTime, + Finish = startState.CurrentTime.AddHours(1).UtcDateTime + }, + new List + { + new() { StartTime = TimeSpan.Zero, EndTime = TimeSpan.FromMinutes(6) }, + new() { StartTime = TimeSpan.FromMinutes(6), EndTime = TimeSpan.FromMinutes(45) } + }); + + playoutItems.Count.Should().Be(5); + + // content chapter 1 + playoutItems[0].MediaItemId.Should().Be(1); + playoutItems[0].StartOffset.Should().Be(startState.CurrentTime); + + // mid-roll 1 + playoutItems[1].MediaItemId.Should().Be(3); + playoutItems[1].StartOffset.Should().Be(startState.CurrentTime + TimeSpan.FromMinutes(6)); + + // content chapter 2 + playoutItems[2].MediaItemId.Should().Be(1); + playoutItems[2].StartOffset.Should().Be(startState.CurrentTime + TimeSpan.FromMinutes(11)); + + // post-roll 1 + playoutItems[3].MediaItemId.Should().Be(5); + playoutItems[3].StartOffset.Should().Be(startState.CurrentTime + TimeSpan.FromMinutes(50)); + + // post-roll 2 + playoutItems[4].MediaItemId.Should().Be(6); + playoutItems[4].StartOffset.Should().Be(startState.CurrentTime + TimeSpan.FromMinutes(55)); + } } [TestFixture] diff --git a/ErsatzTV.Core/ErsatzTV.Core.csproj b/ErsatzTV.Core/ErsatzTV.Core.csproj index a93e3b433..86cdf35c5 100644 --- a/ErsatzTV.Core/ErsatzTV.Core.csproj +++ b/ErsatzTV.Core/ErsatzTV.Core.csproj @@ -10,15 +10,15 @@ - - + + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerBase.cs b/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerBase.cs index a3b8ee1a3..3e1e50f58 100644 --- a/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerBase.cs +++ b/ErsatzTV.Core/Scheduling/PlayoutModeSchedulerBase.cs @@ -461,10 +461,14 @@ public abstract class PlayoutModeSchedulerBase : IPlayoutModeScheduler whe foreach (FillerPreset padFiller in Optional( allFiller.FirstOrDefault(f => f.FillerMode == FillerMode.Pad && f.PadToNearestMinute.HasValue))) { - var totalDuration = - TimeSpan.FromMilliseconds( - result.Sum(pi => (pi.Finish - pi.Start).TotalMilliseconds) + + var totalDuration = TimeSpan.FromMilliseconds(result.Sum(pi => (pi.Finish - pi.Start).TotalMilliseconds)); + + // add primary content to totalDuration only if it hasn't already been added + if (result.All(pi => pi.MediaItemId != playoutItem.MediaItemId)) + { + totalDuration += TimeSpan.FromMilliseconds( effectiveChapters.Sum(c => (c.EndTime - c.StartTime).TotalMilliseconds)); + } int currentMinute = (playoutItem.StartOffset + totalDuration).Minute; // ReSharper disable once PossibleInvalidOperationException diff --git a/ErsatzTV.FFmpeg/ErsatzTV.FFmpeg.csproj b/ErsatzTV.FFmpeg/ErsatzTV.FFmpeg.csproj index a759d92af..5c8e7e140 100644 --- a/ErsatzTV.FFmpeg/ErsatzTV.FFmpeg.csproj +++ b/ErsatzTV.FFmpeg/ErsatzTV.FFmpeg.csproj @@ -8,7 +8,7 @@ - + diff --git a/ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj b/ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj index 2efb8c78d..e2eb08145 100644 --- a/ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj +++ b/ErsatzTV.Infrastructure/ErsatzTV.Infrastructure.csproj @@ -21,14 +21,14 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj b/ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj index 439348d57..ed1174309 100644 --- a/ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj +++ b/ErsatzTV.Scanner.Tests/ErsatzTV.Scanner.Tests.csproj @@ -10,7 +10,7 @@ - + diff --git a/ErsatzTV.Scanner/ErsatzTV.Scanner.csproj b/ErsatzTV.Scanner/ErsatzTV.Scanner.csproj index 55ed59508..b8dad3f40 100644 --- a/ErsatzTV.Scanner/ErsatzTV.Scanner.csproj +++ b/ErsatzTV.Scanner/ErsatzTV.Scanner.csproj @@ -17,7 +17,7 @@ - + diff --git a/ErsatzTV/ErsatzTV.csproj b/ErsatzTV/ErsatzTV.csproj index 9617f4c2e..1f32155b9 100644 --- a/ErsatzTV/ErsatzTV.csproj +++ b/ErsatzTV/ErsatzTV.csproj @@ -57,7 +57,7 @@ - + @@ -68,7 +68,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive