aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiels van Velzen <nielsvanvelzen@users.noreply.github.com>2026-05-04 18:02:16 +0200
committerGitHub <noreply@github.com>2026-05-04 18:02:16 +0200
commitd87e9f96228ef8863426e2544cada67235186a18 (patch)
tree27b8250646842e313019505566925b37b2ff51dd
parent10de1ce8feff92bbb604fed6eb561256d449f809 (diff)
parent127d924c5bd004cb61bebc47a6474453408dcd5e (diff)
Merge pull request #16695 from ExpctING/fix_dummy_chapter
Fix dummy chapter handling for videos with a single chapter or short duration.
-rw-r--r--Emby.Server.Implementations/Chapters/ChapterManager.cs2
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs7
-rw-r--r--tests/Jellyfin.Providers.Tests/MediaInfo/FFProbeVideoInfoTests.cs21
3 files changed, 24 insertions, 6 deletions
diff --git a/Emby.Server.Implementations/Chapters/ChapterManager.cs b/Emby.Server.Implementations/Chapters/ChapterManager.cs
index 79ab29b87c..8a4721ce62 100644
--- a/Emby.Server.Implementations/Chapters/ChapterManager.cs
+++ b/Emby.Server.Implementations/Chapters/ChapterManager.cs
@@ -129,7 +129,7 @@ public class ChapterManager : IChapterManager
var averageChapterDuration = GetAverageDurationBetweenChapters(chapters);
var threshold = TimeSpan.FromSeconds(1).Ticks;
- if (averageChapterDuration < threshold)
+ if (chapters.Count >= 2 && averageChapterDuration < threshold)
{
_logger.LogInformation("Skipping chapter image extraction for {Video} as the average chapter duration {AverageDuration} was lower than the minimum threshold {Threshold}", video.Name, averageChapterDuration, threshold);
extractImages = false;
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
index e79f69dd28..f9d8883dff 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
@@ -276,7 +276,7 @@ namespace MediaBrowser.Providers.MediaInfo
if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh
|| options.MetadataRefreshMode == MetadataRefreshMode.Default)
{
- if (_config.Configuration.DummyChapterDuration > 0 && chapters.Length == 0 && mediaStreams.Any(i => i.Type == MediaStreamType.Video))
+ if (_config.Configuration.DummyChapterDuration > 0 && chapters.Length <= 1 && mediaStreams.Any(i => i.Type == MediaStreamType.Video))
{
chapters = CreateDummyChapters(video);
}
@@ -616,12 +616,13 @@ namespace MediaBrowser.Providers.MediaInfo
}
long dummyChapterDuration = TimeSpan.FromSeconds(_config.Configuration.DummyChapterDuration).Ticks;
- if (runtime <= dummyChapterDuration)
+
+ if (runtime <= 0)
{
return [];
}
- int chapterCount = (int)(runtime / dummyChapterDuration);
+ int chapterCount = Math.Max(1, (int)(runtime / dummyChapterDuration));
var chapters = new ChapterInfo[chapterCount];
long currentChapterTicks = 0;
diff --git a/tests/Jellyfin.Providers.Tests/MediaInfo/FFProbeVideoInfoTests.cs b/tests/Jellyfin.Providers.Tests/MediaInfo/FFProbeVideoInfoTests.cs
index 76922af8d5..a7491f42e9 100644
--- a/tests/Jellyfin.Providers.Tests/MediaInfo/FFProbeVideoInfoTests.cs
+++ b/tests/Jellyfin.Providers.Tests/MediaInfo/FFProbeVideoInfoTests.cs
@@ -45,8 +45,9 @@ public class FFProbeVideoInfoTests
[Theory]
[InlineData(null, 0)]
[InlineData(0L, 0)]
- [InlineData(1L, 0)]
- [InlineData(TimeSpan.TicksPerMinute * 5, 0)]
+ [InlineData(1L, 1)]
+ [InlineData(TimeSpan.TicksPerMinute * 3, 1)]
+ [InlineData(TimeSpan.TicksPerMinute * 5, 1)]
[InlineData((TimeSpan.TicksPerMinute * 5) + 1, 1)]
[InlineData(TimeSpan.TicksPerMinute * 50, 10)]
public void CreateDummyChapters_ValidRuntime_CorrectChaptersCount(long? runtime, int chaptersCount)
@@ -58,4 +59,20 @@ public class FFProbeVideoInfoTests
Assert.Equal(chaptersCount, chapters.Length);
}
+
+ [Theory]
+ [InlineData(1L)]
+ [InlineData(TimeSpan.TicksPerMinute * 3)]
+ [InlineData(TimeSpan.TicksPerMinute * 5)]
+ [InlineData((TimeSpan.TicksPerMinute * 5) + 1)]
+ [InlineData((TimeSpan.TicksPerMinute * 50) + 1)]
+ public void CreateDummyChapters_PositiveRuntime_NoChapterBeyondRuntime(long runtime)
+ {
+ var chapters = _fFProbeVideoInfo.CreateDummyChapters(new Video()
+ {
+ RunTimeTicks = runtime
+ });
+
+ Assert.All(chapters, chapter => Assert.True(chapter.StartPositionTicks < runtime));
+ }
}