Merge pull request #17311 from dkanada/book-progress

extract page count from archives and PDFs
This commit is contained in:
Cody Robibero
2026-07-20 20:50:25 -04:00
committed by GitHub
5 changed files with 57 additions and 6 deletions
+1
View File
@@ -53,6 +53,7 @@
<PackageVersion Include="Moq" Version="4.18.4" />
<PackageVersion Include="NEbml" Version="1.1.0.5" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
<PackageVersion Include="PDFtoImage" Version="5.2.1" />
<PackageVersion Include="PlaylistsNET" Version="1.4.1" />
<PackageVersion Include="prometheus-net.AspNetCore" Version="8.2.1" />
<PackageVersion Include="prometheus-net.DotNetRuntime" Version="4.4.1" />
-5
View File
@@ -13,11 +13,6 @@ namespace MediaBrowser.Controller.Entities
[Common.RequiresSourceSerialisation]
public class Book : BaseItem, IHasLookupInfo<BookInfo>, IHasSeries
{
public Book()
{
this.RunTimeTicks = TimeSpan.TicksPerSecond;
}
[JsonIgnore]
public override MediaType MediaType => MediaType.Book;
@@ -1123,7 +1123,7 @@ namespace MediaBrowser.Providers.Manager
{
if (replaceData || !target.RunTimeTicks.HasValue)
{
if (target is not Audio && target is not Video)
if (target is not Audio && target is not Video && target is not Book)
{
target.RunTimeTicks = source.RunTimeTicks;
}
@@ -21,6 +21,7 @@
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" />
<PackageReference Include="Microsoft.Extensions.Http" />
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="PDFtoImage" />
<PackageReference Include="PlaylistsNET" />
<PackageReference Include="SharpCompress" />
<PackageReference Include="z440.atl.core" />
@@ -24,6 +24,8 @@ using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.MediaInfo;
using Microsoft.Extensions.Logging;
using PDFtoImage;
using SharpCompress.Archives;
namespace MediaBrowser.Providers.MediaInfo
{
@@ -37,6 +39,7 @@ namespace MediaBrowser.Providers.MediaInfo
ICustomMetadataProvider<Video>,
ICustomMetadataProvider<Audio>,
ICustomMetadataProvider<AudioBook>,
ICustomMetadataProvider<Book>,
IHasOrder,
IForcedProvider,
IPreRefreshProvider,
@@ -214,6 +217,57 @@ namespace MediaBrowser.Providers.MediaInfo
return FetchAudioInfo(item, options, cancellationToken);
}
/// <inheritdoc />
public Task<ItemUpdateType> FetchAsync(Book item, MetadataRefreshOptions options, CancellationToken cancellationToken)
{
if (item.IsVirtualItem || !item.IsFileProtocol)
{
return _cachedTask;
}
long pageCount;
switch (Path.GetExtension(item.Path).ToLowerInvariant())
{
case ".cb7":
case ".cbr":
case ".cbt":
case ".cbz":
using (var stream = File.OpenRead(item.Path))
using (var archive = ArchiveFactory.OpenArchive(stream))
{
pageCount = archive.Entries.Count(e => !e.IsDirectory);
}
break;
#pragma warning disable CA1416
case ".pdf":
using (var stream = File.OpenRead(item.Path))
{
pageCount = Conversion.GetPageCount(stream);
}
break;
#pragma warning restore CA1416
case ".epub":
// TODO process CFI and store as a string when multiple progress types are supported
// current progress value is percentage stored as a proportion of one second worth of ticks
item.RunTimeTicks = TimeSpan.TicksPerSecond;
return Task.FromResult(ItemUpdateType.MetadataImport);
default:
return _cachedTask;
}
// TODO use page count without modification when multiple progress types are supported
// book players report page count and the web client multiplies that value by 10000 to convert the expected milliseconds into ticks
item.RunTimeTicks = pageCount * 10000;
return Task.FromResult(ItemUpdateType.MetadataImport);
}
/// <summary>
/// Fetches video information for an item.
/// </summary>