Browse Source

include hardware info in troubleshooting archive (#2159)

* add cpu and gpu info to troubleshooting general

* include capabilities in troubleshooting archive
pull/2160/head
Jason Dove 4 weeks ago committed by GitHub
parent
commit
837f824660
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 5
      ErsatzTV.Application/Troubleshooting/Commands/ArchiveTroubleshootingResultsHandler.cs
  3. 32
      ErsatzTV.Application/Troubleshooting/Commands/StartTroubleshootingPlaybackHandler.cs
  4. 16
      ErsatzTV.Application/Troubleshooting/Queries/GetTroubleshootingInfoHandler.cs
  5. 3
      ErsatzTV.Application/Troubleshooting/TroubleshootingInfo.cs
  6. 3
      ErsatzTV.FFmpeg/Capabilities/CpuModel.cs
  7. 35
      ErsatzTV.FFmpeg/Capabilities/HardwareCapabilitiesFactory.cs
  8. 4
      ErsatzTV.FFmpeg/Capabilities/IHardwareCapabilitiesFactory.cs
  9. 3
      ErsatzTV.FFmpeg/Capabilities/VideoControllerModel.cs
  10. 1
      ErsatzTV.FFmpeg/ErsatzTV.FFmpeg.csproj
  11. 2
      ErsatzTV/Pages/Troubleshooting.razor

1
CHANGELOG.md

@ -105,6 +105,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -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

5
ErsatzTV.Application/Troubleshooting/Commands/ArchiveTroubleshootingResultsHandler.cs

@ -28,6 +28,11 @@ public class ArchiveTroubleshootingResultsHandler(ILocalFileSystem localFileSyst @@ -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<string>.None);

32
ErsatzTV.Application/Troubleshooting/Commands/StartTroubleshootingPlaybackHandler.cs

@ -1,10 +1,13 @@ @@ -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; @@ -12,6 +15,7 @@ namespace ErsatzTV.Application.Troubleshooting;
public class StartTroubleshootingPlaybackHandler(
IMediator mediator,
IEntityLocker entityLocker,
IRuntimeInfo runtimeInfo,
ILogger<StartTroubleshootingPlaybackHandler> logger)
: IRequestHandler<StartTroubleshootingPlayback>
{
@ -41,6 +45,8 @@ public class StartTroubleshootingPlaybackHandler( @@ -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( @@ -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

16
ErsatzTV.Application/Troubleshooting/Queries/GetTroubleshootingInfoHandler.cs

@ -1,5 +1,4 @@ @@ -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<GetTroubleshootingI @@ -63,19 +62,11 @@ public class GetTroubleshootingInfoHandler : IRequestHandler<GetTroubleshootingI
.AsNoTracking()
.ToListAsync(cancellationToken);
var channelFFmpegProfiles = channels
.Map(c => c.FFmpegProfileId)
.ToImmutableHashSet();
List<FFmpegProfile> ffmpegProfiles = await dbContext.FFmpegProfiles
.AsNoTracking()
.Include(p => p.Resolution)
.ToListAsync(cancellationToken);
var activeFFmpegProfiles = ffmpegProfiles
.Filter(f => channelFFmpegProfiles.Contains(f.Id))
.ToList();
List<ChannelWatermark> channelWatermarks = await dbContext.ChannelWatermarks
.AsNoTracking()
.ToListAsync(cancellationToken);
@ -152,12 +143,17 @@ public class GetTroubleshootingInfoHandler : IRequestHandler<GetTroubleshootingI @@ -152,12 +143,17 @@ public class GetTroubleshootingInfoHandler : IRequestHandler<GetTroubleshootingI
}
}
List<CpuModel> cpuList = _hardwareCapabilitiesFactory.GetCpuList();
List<VideoControllerModel> videoControllerList = _hardwareCapabilitiesFactory.GetVideoControllerList();
return new TroubleshootingInfo(
version,
environment,
cpuList,
videoControllerList,
healthCheckSummaries,
ffmpegSettings,
activeFFmpegProfiles,
ffmpegProfiles,
channels,
channelWatermarks,
nvidiaCapabilities,

3
ErsatzTV.Application/Troubleshooting/TroubleshootingInfo.cs

@ -1,11 +1,14 @@ @@ -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<string, string> Environment,
List<CpuModel> Cpus,
List<VideoControllerModel> VideoControllers,
List<HealthCheckResultSummary> Health,
FFmpegSettingsViewModel FFmpegSettings,
List<FFmpegProfile> FFmpegProfiles,

3
ErsatzTV.FFmpeg/Capabilities/CpuModel.cs

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
namespace ErsatzTV.FFmpeg.Capabilities;
public record CpuModel(string Manufacturer, string Name);

35
ErsatzTV.FFmpeg/Capabilities/HardwareCapabilitiesFactory.cs

@ -9,6 +9,7 @@ using ErsatzTV.FFmpeg.Capabilities.Qsv; @@ -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 @@ -209,6 +210,40 @@ public class HardwareCapabilitiesFactory : IHardwareCapabilitiesFactory
: result.StandardOutput.Trim().Split("\n").Skip(1).Map(s => s.Trim()).ToList();
}
public List<CpuModel> 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<VideoControllerModel> 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<IReadOnlySet<string>> GetFFmpegCapabilities(
string ffmpegPath,
string capabilities,

4
ErsatzTV.FFmpeg/Capabilities/IHardwareCapabilitiesFactory.cs

@ -21,4 +21,8 @@ public interface IHardwareCapabilitiesFactory @@ -21,4 +21,8 @@ public interface IHardwareCapabilitiesFactory
Task<Option<string>> GetVaapiOutput(string display, Option<string> vaapiDriver, string vaapiDevice);
Task<List<string>> GetVaapiDisplays();
List<CpuModel> GetCpuList();
List<VideoControllerModel> GetVideoControllerList();
}

3
ErsatzTV.FFmpeg/Capabilities/VideoControllerModel.cs

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
namespace ErsatzTV.FFmpeg.Capabilities;
public record VideoControllerModel(string Manufacturer, string Name);

1
ErsatzTV.FFmpeg/ErsatzTV.FFmpeg.csproj

@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
<ItemGroup>
<PackageReference Include="CliWrap" Version="3.9.0" />
<PackageReference Include="Hardware.Info" Version="101.0.1.1" />
<PackageReference Include="LanguageExt.Core" Version="4.4.9" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="9.0.7" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.7" />

2
ErsatzTV/Pages/Troubleshooting.razor

@ -95,6 +95,8 @@ @@ -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,

Loading…
Cancel
Save