154 lines
5.4 KiB
C#
154 lines
5.4 KiB
C#
using NAudio.CoreAudioApi;
|
|
using NAudio.Wave;
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace _2dxAutoClip_NET
|
|
{
|
|
internal class ffmpegAPI
|
|
{
|
|
|
|
public ffmpegAPI() { }
|
|
|
|
private static Process _ffmpegProcess;
|
|
private static string _ffmpegFolderPath = File.ReadAllText($@"{Environment.CurrentDirectory}\conf\ffmpeg.exe");
|
|
private static WasapiCapture _waveSource;
|
|
private static WaveFileWriter _writer = null;
|
|
private static string _audioFilePath = null;
|
|
private static string _videoFilePath = null;
|
|
public void StartRecording(string songName)
|
|
{
|
|
Task.Run(() => StartAudioRecording(songName));
|
|
StartFfmpegRecording(songName);
|
|
}
|
|
|
|
public void StartAudioRecording(string songName)
|
|
{
|
|
try
|
|
{
|
|
var date = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
|
|
_audioFilePath = $"{_ffmpegFolderPath}\\{songName}_{date}.wav";
|
|
var outputFolder = Path.GetDirectoryName(_audioFilePath);
|
|
Directory.CreateDirectory(outputFolder);
|
|
_waveSource = new WasapiLoopbackCapture();
|
|
_writer = new WaveFileWriter(_audioFilePath, _waveSource.WaveFormat);
|
|
_waveSource.DataAvailable += (sender, args) =>
|
|
{
|
|
_writer.Write(args.Buffer, 0, args.BytesRecorded);
|
|
};
|
|
_waveSource.RecordingStopped += (sender, args) =>
|
|
{
|
|
_writer.Dispose();
|
|
_writer = null;
|
|
_waveSource.Dispose();
|
|
_waveSource = null;
|
|
};
|
|
|
|
_waveSource.StartRecording();
|
|
Console.WriteLine("WASAPI Audio recording started.");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Error starting audio recording: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public void StartFfmpegRecording(string songName)
|
|
{
|
|
var date = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
|
|
_videoFilePath = $"{_ffmpegFolderPath}\\{songName}_{date}.mkv";
|
|
|
|
var ffmpegArguments = $"-framerate 60 " +
|
|
$"-filter_complex \"ddagrab=0,hwdownload,format=bgra\" " +
|
|
$"-c:v libx264 -movflags +faststart -crf 20 -y \"{_videoFilePath}\"";
|
|
|
|
_ffmpegProcess = new Process();
|
|
_ffmpegProcess.StartInfo.FileName = "ffmpeg";
|
|
_ffmpegProcess.StartInfo.Arguments = ffmpegArguments;
|
|
_ffmpegProcess.StartInfo.UseShellExecute = false;
|
|
_ffmpegProcess.StartInfo.RedirectStandardOutput = false;
|
|
_ffmpegProcess.StartInfo.RedirectStandardError = true;
|
|
_ffmpegProcess.StartInfo.CreateNoWindow = true;
|
|
|
|
_ffmpegProcess.ErrorDataReceived += (_, args) => Console.WriteLine(args.Data);
|
|
|
|
_ffmpegProcess.Start();
|
|
_ffmpegProcess.BeginErrorReadLine();
|
|
}
|
|
|
|
public void StopRecording(string songName)
|
|
{
|
|
StopFfmpegRecording();
|
|
StopAudioRecording();
|
|
CombineAudioAndVideo(_videoFilePath, _audioFilePath, songName);
|
|
}
|
|
|
|
public void StopAudioRecording()
|
|
{
|
|
if (_waveSource == null) return;
|
|
|
|
_waveSource.StopRecording();
|
|
_waveSource.Dispose();
|
|
_waveSource = null;
|
|
if (_writer != null)
|
|
{
|
|
_writer.Dispose();
|
|
_writer = null;
|
|
}
|
|
|
|
Console.WriteLine("Audio recording stopped.");
|
|
}
|
|
|
|
|
|
public void StopFfmpegRecording()
|
|
{
|
|
if (_ffmpegProcess != null && _ffmpegProcess.HasExited) return;
|
|
_ffmpegProcess?.Kill();
|
|
_ffmpegProcess?.WaitForExit();
|
|
_ffmpegProcess?.Dispose();
|
|
_ffmpegProcess = null;
|
|
Console.WriteLine("FFMPEG process stopped.");
|
|
}
|
|
|
|
public void CombineAudioAndVideo(string videoFilePath, string audioFilePath, string songName)
|
|
{
|
|
var combinedOutputFilePath = $"{_ffmpegFolderPath}\\{songName}_combined_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.mp4";
|
|
var ffmpegArgs =
|
|
$"-y -i \"{videoFilePath}\" -i \"{audioFilePath}\" -c:v copy -c:a aac -strict experimental \"{combinedOutputFilePath}\"";
|
|
|
|
var processInfo = new ProcessStartInfo
|
|
{
|
|
FileName = "ffmpeg",
|
|
Arguments = ffmpegArgs,
|
|
RedirectStandardOutput = false,
|
|
RedirectStandardError = true,
|
|
UseShellExecute = false,
|
|
CreateNoWindow = true
|
|
};
|
|
|
|
var process = Process.Start(processInfo);
|
|
if (process == null)
|
|
{
|
|
Console.WriteLine("FFmpeg failed to start.");
|
|
return;
|
|
}
|
|
|
|
var error = process.StandardError.ReadToEnd();
|
|
|
|
process.WaitForExit();
|
|
|
|
Console.WriteLine("FFmpeg Error: " + error);
|
|
|
|
Console.WriteLine(File.Exists(combinedOutputFilePath)
|
|
? "Audio and video have been successfully combined."
|
|
: "Failed to combine audio and video. Check the logs for errors.");
|
|
File.Delete(videoFilePath);
|
|
File.Delete(audioFilePath);
|
|
}
|
|
}
|
|
}
|