using System; using System.IO; using System.Threading.Tasks; using ScreenRecorderLib; namespace ClipForge { public class ScreenCaptureService { private Recorder? _recorder; private string _tempOutputPath; private bool _isRecording; public bool IsCapturing => _isRecording; public ScreenCaptureService() { _tempOutputPath = Path.Combine( Path.GetTempPath(), "clipforge_buffer.mp4"); } public Task StartCaptureAsync(IntPtr hwnd) { try { _recorder = Recorder.CreateRecorder(); _recorder.OnRecordingComplete += OnRecordingComplete; _recorder.OnRecordingFailed += OnRecordingFailed; _recorder.OnStatusChanged += OnStatusChanged; if (File.Exists(_tempOutputPath)) File.Delete(_tempOutputPath); _recorder.Record(_tempOutputPath); _isRecording = true; System.Diagnostics.Debug.WriteLine("Recording started!"); return Task.FromResult(true); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"Failed to start: {ex.Message}"); return Task.FromResult(false); } } private void OnStatusChanged(object? sender, RecordingStatusEventArgs e) { System.Diagnostics.Debug.WriteLine($"Status: {e.Status}"); } private void OnRecordingFailed(object? sender, RecordingFailedEventArgs e) { System.Diagnostics.Debug.WriteLine($"Failed: {e.Error}"); _isRecording = false; } private void OnRecordingComplete(object? sender, RecordingCompleteEventArgs e) { System.Diagnostics.Debug.WriteLine($"Complete: {e.FilePath}"); _isRecording = false; } public async Task SaveClipAsync(int seconds = 30) { if (_recorder == null || !_isRecording) return null; try { _recorder.Stop(); await Task.Delay(1500); if (!File.Exists(_tempOutputPath)) return null; var outputDir = Path.Combine( Environment.GetFolderPath( Environment.SpecialFolder.MyVideos), "ClipForge"); if (!Directory.Exists(outputDir)) Directory.CreateDirectory(outputDir); var fileName = $"clip_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.mp4"; var outputPath = Path.Combine(outputDir, fileName); await TrimToLastSecondsAsync(_tempOutputPath, outputPath, seconds); // Restart recording for the next clip if (File.Exists(_tempOutputPath)) File.Delete(_tempOutputPath); _recorder.Record(_tempOutputPath); _isRecording = true; return outputPath; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"Save error: {ex.Message}"); return null; } } private async Task TrimToLastSecondsAsync( string inputPath, string outputPath, int seconds) { var ffmpegPath = Path.Combine(AppContext.BaseDirectory, "ffmpeg.exe"); if (!File.Exists(ffmpegPath)) { // No ffmpeg found — just copy the whole file for now File.Copy(inputPath, outputPath, true); return; } var args = $"-sseof -{seconds} -i \"{inputPath}\" -c copy \"{outputPath}\""; var process = new System.Diagnostics.Process { StartInfo = new System.Diagnostics.ProcessStartInfo { FileName = ffmpegPath, Arguments = args, UseShellExecute = false, CreateNoWindow = true } }; process.Start(); await Task.Run(() => process.WaitForExit()); } public void StopCapture() { _recorder?.Stop(); _recorder = null; _isRecording = false; } } }