Initial support for ApplicationLoopback audio recording (WASAPI only)
This commit is contained in:
parent
d6010162fc
commit
139b64dd1b
|
@ -5,7 +5,6 @@ using System.Text.RegularExpressions;
|
|||
using NAudio.CoreAudioApi;
|
||||
using NAudio.Wave;
|
||||
using System.Net;
|
||||
// ReSharper disable PossibleInvalidCastExceptionInForeachLoop
|
||||
|
||||
namespace _2dxAutoClip;
|
||||
#pragma warning disable CA1416
|
||||
|
@ -15,6 +14,7 @@ class Program
|
|||
{
|
||||
private static readonly string WebsocketAddress = "localhost";
|
||||
private static Process? _ffmpegProcess;
|
||||
private static Process? _recorderprocess;
|
||||
private static string _ffmpegFolderPath = GetDefaultVideosFolderPath();
|
||||
private static WasapiCapture? _waveSource;
|
||||
private static WaveFileWriter _writer = null!;
|
||||
|
@ -69,6 +69,16 @@ class Program
|
|||
}
|
||||
}
|
||||
}
|
||||
public static int GetFirstProcessIdByName(string executableName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(executableName))
|
||||
{
|
||||
throw new ArgumentException("Executable name cannot be null or empty.", nameof(executableName));
|
||||
}
|
||||
var processes = Process.GetProcessesByName(executableName);
|
||||
Console.WriteLine($"Found spice PID: {processes.FirstOrDefault()?.Id}");
|
||||
return processes.FirstOrDefault()?.Id ?? -1;
|
||||
}
|
||||
private static void LoadSettingsFromPropFile()
|
||||
{
|
||||
const string filePath = "prop.txt";
|
||||
|
@ -228,30 +238,46 @@ class Program
|
|||
|
||||
private static void StartRecording(string songName)
|
||||
{
|
||||
Task.Run(() => StartAudioRecording(songName));
|
||||
StartAudioProcessRecording(songName);
|
||||
StartFfmpegRecording(songName);
|
||||
}
|
||||
|
||||
private static void StartAudioRecording(string songName)
|
||||
|
||||
|
||||
private static void StartAudioProcessRecording(string songName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var date = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
|
||||
_audioFilePath = $"{_ffmpegFolderPath}\\{songName}_{date}.wav";
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(_audioFilePath)!);
|
||||
_waveSource = new WasapiLoopbackCapture();
|
||||
_writer = new WaveFileWriter(_audioFilePath, _waveSource.WaveFormat);
|
||||
_waveSource.DataAvailable += (sender, args) =>
|
||||
|
||||
var directory = Path.GetDirectoryName(_audioFilePath);
|
||||
if (directory == null)
|
||||
{
|
||||
_writer.Write(args.Buffer, 0, args.BytesRecorded);
|
||||
};
|
||||
_waveSource.RecordingStopped += (sender, args) =>
|
||||
throw new InvalidOperationException("Invalid audio file path.");
|
||||
}
|
||||
Directory.CreateDirectory(directory);
|
||||
|
||||
var procid = GetFirstProcessIdByName(_gameProcessName);
|
||||
if (procid == -1)
|
||||
{
|
||||
_writer.Dispose();
|
||||
_waveSource.Dispose();
|
||||
throw new InvalidOperationException("Target process is not running.");
|
||||
}
|
||||
|
||||
var args = $"{procid} includetree {_audioFilePath}";
|
||||
_recorderprocess = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "applb",
|
||||
Arguments = args,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardError = true,
|
||||
CreateNoWindow = true
|
||||
}
|
||||
};
|
||||
_waveSource.StartRecording();
|
||||
Console.WriteLine("WASAPI Audio recording started.");
|
||||
|
||||
_recorderprocess.Start();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -259,6 +285,7 @@ class Program
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static void StartFfmpegRecording(string songName)
|
||||
{
|
||||
var date = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
|
||||
|
@ -380,15 +407,34 @@ class Program
|
|||
|
||||
private static void StopRecording(string songName)
|
||||
{
|
||||
StopAudioRecording();
|
||||
//StopAudioRecording();
|
||||
TerminateProcessByName();
|
||||
StopFfmpegRecording();
|
||||
CombineAudioAndVideo(_videoFilePath, _audioFilePath, songName);
|
||||
}
|
||||
|
||||
private static void StopAudioRecording()
|
||||
public static void TerminateProcessByName()
|
||||
{
|
||||
_waveSource?.StopRecording();
|
||||
Console.WriteLine("WASAPI Audio recording stopped.");
|
||||
var executableName = "applb";
|
||||
try
|
||||
{
|
||||
int processId = GetFirstProcessIdByName(executableName);
|
||||
|
||||
if (processId == -1)
|
||||
{
|
||||
Console.WriteLine($"No running process found for '{executableName}'.");
|
||||
return;
|
||||
}
|
||||
|
||||
var process = Process.GetProcessById(processId);
|
||||
process.Kill();
|
||||
|
||||
Console.WriteLine($"Process '{executableName}' with ID {processId} terminated successfully.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error terminating process '{executableName}': {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void StopFfmpegRecording()
|
||||
|
|
|
@ -39,7 +39,13 @@
|
|||
"warnAsError": [
|
||||
"NU1605"
|
||||
]
|
||||
}
|
||||
},
|
||||
"restoreAuditProperties": {
|
||||
"enableAudit": "true",
|
||||
"auditLevel": "low",
|
||||
"auditMode": "direct"
|
||||
},
|
||||
"SdkAnalysisLevel": "9.0.100"
|
||||
},
|
||||
"frameworks": {
|
||||
"net8.0": {
|
||||
|
@ -70,7 +76,7 @@
|
|||
"privateAssets": "all"
|
||||
}
|
||||
},
|
||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\8.0.300/PortableRuntimeIdentifierGraph.json"
|
||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.101/PortableRuntimeIdentifierGraph.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
|
||||
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\Mercury\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders>
|
||||
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.9.1</NuGetToolVersion>
|
||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.12.2</NuGetToolVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<SourceRoot Include="C:\Users\Mercury\.nuget\packages\" />
|
||||
|
|
|
@ -490,7 +490,13 @@
|
|||
"warnAsError": [
|
||||
"NU1605"
|
||||
]
|
||||
}
|
||||
},
|
||||
"restoreAuditProperties": {
|
||||
"enableAudit": "true",
|
||||
"auditLevel": "low",
|
||||
"auditMode": "direct"
|
||||
},
|
||||
"SdkAnalysisLevel": "9.0.100"
|
||||
},
|
||||
"frameworks": {
|
||||
"net8.0": {
|
||||
|
@ -521,7 +527,7 @@
|
|||
"privateAssets": "all"
|
||||
}
|
||||
},
|
||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\8.0.300/PortableRuntimeIdentifierGraph.json"
|
||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.101/PortableRuntimeIdentifierGraph.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"version": 2,
|
||||
"dgSpecHash": "xTfdkrpqvxmeY+pzZcnpBIJbSyoO94xa04eSLg8IlKmzbTfi/q7IfP/sLGg2XwIVxlpAVQKwcAeegUkFcOHA5A==",
|
||||
"dgSpecHash": "Cu8IH0pDN8c=",
|
||||
"success": true,
|
||||
"projectFilePath": "E:\\csharpcazzo\\2dxAutoClip\\2dxAutoClip\\2dxAutoClip.csproj",
|
||||
"expectedPackageFiles": [
|
||||
|
|
Loading…
Reference in a new issue