diff --git a/Views/UserControl/ViewportData/Helper/VideoHelper.cs b/Views/UserControl/ViewportData/Helper/VideoHelper.cs index 9af1d9c..048d438 100644 --- a/Views/UserControl/ViewportData/Helper/VideoHelper.cs +++ b/Views/UserControl/ViewportData/Helper/VideoHelper.cs @@ -14,12 +14,12 @@ namespace SparkClient.Views.UserControl.ViewportData.Helper; public class VideoHelper { - public static async Task CreateVideoFromPngList(List pngEncoders, string outputPath) + public static void CreateVideoFromPngList(List pngEncoders, string outputPath) { string tempDirectory = Path.Combine(System.Environment.CurrentDirectory, "PngFrames"); Directory.CreateDirectory(tempDirectory); - await Task.Delay(1); - try + + try { // Save each PNG frame to a temporary directory for (int i = 0; i < pngEncoders.Count; i++) @@ -73,6 +73,73 @@ public class VideoHelper } } + public static async Task CreateVideoFromPngListAsync(List pngEncoders, string outputPath) + { + string tempDirectory = Path.Combine(Environment.CurrentDirectory, "PngFrames"); + Directory.CreateDirectory(tempDirectory); + await Task.Delay(1).ConfigureAwait(false); + + try + { + // Save each PNG frame to a temporary directory + for (int i = 0; i < pngEncoders.Count; i++) + { + string framePath = Path.Combine(tempDirectory, $"frame_{i:D5}.png"); + + await Task.Run(() => + { + Application.Current.Dispatcher.Invoke(() => + { + using (FileStream fs = new FileStream(framePath, FileMode.Create)) + { + pngEncoders[i].Save(fs); + } + }); + }).ConfigureAwait(false); + } + + // Use FFmpeg to create a video from the PNG frames + string ffmpegPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ffmpeg.exe"); // Assuming ffmpeg.exe is in the same directory as the application + if (!File.Exists(ffmpegPath)) + { + throw new FileNotFoundException("FFmpeg executable not found.", ffmpegPath); + } + + string framePattern = Path.Combine(tempDirectory, "frame_%05d.png").Replace("\\", "/"); // Replace backslashes with forward slashes for FFmpeg compatibility + string arguments = $"-framerate 30 -i \"{framePattern}\" -vf \"scale=640:480\" -c:v libx264 -pix_fmt yuv420p \"{outputPath}\""; + + var processInfo = new System.Diagnostics.ProcessStartInfo + { + FileName = ffmpegPath, + Arguments = arguments, + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + }; + + using (var process = System.Diagnostics.Process.Start(processInfo)) + { + string error = await process.StandardError.ReadToEndAsync().ConfigureAwait(false); + process.WaitForExit(); + + if (process.ExitCode != 0) + { + throw new Exception($"FFmpeg error: {error}"); + } + } + + var dicName = Path.GetDirectoryName(outputPath); + var fileName = Path.GetFileNameWithoutExtension(outputPath); + Microsoft.VisualBasic.FileIO.FileSystem.RenameFile(outputPath, fileName + ".dat"); + } + finally + { + // Clean up temporary frames + Directory.Delete(tempDirectory, true); + } + } + public static void ConvertMp4ToDat(string inputFilePath, string outputFilePath) { string ffmpegPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ffmpeg.exe"); // Assuming ffmpeg.exe is in the same directory as the application diff --git a/Views/UserControl/ViewportData/Helper/ViewportHelperPro.cs b/Views/UserControl/ViewportData/Helper/ViewportHelperPro.cs index 9b96816..dd9bd53 100644 --- a/Views/UserControl/ViewportData/Helper/ViewportHelperPro.cs +++ b/Views/UserControl/ViewportData/Helper/ViewportHelperPro.cs @@ -174,7 +174,7 @@ public class ViewportHelperPro List pngList = await generationTask; - await VideoHelper.CreateVideoFromPngList(pngList, filePath); + await VideoHelper.CreateVideoFromPngListAsync(pngList, filePath); } /// diff --git a/Views/UserControl/ViewportData/Helper/ViewportManager.cs b/Views/UserControl/ViewportData/Helper/ViewportManager.cs index a376140..d619dbd 100644 --- a/Views/UserControl/ViewportData/Helper/ViewportManager.cs +++ b/Views/UserControl/ViewportData/Helper/ViewportManager.cs @@ -158,6 +158,7 @@ public class ViewportManager ViewportTriangle.Clear(); ViewportTriangle.AddRange(entities); + _viewport.Items.Clear(); MainModel3D = ViewportHelperPro.GenerateModelByEntity(_viewport, entities); MainModelLines = ViewportHelperPro.GentrateLineByEntity(_viewport, entities); MainModelLighting = ViewportHelperPro.GenerateLightingForModel(_viewport);