vpr/ShadowStream/Modules/videoFrameModule.cs
2025-06-17 12:42:39 +01:00

119 lines
3.4 KiB
C#

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using LibVLCSharp.Shared;
using ModuleManager;
public static class VideoFrameExtractor
{
public static BitmapImage GetFrame200(string videoPath)
{
try
{
Core.Initialize();
string path = Path.GetTempFileName() + ".png";
using (var libVLC = new LibVLC("--no-xlib"))
using (var media = new Media(libVLC, videoPath, FromType.FromPath))
using (var mp = new MediaPlayer(media))
{
mp.Play();
while (!mp.IsPlaying)
Thread.Sleep(10);
// Seek to ~200th frame at 30 fps
mp.Time = (long)((200.0 / 30.0) * 1000);
Thread.Sleep(500);
if (!mp.IsPlaying)
mp.Play();
Thread.Sleep(1000);
if (!mp.TakeSnapshot(0, path, 0, 0))
throw new Exception("Snapshot failed.");
// Wait for snapshot file to be fully written and valid
int attempts = 10;
while (attempts-- > 0)
{
if (File.Exists(path) && new FileInfo(path).Length > 0)
break;
Thread.Sleep(100);
}
// ❗ Stop playback and dispose BEFORE trying to read the file
mp.Stop();
}
if (!File.Exists(path))
throw new FileNotFoundException("Snapshot file not found", path);
var fileInfo = new FileInfo(path);
if (fileInfo.Length == 0)
throw new Exception("Snapshot file is empty or corrupted.");
// Load BitmapImage on the UI thread
BitmapImage image = Application.Current.Dispatcher.Invoke(() =>
{
try
{
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
{
var img = new BitmapImage();
img.BeginInit();
img.CacheOption = BitmapCacheOption.OnLoad;
img.DecodePixelWidth = 150;
img.DecodePixelHeight = 100;
img.StreamSource = fs;
fs.Position = 0;
img.EndInit();
img.Freeze();
return img;
}
}
catch (Exception ex)
{
foreach (System.Windows.Window window in System.Windows.Application.Current.Windows)
{
if (window.IsActive && window is MainWindow mainWindow)
{
mainWindow.ReciveErrorLog($"Error loading snapshot image from {path}: {ex}");
break;
}
}
throw new Exception("Failed to load snapshot image.", ex);
}
});
DeleteFileLaterAsync(path);
return image;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
private static async void DeleteFileLaterAsync(string path, int delayMs = 60000)
{
try
{
await Task.Delay(delayMs);
File.Delete(path);
}
catch (Exception ex)
{
Console.WriteLine($"[WARNING] Failed to delete temp snapshot file {path}: {ex.Message}");
}
}
}