diff --git a/Wasari.Cli/Commands/DownloadCommand.cs b/Wasari.Cli/Commands/DownloadCommand.cs index 07f1345..4408871 100644 --- a/Wasari.Cli/Commands/DownloadCommand.cs +++ b/Wasari.Cli/Commands/DownloadCommand.cs @@ -44,6 +44,9 @@ public DownloadCommand(EnvironmentService environmentService, ILogger ParseFfmpegModules(string i } } + private static async Task> FindGpus() + { + var computer = new Computer + { + IsGpuEnabled = true + }; + + try + { + var features = new HashSet(); + + computer.Open(); + + foreach (var hardware in computer.Hardware) + { + switch (hardware.HardwareType) + { + case HardwareType.GpuNvidia: + if (await IsProgramAvailable("nvidia-smi", null).DefaultIfFailed()) + features.Add(EnvironmentFeatureType.NvidiaGpu); + + break; + case HardwareType.GpuAmd: + features.Add(EnvironmentFeatureType.AmdGpu); + break; + } + } + + return features + .Select(i => new EnvironmentFeature(i, null, null, string.Empty)) + .ToHashSet(); + } + catch (Exception e) + { + Debug.WriteLine("Failed to open LibreHardwareMonitor: {0}", e); + return Array.Empty(); + } + finally + { + computer.Close(); + } + } + public static async IAsyncEnumerable GetEnvironmentFeatures() { if (await GetProgramWithVersion(Environment.GetEnvironmentVariable("YTDLP") ?? "yt-dlp", "--version", @@ -113,7 +158,7 @@ public static async IAsyncEnumerable GetEnvironmentFeatures( yield return new EnvironmentFeature(EnvironmentFeatureType.FfmpegLibPlacebo, null, null, string.Empty); } - if (await IsProgramAvailable("nvidia-smi", null).DefaultIfFailed()) - yield return new EnvironmentFeature(EnvironmentFeatureType.NvidiaGpu, null, null, string.Empty); + foreach (var gpuFeature in await FindGpus()) + yield return gpuFeature; } } \ No newline at end of file diff --git a/Wasari.Environment/EnvironmentFeatureType.cs b/Wasari.Environment/EnvironmentFeatureType.cs index c795234..25da3ac 100644 --- a/Wasari.Environment/EnvironmentFeatureType.cs +++ b/Wasari.Environment/EnvironmentFeatureType.cs @@ -5,5 +5,6 @@ public enum EnvironmentFeatureType YtDlp, Ffmpeg, FfmpegLibPlacebo, - NvidiaGpu + NvidiaGpu, + AmdGpu } \ No newline at end of file diff --git a/Wasari.Environment/Wasari.Environment.csproj b/Wasari.Environment/Wasari.Environment.csproj index 82f47ea..c2ec5f2 100644 --- a/Wasari.Environment/Wasari.Environment.csproj +++ b/Wasari.Environment/Wasari.Environment.csproj @@ -9,6 +9,7 @@ + diff --git a/Wasari.FFmpeg/FFmpegOptions.cs b/Wasari.FFmpeg/FFmpegOptions.cs index 02a6d8c..83d914b 100644 --- a/Wasari.FFmpeg/FFmpegOptions.cs +++ b/Wasari.FFmpeg/FFmpegOptions.cs @@ -11,6 +11,8 @@ public record FFmpegOptions public FFmpegResolution? Resolution { get; set; } public bool UseNvidiaAcceleration { get; set; } + + public bool UseAmdAcceleration { get; set; } public bool UseTemporaryEncodingPath { get; set; } diff --git a/Wasari.FFmpeg/FFmpegService.cs b/Wasari.FFmpeg/FFmpegService.cs index 6c34131..3c0183c 100644 --- a/Wasari.FFmpeg/FFmpegService.cs +++ b/Wasari.FFmpeg/FFmpegService.cs @@ -145,8 +145,13 @@ private async IAsyncEnumerable BuildArgumentsForEpisode(IWasariEpisode e if (Options.Value.UseHevc) { + if(Options.Value is { UseNvidiaAcceleration: true, UseAmdAcceleration: true } && EnvironmentService.IsFeatureAvailable(EnvironmentFeatureType.NvidiaGpu, EnvironmentFeatureType.AmdGpu)) + throw new MultipleEncodersException("Cannot use both Nvidia and AMD acceleration at the same time"); + if (Options.Value.UseNvidiaAcceleration && EnvironmentService.IsFeatureAvailable(EnvironmentFeatureType.NvidiaGpu)) yield return "-c:v hevc_nvenc -rc vbr -cq 24 -qmin 24 -qmax 24 -profile:v main10 -pix_fmt p010le"; + else if(Options.Value.UseAmdAcceleration && EnvironmentService.IsFeatureAvailable(EnvironmentFeatureType.AmdGpu)) + yield return "-c:v hevc_amf -rc cbr -qmin 24 -qmax 24 -pix_fmt p010le"; else yield return "-crf 20 -pix_fmt yuv420p10le -c:v libx265 -tune animation -x265-params profile=main10"; } diff --git a/Wasari.FFmpeg/MultipleEncodersException.cs b/Wasari.FFmpeg/MultipleEncodersException.cs new file mode 100644 index 0000000..af0dd56 --- /dev/null +++ b/Wasari.FFmpeg/MultipleEncodersException.cs @@ -0,0 +1,8 @@ +namespace Wasari.FFmpeg; + +public class MultipleEncodersException : Exception +{ + public MultipleEncodersException(string message) : base(message) + { + } +} \ No newline at end of file