From b24617fe7c16b7a0c750939f8649f258d556fbb5 Mon Sep 17 00:00:00 2001 From: Jason Dove <1695733+jasongdove@users.noreply.github.com> Date: Sat, 1 Nov 2025 08:29:56 -0500 Subject: [PATCH] add some graphics engine template data fields (#2586) * move resolution out of media item template data key * add some media item template data --- CHANGELOG.md | 4 +++ .../Metadata/FFmpegProfileTemplateDataKey.cs | 6 +++++ .../Metadata/MediaItemTemplateDataKey.cs | 5 ++-- .../Repositories/TemplateDataRepository.cs | 25 ++++++++++++++++--- .../Graphics/GraphicsElementLoader.cs | 6 +++-- 5 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 ErsatzTV.Core/Metadata/FFmpegProfileTemplateDataKey.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index 76eed07e7..a9bd937d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] ### Added - Show playout warnings count badge in left menu +- Graphics Engine: + - Add `MediaItem_Resolution` template data (the current `Resolution` variable is the FFmpeg Profile resolution) + - Add `MediaItem_Start` template data (DateTimeOffset) + - Add `MediaItem_Stop` template data (DateTimeOffset) ### Fixed - Fix HLS Direct playback with Jellyfin 10.11 diff --git a/ErsatzTV.Core/Metadata/FFmpegProfileTemplateDataKey.cs b/ErsatzTV.Core/Metadata/FFmpegProfileTemplateDataKey.cs new file mode 100644 index 000000000..5f6815c8c --- /dev/null +++ b/ErsatzTV.Core/Metadata/FFmpegProfileTemplateDataKey.cs @@ -0,0 +1,6 @@ +namespace ErsatzTV.Core.Metadata; + +public static class FFmpegProfileTemplateDataKey +{ + public static readonly string Resolution = "Resolution"; +} diff --git a/ErsatzTV.Core/Metadata/MediaItemTemplateDataKey.cs b/ErsatzTV.Core/Metadata/MediaItemTemplateDataKey.cs index c9368a9f4..09c63f5f9 100644 --- a/ErsatzTV.Core/Metadata/MediaItemTemplateDataKey.cs +++ b/ErsatzTV.Core/Metadata/MediaItemTemplateDataKey.cs @@ -2,10 +2,11 @@ namespace ErsatzTV.Core.Metadata; public static class MediaItemTemplateDataKey { - public static readonly string Resolution = "Resolution"; - + public static readonly string Resolution = "MediaItem_Resolution"; public static readonly string Duration = "MediaItem_Duration"; public static readonly string StreamSeek = "MediaItem_StreamSeek"; + public static readonly string Start = "MediaItem_Start"; + public static readonly string Stop = "MediaItem_Stop"; // common public static readonly string Path = "MediaItem_Path"; diff --git a/ErsatzTV.Infrastructure/Data/Repositories/TemplateDataRepository.cs b/ErsatzTV.Infrastructure/Data/Repositories/TemplateDataRepository.cs index a9ba858ed..f6bbbc764 100644 --- a/ErsatzTV.Infrastructure/Data/Repositories/TemplateDataRepository.cs +++ b/ErsatzTV.Infrastructure/Data/Repositories/TemplateDataRepository.cs @@ -143,6 +143,8 @@ public class TemplateDataRepository(ILocalFileSystem localFileSystem, IDbContext { foreach (MovieMetadata metadata in movie.MovieMetadata.HeadOrNone()) { + var headVersion = movie.GetHeadVersion(); + var result = new Dictionary { [MediaItemTemplateDataKey.Title] = metadata.Title, @@ -152,7 +154,9 @@ public class TemplateDataRepository(ILocalFileSystem localFileSystem, IDbContext [MediaItemTemplateDataKey.Directors] = (metadata.Directors ?? []).Map(d => d.Name).OrderBy(identity), [MediaItemTemplateDataKey.Genres] = (metadata.Genres ?? []).Map(g => g.Name).OrderBy(identity), - [MediaItemTemplateDataKey.Duration] = movie.GetHeadVersion().Duration, + [MediaItemTemplateDataKey.Resolution] = new Resolution + { Height = headVersion.Height, Width = headVersion.Width }, + [MediaItemTemplateDataKey.Duration] = headVersion.Duration, [MediaItemTemplateDataKey.ContentRating] = metadata.ContentRating }; @@ -206,6 +210,8 @@ public class TemplateDataRepository(ILocalFileSystem localFileSystem, IDbContext (showMetadata.Genres ?? []).Map(s => s.Name).OrderBy(identity)); } + var headVersion = episode.GetHeadVersion(); + foreach (EpisodeMetadata metadata in episode.EpisodeMetadata.HeadOrNone()) { result.Add(MediaItemTemplateDataKey.Title, metadata.Title); @@ -220,7 +226,10 @@ public class TemplateDataRepository(ILocalFileSystem localFileSystem, IDbContext result.Add( MediaItemTemplateDataKey.Genres, (metadata.Genres ?? []).Map(s => s.Name).OrderBy(identity)); - result.Add(MediaItemTemplateDataKey.Duration, episode.GetHeadVersion().Duration); + result.Add( + MediaItemTemplateDataKey.Resolution, + new Resolution { Height = headVersion.Height, Width = headVersion.Width }); + result.Add(MediaItemTemplateDataKey.Duration, headVersion.Duration); } foreach (var version in episode.MediaVersions.HeadOrNone()) @@ -269,6 +278,8 @@ public class TemplateDataRepository(ILocalFileSystem localFileSystem, IDbContext artist = artistMetadata.Title; } + var headVersion = musicVideo.GetHeadVersion(); + var result = new Dictionary { [MediaItemTemplateDataKey.Title] = metadata.Title, @@ -282,7 +293,9 @@ public class TemplateDataRepository(ILocalFileSystem localFileSystem, IDbContext [MediaItemTemplateDataKey.Directors] = (metadata.Directors ?? []).Map(d => d.Name).OrderBy(identity), [MediaItemTemplateDataKey.Genres] = (metadata.Genres ?? []).Map(g => g.Name).OrderBy(identity), - [MediaItemTemplateDataKey.Duration] = musicVideo.GetHeadVersion().Duration + [MediaItemTemplateDataKey.Resolution] = new Resolution + { Height = headVersion.Height, Width = headVersion.Width }, + [MediaItemTemplateDataKey.Duration] = headVersion.Duration }; foreach (var version in musicVideo.MediaVersions.HeadOrNone()) @@ -323,6 +336,8 @@ public class TemplateDataRepository(ILocalFileSystem localFileSystem, IDbContext { foreach (OtherVideoMetadata metadata in otherVideo.OtherVideoMetadata.HeadOrNone()) { + var headVersion = otherVideo.GetHeadVersion(); + var result = new Dictionary { [MediaItemTemplateDataKey.Title] = metadata.Title, @@ -332,7 +347,9 @@ public class TemplateDataRepository(ILocalFileSystem localFileSystem, IDbContext [MediaItemTemplateDataKey.Directors] = (metadata.Directors ?? []).Map(d => d.Name).OrderBy(identity), [MediaItemTemplateDataKey.Genres] = (metadata.Genres ?? []).Map(g => g.Name).OrderBy(identity), - [MediaItemTemplateDataKey.Duration] = otherVideo.GetHeadVersion().Duration + [MediaItemTemplateDataKey.Resolution] = new Resolution + { Height = headVersion.Height, Width = headVersion.Width }, + [MediaItemTemplateDataKey.Duration] = headVersion.Duration }; foreach (var version in otherVideo.MediaVersions.HeadOrNone()) diff --git a/ErsatzTV.Infrastructure/Streaming/Graphics/GraphicsElementLoader.cs b/ErsatzTV.Infrastructure/Streaming/Graphics/GraphicsElementLoader.cs index f6e53d4a0..ffeea0d4b 100644 --- a/ErsatzTV.Infrastructure/Streaming/Graphics/GraphicsElementLoader.cs +++ b/ErsatzTV.Infrastructure/Streaming/Graphics/GraphicsElementLoader.cs @@ -175,8 +175,10 @@ public partial class GraphicsElementLoader( // common variables var result = new Dictionary { - [MediaItemTemplateDataKey.Resolution] = context.FrameSize, - [MediaItemTemplateDataKey.StreamSeek] = context.Seek + [FFmpegProfileTemplateDataKey.Resolution] = context.FrameSize, + [MediaItemTemplateDataKey.StreamSeek] = context.Seek, + [MediaItemTemplateDataKey.Start] = context.ContentStartTime, + [MediaItemTemplateDataKey.Stop] = context.ContentStartTime + context.Duration }; // media item variables