From 837f824660e90d8ac8f027a2969746197125d362 Mon Sep 17 00:00:00 2001 From: Jason Dove <1695733+jasongdove@users.noreply.github.com> Date: Thu, 17 Jul 2025 16:23:57 +0000 Subject: [PATCH] include hardware info in troubleshooting archive (#2159) * add cpu and gpu info to troubleshooting general * include capabilities in troubleshooting archive --- CHANGELOG.md | 1 + .../ArchiveTroubleshootingResultsHandler.cs | 5 +++ .../StartTroubleshootingPlaybackHandler.cs | 32 +++++++++++++++++ .../Queries/GetTroubleshootingInfoHandler.cs | 16 ++++----- .../Troubleshooting/TroubleshootingInfo.cs | 3 ++ ErsatzTV.FFmpeg/Capabilities/CpuModel.cs | 3 ++ .../HardwareCapabilitiesFactory.cs | 35 +++++++++++++++++++ .../IHardwareCapabilitiesFactory.cs | 4 +++ .../Capabilities/VideoControllerModel.cs | 3 ++ ErsatzTV.FFmpeg/ErsatzTV.FFmpeg.csproj | 1 + ErsatzTV/Pages/Troubleshooting.razor | 2 ++ 11 files changed, 95 insertions(+), 10 deletions(-) create mode 100644 ErsatzTV.FFmpeg/Capabilities/CpuModel.cs create mode 100644 ErsatzTV.FFmpeg/Capabilities/VideoControllerModel.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index 31d0b8d3..c3fdc1ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -105,6 +105,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Mixed transcoding (software decode, hardware filters/encode) can now use multiple decode threads - Split main `Settings` page into multiple pages - Update UI layout on all pages to be less cramped and to work better on mobile +- Add CPU and Video Controller info to `Troubleshooting` > `General` output ### Fixed - Fix QSV acceleration in docker with older Intel devices diff --git a/ErsatzTV.Application/Troubleshooting/Commands/ArchiveTroubleshootingResultsHandler.cs b/ErsatzTV.Application/Troubleshooting/Commands/ArchiveTroubleshootingResultsHandler.cs index f49c0573..ffba9752 100644 --- a/ErsatzTV.Application/Troubleshooting/Commands/ArchiveTroubleshootingResultsHandler.cs +++ b/ErsatzTV.Application/Troubleshooting/Commands/ArchiveTroubleshootingResultsHandler.cs @@ -28,6 +28,11 @@ public class ArchiveTroubleshootingResultsHandler(ILocalFileSystem localFileSyst { zipArchive.CreateEntryFromFile(file, fileName); } + + if (fileName.Contains("capabilities", StringComparison.OrdinalIgnoreCase)) + { + zipArchive.CreateEntryFromFile(file, fileName); + } } return Task.FromResult(hasReport ? tempFile : Option.None); diff --git a/ErsatzTV.Application/Troubleshooting/Commands/StartTroubleshootingPlaybackHandler.cs b/ErsatzTV.Application/Troubleshooting/Commands/StartTroubleshootingPlaybackHandler.cs index 5b9d0678..6758c777 100644 --- a/ErsatzTV.Application/Troubleshooting/Commands/StartTroubleshootingPlaybackHandler.cs +++ b/ErsatzTV.Application/Troubleshooting/Commands/StartTroubleshootingPlaybackHandler.cs @@ -1,10 +1,13 @@ +using System.Runtime.InteropServices; using System.Text.Json; using System.Text.Json.Serialization; using CliWrap; using CliWrap.Buffered; using ErsatzTV.Core; +using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Locking; using ErsatzTV.Core.Notifications; +using ErsatzTV.FFmpeg.Runtime; using Microsoft.Extensions.Logging; namespace ErsatzTV.Application.Troubleshooting; @@ -12,6 +15,7 @@ namespace ErsatzTV.Application.Troubleshooting; public class StartTroubleshootingPlaybackHandler( IMediator mediator, IEntityLocker entityLocker, + IRuntimeInfo runtimeInfo, ILogger logger) : IRequestHandler { @@ -41,6 +45,8 @@ public class StartTroubleshootingPlaybackHandler( Environment = request.TroubleshootingInfo.Environment.OrderBy(x => x.Key) .ToDictionary(x => x.Key, x => x.Value), request.TroubleshootingInfo.Health, + request.TroubleshootingInfo.Cpus, + request.TroubleshootingInfo.VideoControllers, request.TroubleshootingInfo.FFmpegSettings, request.TroubleshootingInfo.FFmpegProfiles, request.TroubleshootingInfo.Watermarks @@ -51,6 +57,32 @@ public class StartTroubleshootingPlaybackHandler( troubleshootingInfoJson, cancellationToken); + HardwareAccelerationKind hwAccel = request.TroubleshootingInfo.FFmpegProfiles.Head().HardwareAcceleration; + if (hwAccel is HardwareAccelerationKind.Qsv) + { + await File.WriteAllTextAsync( + Path.Combine(FileSystemLayout.TranscodeTroubleshootingFolder, "capabilities_qsv.txt"), + request.TroubleshootingInfo.QsvCapabilities, + cancellationToken); + } + + if (hwAccel is HardwareAccelerationKind.Vaapi || (hwAccel is HardwareAccelerationKind.Qsv && + runtimeInfo.IsOSPlatform(OSPlatform.Linux))) + { + await File.WriteAllTextAsync( + Path.Combine(FileSystemLayout.TranscodeTroubleshootingFolder, "capabilities_vaapi.txt"), + request.TroubleshootingInfo.VaapiCapabilities, + cancellationToken); + } + + if (hwAccel is HardwareAccelerationKind.Nvenc) + { + await File.WriteAllTextAsync( + Path.Combine(FileSystemLayout.TranscodeTroubleshootingFolder, "capabilities_nvidia.txt"), + request.TroubleshootingInfo.NvidiaCapabilities, + cancellationToken); + } + logger.LogDebug("ffmpeg troubleshooting arguments {FFmpegArguments}", request.Command.Arguments); BufferedCommandResult result = await request.Command diff --git a/ErsatzTV.Application/Troubleshooting/Queries/GetTroubleshootingInfoHandler.cs b/ErsatzTV.Application/Troubleshooting/Queries/GetTroubleshootingInfoHandler.cs index 6dbe7fc5..759ecb49 100644 --- a/ErsatzTV.Application/Troubleshooting/Queries/GetTroubleshootingInfoHandler.cs +++ b/ErsatzTV.Application/Troubleshooting/Queries/GetTroubleshootingInfoHandler.cs @@ -1,5 +1,4 @@ using System.Collections; -using System.Collections.Immutable; using System.Reflection; using System.Runtime.InteropServices; using ErsatzTV.Application.FFmpegProfiles; @@ -63,19 +62,11 @@ public class GetTroubleshootingInfoHandler : IRequestHandler c.FFmpegProfileId) - .ToImmutableHashSet(); - List ffmpegProfiles = await dbContext.FFmpegProfiles .AsNoTracking() .Include(p => p.Resolution) .ToListAsync(cancellationToken); - var activeFFmpegProfiles = ffmpegProfiles - .Filter(f => channelFFmpegProfiles.Contains(f.Id)) - .ToList(); - List channelWatermarks = await dbContext.ChannelWatermarks .AsNoTracking() .ToListAsync(cancellationToken); @@ -152,12 +143,17 @@ public class GetTroubleshootingInfoHandler : IRequestHandler cpuList = _hardwareCapabilitiesFactory.GetCpuList(); + List videoControllerList = _hardwareCapabilitiesFactory.GetVideoControllerList(); + return new TroubleshootingInfo( version, environment, + cpuList, + videoControllerList, healthCheckSummaries, ffmpegSettings, - activeFFmpegProfiles, + ffmpegProfiles, channels, channelWatermarks, nvidiaCapabilities, diff --git a/ErsatzTV.Application/Troubleshooting/TroubleshootingInfo.cs b/ErsatzTV.Application/Troubleshooting/TroubleshootingInfo.cs index 68753d9c..863e29d3 100644 --- a/ErsatzTV.Application/Troubleshooting/TroubleshootingInfo.cs +++ b/ErsatzTV.Application/Troubleshooting/TroubleshootingInfo.cs @@ -1,11 +1,14 @@ using ErsatzTV.Application.FFmpegProfiles; using ErsatzTV.Core.Domain; +using ErsatzTV.FFmpeg.Capabilities; namespace ErsatzTV.Application.Troubleshooting; public record TroubleshootingInfo( string Version, Dictionary Environment, + List Cpus, + List VideoControllers, List Health, FFmpegSettingsViewModel FFmpegSettings, List FFmpegProfiles, diff --git a/ErsatzTV.FFmpeg/Capabilities/CpuModel.cs b/ErsatzTV.FFmpeg/Capabilities/CpuModel.cs new file mode 100644 index 00000000..931be052 --- /dev/null +++ b/ErsatzTV.FFmpeg/Capabilities/CpuModel.cs @@ -0,0 +1,3 @@ +namespace ErsatzTV.FFmpeg.Capabilities; + +public record CpuModel(string Manufacturer, string Name); diff --git a/ErsatzTV.FFmpeg/Capabilities/HardwareCapabilitiesFactory.cs b/ErsatzTV.FFmpeg/Capabilities/HardwareCapabilitiesFactory.cs index e2ea3f7f..3766ebe1 100644 --- a/ErsatzTV.FFmpeg/Capabilities/HardwareCapabilitiesFactory.cs +++ b/ErsatzTV.FFmpeg/Capabilities/HardwareCapabilitiesFactory.cs @@ -9,6 +9,7 @@ using ErsatzTV.FFmpeg.Capabilities.Qsv; using ErsatzTV.FFmpeg.Capabilities.Vaapi; using ErsatzTV.FFmpeg.GlobalOption.HardwareAcceleration; using ErsatzTV.FFmpeg.Runtime; +using Hardware.Info; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; @@ -209,6 +210,40 @@ public class HardwareCapabilitiesFactory : IHardwareCapabilitiesFactory : result.StandardOutput.Trim().Split("\n").Skip(1).Map(s => s.Trim()).ToList(); } + public List GetCpuList() + { + try + { + var hardwareInfo = new HardwareInfo(); + hardwareInfo.RefreshCPUList(); + return hardwareInfo.CpuList.Map(c => new CpuModel(c.Manufacturer, c.Name)).ToList(); + } + catch (Exception) + { + // do nothing + } + + return []; + } + + public List GetVideoControllerList() + { + try + { + var hardwareInfo = new HardwareInfo(); + hardwareInfo.RefreshVideoControllerList(); + return hardwareInfo.VideoControllerList + .Map(v => new VideoControllerModel(v.Manufacturer, v.Name)) + .ToList(); + } + catch (Exception) + { + // do nothing + } + + return []; + } + private async Task> GetFFmpegCapabilities( string ffmpegPath, string capabilities, diff --git a/ErsatzTV.FFmpeg/Capabilities/IHardwareCapabilitiesFactory.cs b/ErsatzTV.FFmpeg/Capabilities/IHardwareCapabilitiesFactory.cs index b725f0b7..eda37dec 100644 --- a/ErsatzTV.FFmpeg/Capabilities/IHardwareCapabilitiesFactory.cs +++ b/ErsatzTV.FFmpeg/Capabilities/IHardwareCapabilitiesFactory.cs @@ -21,4 +21,8 @@ public interface IHardwareCapabilitiesFactory Task> GetVaapiOutput(string display, Option vaapiDriver, string vaapiDevice); Task> GetVaapiDisplays(); + + List GetCpuList(); + + List GetVideoControllerList(); } diff --git a/ErsatzTV.FFmpeg/Capabilities/VideoControllerModel.cs b/ErsatzTV.FFmpeg/Capabilities/VideoControllerModel.cs new file mode 100644 index 00000000..44d9a281 --- /dev/null +++ b/ErsatzTV.FFmpeg/Capabilities/VideoControllerModel.cs @@ -0,0 +1,3 @@ +namespace ErsatzTV.FFmpeg.Capabilities; + +public record VideoControllerModel(string Manufacturer, string Name); diff --git a/ErsatzTV.FFmpeg/ErsatzTV.FFmpeg.csproj b/ErsatzTV.FFmpeg/ErsatzTV.FFmpeg.csproj index 419a3e02..cf6334bc 100644 --- a/ErsatzTV.FFmpeg/ErsatzTV.FFmpeg.csproj +++ b/ErsatzTV.FFmpeg/ErsatzTV.FFmpeg.csproj @@ -10,6 +10,7 @@ + diff --git a/ErsatzTV/Pages/Troubleshooting.razor b/ErsatzTV/Pages/Troubleshooting.razor index 3da9352d..bbfdea2a 100644 --- a/ErsatzTV/Pages/Troubleshooting.razor +++ b/ErsatzTV/Pages/Troubleshooting.razor @@ -95,6 +95,8 @@ { info.Version, Environment = info.Environment.OrderBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value), + info.Cpus, + info.VideoControllers, info.Health, info.FFmpegSettings, info.Channels,