feat: Add FFmpeg audio recording and ydotool typing backends, making them configurable.
This commit is contained in:
87
Audio/FfmpegAudioRecorder.cs
Normal file
87
Audio/FfmpegAudioRecorder.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
using Toak.Core;
|
||||
using Toak.IO;
|
||||
using Toak.Core.Interfaces;
|
||||
|
||||
namespace Toak.Audio;
|
||||
|
||||
public class FfmpegAudioRecorder : IAudioRecorder
|
||||
{
|
||||
private readonly string WavPath = Constants.Paths.RecordingWavFile;
|
||||
private readonly IRecordingStateTracker _stateTracker;
|
||||
private readonly INotifications _notifications;
|
||||
|
||||
public FfmpegAudioRecorder(IRecordingStateTracker stateTracker, INotifications notifications)
|
||||
{
|
||||
_stateTracker = stateTracker;
|
||||
_notifications = notifications;
|
||||
}
|
||||
|
||||
public string GetWavPath() => WavPath;
|
||||
|
||||
public void StartRecording()
|
||||
{
|
||||
if (File.Exists(WavPath))
|
||||
{
|
||||
Logger.LogDebug($"Deleting old audio file: {WavPath}");
|
||||
File.Delete(WavPath);
|
||||
}
|
||||
|
||||
Logger.LogDebug("Starting ffmpeg to record audio...");
|
||||
|
||||
var pInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = Constants.Commands.AudioFfmpeg,
|
||||
Arguments = $"-f pulse -i default -ac 1 -ar 16000 \"{WavPath}\"",
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true
|
||||
};
|
||||
|
||||
var process = Process.Start(pInfo);
|
||||
if (process != null)
|
||||
{
|
||||
_stateTracker.SetRecording(process.Id);
|
||||
_notifications.Notify("Recording Started (FFmpeg)");
|
||||
}
|
||||
}
|
||||
|
||||
public void StopRecording()
|
||||
{
|
||||
var pid = _stateTracker.GetRecordingPid();
|
||||
if (pid.HasValue)
|
||||
{
|
||||
Logger.LogDebug($"Found active ffmpeg process with PID {pid.Value}. Attempting to stop...");
|
||||
try
|
||||
{
|
||||
var process = Process.GetProcessById(pid.Value);
|
||||
if (!process.HasExited)
|
||||
{
|
||||
// Gracefully stop ffmpeg using SIGINT to ensure WAV headers are finalizing cleanly
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = Constants.Commands.ProcessKill,
|
||||
Arguments = $"-INT {pid.Value}",
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = false
|
||||
})?.WaitForExit();
|
||||
|
||||
process.WaitForExit(2000); // give it a moment to flush
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Process might already be dead
|
||||
Console.WriteLine($"[FfmpegAudioRecorder] Error stopping ffmpeg: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_stateTracker.ClearRecording();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user