diff --git a/ErsatzTV.Core/FFmpeg/FFmpegProcessBuilder.cs b/ErsatzTV.Core/FFmpeg/FFmpegProcessBuilder.cs index 629c1163f..4ffd0b858 100644 --- a/ErsatzTV.Core/FFmpeg/FFmpegProcessBuilder.cs +++ b/ErsatzTV.Core/FFmpeg/FFmpegProcessBuilder.cs @@ -225,7 +225,8 @@ namespace ErsatzTV.Core.FFmpeg public FFmpegProcessBuilder WithErrorText(IDisplaySize desiredResolution, string text) { - const string FONT_FILE = "fontfile=Resources/Roboto-Regular.ttf"; + string fontPath = Path.Combine(FileSystemLayout.ResourcesCacheFolder, "Roboto-Regular.ttf"); + var fontFile = $"fontfile={fontPath}"; const string FONT_COLOR = "fontcolor=white"; const string X = "x=(w-text_w)/2"; const string Y = "y=(h-text_h)/3*2"; @@ -233,7 +234,7 @@ namespace ErsatzTV.Core.FFmpeg string fontSize = text.Length > 80 ? "fontsize=30" : text.Length > 60 ? "fontsize=40" : "fontsize=60"; return WithFilterComplex( - $"[0:0]scale={desiredResolution.Width}:{desiredResolution.Height},drawtext={FONT_FILE}:{fontSize}:{FONT_COLOR}:{X}:{Y}:text='{text}'[v]", + $"[0:0]scale={desiredResolution.Width}:{desiredResolution.Height},drawtext={fontFile}:{fontSize}:{FONT_COLOR}:{X}:{Y}:text='{text}'[v]", "[v]", "1:a"); } diff --git a/ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs b/ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs index bcf46c71a..dadbbd3c3 100644 --- a/ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs +++ b/ErsatzTV.Core/FFmpeg/FFmpegProcessService.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.IO; using System.Threading.Tasks; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.FFmpeg; @@ -110,7 +111,7 @@ namespace ErsatzTV.Core.FFmpeg .WithQuiet() .WithFormatFlags(playbackSettings.FormatFlags) .WithRealtimeOutput(playbackSettings.RealtimeOutput) - .WithLoopedImage("Resources/background.png") + .WithLoopedImage(Path.Combine(FileSystemLayout.ResourcesCacheFolder, "background.png")) .WithLibavfilter() .WithInput("anullsrc") .WithErrorText(desiredResolution, errorMessage) diff --git a/ErsatzTV.Core/FileSystemLayout.cs b/ErsatzTV.Core/FileSystemLayout.cs index 7375bc522..1072234a4 100644 --- a/ErsatzTV.Core/FileSystemLayout.cs +++ b/ErsatzTV.Core/FileSystemLayout.cs @@ -16,6 +16,7 @@ namespace ErsatzTV.Core public static readonly string LogDatabasePath = Path.Combine(AppDataFolder, "logs.sqlite3"); public static readonly string LegacyImageCacheFolder = Path.Combine(AppDataFolder, "cache", "images"); + public static readonly string ResourcesCacheFolder = Path.Combine(AppDataFolder, "cache", "resources"); public static readonly string PlexSecretsPath = Path.Combine(AppDataFolder, "plex-secrets.json"); public static readonly string JellyfinSecretsPath = Path.Combine(AppDataFolder, "jellyfin-secrets.json"); diff --git a/ErsatzTV/ErsatzTV.csproj b/ErsatzTV/ErsatzTV.csproj index f7b0e9fcd..d7d2ff03d 100644 --- a/ErsatzTV/ErsatzTV.csproj +++ b/ErsatzTV/ErsatzTV.csproj @@ -51,12 +51,9 @@ - - Always - - - Always - + + + diff --git a/ErsatzTV/Services/RunOnce/ResourceExtractorService.cs b/ErsatzTV/Services/RunOnce/ResourceExtractorService.cs new file mode 100644 index 000000000..8be066516 --- /dev/null +++ b/ErsatzTV/Services/RunOnce/ResourceExtractorService.cs @@ -0,0 +1,42 @@ +using System.IO; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using ErsatzTV.Core; +using Microsoft.Extensions.Hosting; + +namespace ErsatzTV.Services.RunOnce +{ + public class ResourceExtractorService : IHostedService + { + public async Task StartAsync(CancellationToken cancellationToken) + { + if (!Directory.Exists(FileSystemLayout.ResourcesCacheFolder)) + { + Directory.CreateDirectory(FileSystemLayout.ResourcesCacheFolder); + } + + Assembly assembly = typeof(ResourceExtractorService).GetTypeInfo().Assembly; + + await ExtractResource(assembly, "background.png", cancellationToken); + await ExtractResource(assembly, "ErsatzTV.png", cancellationToken); + await ExtractResource(assembly, "Roboto-Regular.ttf", cancellationToken); + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } + + private async Task ExtractResource(Assembly assembly, string name, CancellationToken cancellationToken) + { + await using Stream resource = assembly.GetManifestResourceStream($"ErsatzTV.Resources.{name}"); + if (resource != null) + { + await using FileStream fs = File.Create( + Path.Combine(FileSystemLayout.ResourcesCacheFolder, name)); + await resource.CopyToAsync(fs, cancellationToken); + } + } + } +} diff --git a/ErsatzTV/Startup.cs b/ErsatzTV/Startup.cs index 55cfc871f..fe4f48dbb 100644 --- a/ErsatzTV/Startup.cs +++ b/ErsatzTV/Startup.cs @@ -255,6 +255,7 @@ namespace ErsatzTV services.AddHostedService(); services.AddHostedService(); services.AddHostedService(); + services.AddHostedService(); services.AddHostedService(); services.AddHostedService(); services.AddHostedService();