aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Server.Implementations
diff options
context:
space:
mode:
authorTim Eisele <Ghost_of_Stone@web.de>2025-04-03 02:06:40 +0200
committerGitHub <noreply@github.com>2025-04-02 18:06:40 -0600
commit0573999d5ef7526a3bb3e24523ba0e5599816155 (patch)
tree7d35df4c7c8536fc8f2f99d8d05309d97862684d /Jellyfin.Server.Implementations
parent49ac705867234c48e79ceb1cd84bc4394c65313d (diff)
Import Keyframes into database (#13771)
* Migrate keyframe data into database * Clear database table before import to handle failed migrations
Diffstat (limited to 'Jellyfin.Server.Implementations')
-rw-r--r--Jellyfin.Server.Implementations/Item/BaseItemRepository.cs1
-rw-r--r--Jellyfin.Server.Implementations/Item/KeyframeRepository.cs64
2 files changed, 65 insertions, 0 deletions
diff --git a/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs b/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs
index 08c024f43..c7cd54ed1 100644
--- a/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs
+++ b/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs
@@ -114,6 +114,7 @@ public sealed class BaseItemRepository
context.ItemDisplayPreferences.Where(e => e.ItemId == id).ExecuteDelete();
context.ItemValues.Where(e => e.BaseItemsMap!.Count == 0).ExecuteDelete();
context.ItemValuesMap.Where(e => e.ItemId == id).ExecuteDelete();
+ context.KeyframeData.Where(e => e.ItemId == id).ExecuteDelete();
context.MediaSegments.Where(e => e.ItemId == id).ExecuteDelete();
context.MediaStreamInfos.Where(e => e.ItemId == id).ExecuteDelete();
context.PeopleBaseItemMap.Where(e => e.ItemId == id).ExecuteDelete();
diff --git a/Jellyfin.Server.Implementations/Item/KeyframeRepository.cs b/Jellyfin.Server.Implementations/Item/KeyframeRepository.cs
new file mode 100644
index 000000000..a2267700f
--- /dev/null
+++ b/Jellyfin.Server.Implementations/Item/KeyframeRepository.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Jellyfin.Database.Implementations;
+using Jellyfin.Database.Implementations.Entities;
+using MediaBrowser.Controller.Persistence;
+using Microsoft.EntityFrameworkCore;
+
+namespace Jellyfin.Server.Implementations.Item;
+
+/// <summary>
+/// Repository for obtaining Keyframe data.
+/// </summary>
+public class KeyframeRepository : IKeyframeRepository
+{
+ private readonly IDbContextFactory<JellyfinDbContext> _dbProvider;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="KeyframeRepository"/> class.
+ /// </summary>
+ /// <param name="dbProvider">The EFCore db factory.</param>
+ public KeyframeRepository(IDbContextFactory<JellyfinDbContext> dbProvider)
+ {
+ _dbProvider = dbProvider;
+ }
+
+ private static MediaEncoding.Keyframes.KeyframeData Map(KeyframeData entity)
+ {
+ return new MediaEncoding.Keyframes.KeyframeData(
+ entity.TotalDuration,
+ (entity.KeyframeTicks ?? []).ToList());
+ }
+
+ private KeyframeData Map(MediaEncoding.Keyframes.KeyframeData dto, Guid itemId)
+ {
+ return new()
+ {
+ ItemId = itemId,
+ TotalDuration = dto.TotalDuration,
+ KeyframeTicks = dto.KeyframeTicks.ToList()
+ };
+ }
+
+ /// <inheritdoc />
+ public IReadOnlyList<MediaEncoding.Keyframes.KeyframeData> GetKeyframeData(Guid itemId)
+ {
+ using var context = _dbProvider.CreateDbContext();
+
+ return context.KeyframeData.AsNoTracking().Where(e => e.ItemId.Equals(itemId)).Select(e => Map(e)).ToList();
+ }
+
+ /// <inheritdoc />
+ public async Task SaveKeyframeDataAsync(Guid itemId, MediaEncoding.Keyframes.KeyframeData data, CancellationToken cancellationToken)
+ {
+ using var context = _dbProvider.CreateDbContext();
+ using var transaction = await context.Database.BeginTransactionAsync(cancellationToken).ConfigureAwait(false);
+ await context.KeyframeData.Where(e => e.ItemId.Equals(itemId)).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false);
+ await context.KeyframeData.AddAsync(Map(data, itemId), cancellationToken).ConfigureAwait(false);
+ await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
+ await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
+ }
+}