forked from Mercury/2dxAutoClip
add GPU autodetection for HW accelerated recording and encoding.
This commit is contained in:
parent
cc70624b54
commit
944c6c90a0
|
@ -1,15 +1,17 @@
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Management;
|
||||||
using NAudio.CoreAudioApi;
|
using NAudio.CoreAudioApi;
|
||||||
using NAudio.Wave;
|
using NAudio.Wave;
|
||||||
|
// ReSharper disable PossibleInvalidCastExceptionInForeachLoop
|
||||||
|
|
||||||
namespace _2dxAutoClip;
|
namespace _2dxAutoClip;
|
||||||
|
#pragma warning disable CA1416
|
||||||
|
|
||||||
class Program
|
class Program
|
||||||
{
|
{
|
||||||
private static readonly string WebsocketAddress = "localhost";
|
private static readonly string WebsocketAddress = "localhost";
|
||||||
private static readonly int WebsocketPort = 10573;
|
|
||||||
private static Process? _ffmpegProcess;
|
private static Process? _ffmpegProcess;
|
||||||
private static string _ffmpegFolderPath = GetDefaultVideosFolderPath();
|
private static string _ffmpegFolderPath = GetDefaultVideosFolderPath();
|
||||||
private static WasapiCapture? _waveSource;
|
private static WasapiCapture? _waveSource;
|
||||||
|
@ -99,11 +101,11 @@ class Program
|
||||||
private static async Task TryConnectWebSocket()
|
private static async Task TryConnectWebSocket()
|
||||||
{
|
{
|
||||||
const int maxRetries = 5;
|
const int maxRetries = 5;
|
||||||
int attempt = 0;
|
var attempt = 0;
|
||||||
while (attempt < maxRetries)
|
while (attempt < maxRetries)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Attempt {attempt + 1} of {maxRetries} to connect...");
|
Console.WriteLine($"Attempt {attempt + 1} of {maxRetries} to connect...");
|
||||||
bool success = await ConnectWebSocket();
|
var success = await ConnectWebSocket();
|
||||||
if (success) break;
|
if (success) break;
|
||||||
attempt++;
|
attempt++;
|
||||||
if (attempt < maxRetries)
|
if (attempt < maxRetries)
|
||||||
|
@ -120,7 +122,7 @@ class Program
|
||||||
|
|
||||||
private static async Task<bool> ConnectWebSocket()
|
private static async Task<bool> ConnectWebSocket()
|
||||||
{
|
{
|
||||||
var tickerUri = new Uri($"ws://{WebsocketAddress}:{WebsocketPort}");
|
var tickerUri = new Uri($"ws://{WebsocketAddress}:10573");
|
||||||
var reconnecting = false;
|
var reconnecting = false;
|
||||||
var lastMessage = string.Empty;
|
var lastMessage = string.Empty;
|
||||||
var consecutiveMessageCount = 0;
|
var consecutiveMessageCount = 0;
|
||||||
|
@ -229,29 +231,77 @@ class Program
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void StartFfmpegRecording(string songName)
|
private static void StartFfmpegRecording(string songName)
|
||||||
{
|
{
|
||||||
var date = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
|
var encoder = GetHardwareEncoder();
|
||||||
_videoFilePath = $"{_ffmpegFolderPath}\\{songName}_{date}.mkv";
|
|
||||||
var ffmpegArguments = $"-framerate {_framerate} " +
|
|
||||||
$"-filter_complex \"ddagrab=framerate={_framerate},hwdownload,format=bgra\" " +
|
|
||||||
$"-c:v libx264 -tune zerolatency -crf {_crf} -video_size {_resolution} -movflags +faststart -y \"{_videoFilePath}\"";
|
|
||||||
_ffmpegProcess = new Process
|
|
||||||
{
|
|
||||||
StartInfo = new ProcessStartInfo
|
|
||||||
{
|
|
||||||
FileName = "ffmpeg",
|
|
||||||
Arguments = ffmpegArguments,
|
|
||||||
UseShellExecute = false,
|
|
||||||
RedirectStandardError = true,
|
|
||||||
CreateNoWindow = true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
_ffmpegProcess.ErrorDataReceived += (_, args) => Console.WriteLine(args.Data);
|
|
||||||
_ffmpegProcess.Start();
|
|
||||||
_ffmpegProcess.BeginErrorReadLine();
|
|
||||||
|
|
||||||
Console.WriteLine("FFmpeg recording started.");
|
var date = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
|
||||||
|
_videoFilePath = $"{_ffmpegFolderPath}\\{songName}_{date}.mkv";
|
||||||
|
var ffmpegArguments = $"-framerate {_framerate} " +
|
||||||
|
$"-filter_complex \"ddagrab=framerate={_framerate},hwdownload,format=bgra\" " +
|
||||||
|
$"{encoder} -crf {_crf} -video_size {_resolution} -movflags +faststart -y \"{_videoFilePath}\"";
|
||||||
|
_ffmpegProcess = new Process
|
||||||
|
{
|
||||||
|
StartInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = "ffmpeg",
|
||||||
|
Arguments = ffmpegArguments,
|
||||||
|
UseShellExecute = false,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
CreateNoWindow = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
_ffmpegProcess.Start();
|
||||||
|
|
||||||
|
Console.WriteLine("FFmpeg recording started.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetHardwareEncoder()
|
||||||
|
{
|
||||||
|
var graphicsCard = GetGraphicsCard();
|
||||||
|
var encoder = "-c:v libx264";
|
||||||
|
|
||||||
|
if (graphicsCard.Contains("NVIDIA"))
|
||||||
|
{
|
||||||
|
encoder = "-c:v h264_nvenc";
|
||||||
|
Console.WriteLine("Using NVIDIA hardware encoding (h264_nvenc).");
|
||||||
}
|
}
|
||||||
|
else if (graphicsCard.Contains("AMD"))
|
||||||
|
{
|
||||||
|
encoder = "-c:v h264_amf";
|
||||||
|
Console.WriteLine("Using AMD hardware encoding (h264_amf).");
|
||||||
|
}
|
||||||
|
else if (graphicsCard.Contains("INTEL"))
|
||||||
|
{
|
||||||
|
encoder = "-c:v h264_qsv";
|
||||||
|
Console.WriteLine("Using Intel hardware encoding (h264_qsv).");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("No recognized hardware encoder found, using CPU (libx264).");
|
||||||
|
}
|
||||||
|
|
||||||
|
return encoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetGraphicsCard()
|
||||||
|
{
|
||||||
|
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DisplayConfiguration");
|
||||||
|
var graphicsCard = "";
|
||||||
|
|
||||||
|
foreach (ManagementObject obj in searcher.Get())
|
||||||
|
{
|
||||||
|
foreach (var prop in obj.Properties)
|
||||||
|
{
|
||||||
|
if (prop.Name == "Description" && prop.Value != null)
|
||||||
|
{
|
||||||
|
graphicsCard = prop.Value.ToString().ToUpper();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return graphicsCard;
|
||||||
|
}
|
||||||
|
|
||||||
private static void StopRecording(string songName)
|
private static void StopRecording(string songName)
|
||||||
{
|
{
|
||||||
|
@ -280,7 +330,7 @@ class Program
|
||||||
{
|
{
|
||||||
var combinedOutputFilePath = $"{_ffmpegFolderPath}\\{songName}_combined_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.mp4";
|
var combinedOutputFilePath = $"{_ffmpegFolderPath}\\{songName}_combined_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.mp4";
|
||||||
var ffmpegArgs =
|
var ffmpegArgs =
|
||||||
$"-y -i \"{videoFilePath}\" -i \"{audioFilePath}\" -c:v copy -c:a aac -strict experimental -shortest \"{combinedOutputFilePath}\"";
|
$"-y -i \"{videoFilePath}\" -i \"{audioFilePath}\" -c:v copy -c:a aac -strict experimental -shortest -hwaccel_output_format d3d11 \"{combinedOutputFilePath}\"";
|
||||||
|
|
||||||
var processInfo = new ProcessStartInfo
|
var processInfo = new ProcessStartInfo
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue