Import Keyframes into database (#13771)

* Migrate keyframe data into database

* Clear database table before import to handle failed migrations
This commit is contained in:
Tim Eisele
2025-04-03 02:06:40 +02:00
committed by GitHub
parent 49ac705867
commit 0573999d5e
22 changed files with 2128 additions and 78 deletions

View File

@@ -0,0 +1,32 @@
#pragma warning disable CA2227 // Collection properties should be read only
using System;
using System.Collections.Generic;
namespace Jellyfin.Database.Implementations.Entities;
/// <summary>
/// Keyframe information for a specific file.
/// </summary>
public class KeyframeData
{
/// <summary>
/// Gets or Sets the ItemId.
/// </summary>
public required Guid ItemId { get; set; }
/// <summary>
/// Gets or sets the total duration of the stream in ticks.
/// </summary>
public long TotalDuration { get; set; }
/// <summary>
/// Gets or sets the keyframes in ticks.
/// </summary>
public ICollection<long>? KeyframeTicks { get; set; }
/// <summary>
/// Gets or sets the item reference.
/// </summary>
public BaseItemEntity? Item { get; set; }
}

View File

@@ -157,6 +157,11 @@ public class JellyfinDbContext(DbContextOptions<JellyfinDbContext> options, ILog
/// </summary>
public DbSet<BaseItemTrailerType> BaseItemTrailerTypes => Set<BaseItemTrailerType>();
/// <summary>
/// Gets the <see cref="DbSet{TEntity}"/>.
/// </summary>
public DbSet<KeyframeData> KeyframeData => Set<KeyframeData>();
/*public DbSet<Artwork> Artwork => Set<Artwork>();
public DbSet<Book> Books => Set<Book>();

View File

@@ -0,0 +1,18 @@
using Jellyfin.Database.Implementations.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Jellyfin.Database.Implementations.ModelConfiguration;
/// <summary>
/// KeyframeData Configuration.
/// </summary>
public class KeyframeDataConfiguration : IEntityTypeConfiguration<KeyframeData>
{
/// <inheritdoc/>
public void Configure(EntityTypeBuilder<KeyframeData> builder)
{
builder.HasKey(e => e.ItemId);
builder.HasOne(e => e.Item).WithMany().HasForeignKey(e => e.ItemId);
}
}

View File

@@ -0,0 +1,41 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Jellyfin.Server.Implementations.Migrations
{
/// <inheritdoc />
public partial class AddKeyframeData : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "KeyframeData",
columns: table => new
{
ItemId = table.Column<Guid>(type: "TEXT", nullable: false),
TotalDuration = table.Column<long>(type: "INTEGER", nullable: false),
KeyframeTicks = table.Column<string>(type: "TEXT", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_KeyframeData", x => x.ItemId);
table.ForeignKey(
name: "FK_KeyframeData_BaseItems_ItemId",
column: x => x.ItemId,
principalTable: "BaseItems",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "KeyframeData");
}
}
}

View File

@@ -748,6 +748,24 @@ namespace Jellyfin.Server.Implementations.Migrations
b.HasAnnotation("Sqlite:UseSqlReturningClause", false);
});
modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.KeyframeData", b =>
{
b.Property<Guid>("ItemId")
.HasColumnType("TEXT");
b.PrimitiveCollection<string>("KeyframeTicks")
.HasColumnType("TEXT");
b.Property<long>("TotalDuration")
.HasColumnType("INTEGER");
b.HasKey("ItemId");
b.ToTable("KeyframeData");
b.HasAnnotation("Sqlite:UseSqlReturningClause", false);
});
modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaSegment", b =>
{
b.Property<Guid>("Id")
@@ -1522,6 +1540,17 @@ namespace Jellyfin.Server.Implementations.Migrations
b.Navigation("ItemValue");
});
modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.KeyframeData", b =>
{
b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item")
.WithMany()
.HasForeignKey("ItemId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Item");
});
modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b =>
{
b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item")