From 00b6f39201f822204f1a8a4c97f7b77c08f123fd Mon Sep 17 00:00:00 2001 From: emil28092005 Date: Fri, 19 Jun 2026 09:01:55 +0300 Subject: [PATCH] fix: video recording captures every frame + dynamic FPS for FFmpeg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Removed skipFrames logic — capture every frame for reliability - FFmpeg framerate set to actual FPS (capped at 60) instead of hardcoded 30 - Added -vf fps=30 filter to downsample to 30fps in output - First frame: CapturedFrame is null (no previous capture), skipped naturally - Second frame onwards: data available from previous frame's GPU copy --- Videos/cortex_20260619_090013.mp4 | Bin 0 -> 261 bytes src/CortexEngine.App/Program.cs | 34 +++++++++++++----------------- 2 files changed, 15 insertions(+), 19 deletions(-) create mode 100644 Videos/cortex_20260619_090013.mp4 diff --git a/Videos/cortex_20260619_090013.mp4 b/Videos/cortex_20260619_090013.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..862f49648777ee248bc8b232c07d0600e621c1fa GIT binary patch literal 261 zcmZQzU{FXasVvAW&d+6FU}6B#Kx~v)mTZ_?U}DI?z`&7Kl$r{nb5jyafb`Ye{QNQ? zos(OZkpiTV0P_nlhmnB+h!6mU0~AK%J0MhIV=(~*6H8M{5`lDNZYr1tsZ-2I$teOc yKp;0Ivna8kAP2&OkUE(;#UKZ(tSrgT2huV?_k#=pTkn%tmS$$8XRK#vU;qH;LL|HZ literal 0 HcmV?d00001 diff --git a/src/CortexEngine.App/Program.cs b/src/CortexEngine.App/Program.cs index b3edcb0..d096435 100644 --- a/src/CortexEngine.App/Program.cs +++ b/src/CortexEngine.App/Program.cs @@ -328,7 +328,8 @@ class Program var w = window.Width; var h = window.Height; - var ffmpegArgs = $"-y -f rawvideo -pixel_format rgba -video_size {w}x{h} -framerate 30 -i - -c:v libx264 -preset fast -crf 23 -pix_fmt yuv420p {recordingPath}"; + var fps = (int)Math.Round(1000.0 / timing.DeltaTime); + var ffmpegArgs = $"-y -f rawvideo -pixel_format rgba -video_size {w}x{h} -framerate {Math.Min(fps, 60)} -i - -c:v libx264 -preset fast -crf 23 -pix_fmt yuv420p -vf fps=30 {recordingPath}"; var psi = new ProcessStartInfo { @@ -388,30 +389,25 @@ class Program renderer.RenderWorld(world); queue.CompletePendingScreenshots(); - // If recording, get captured frame and write to FFmpeg if (isRecording && ffmpegProcess != null && !ffmpegProcess.HasExited) { - skipFrames++; - if (skipFrames >= 2) // Capture every 2nd frame for 30fps at ~60fps + var frameData = vkRenderer.CapturedFrame; + if (frameData != null && frameData.Length > 0) { - skipFrames = 0; - var frameData = vkRenderer.CapturedFrame; - if (frameData != null && frameData.Length > 0) + try { - try - { - ffmpegProcess.StandardInput.BaseStream.Write(frameData, 0, frameData.Length); - ffmpegProcess.StandardInput.BaseStream.Flush(); - recordedFrames++; - } - catch (Exception ex) - { - Console.WriteLine($"[App] FFmpeg write error: {ex.Message}"); - isRecording = false; - } + ffmpegProcess.StandardInput.BaseStream.Write(frameData, 0, frameData.Length); + ffmpegProcess.StandardInput.BaseStream.Flush(); + recordedFrames++; } - } } + catch (Exception ex) + { + Console.WriteLine($"[App] FFmpeg write error: {ex.Message}"); + isRecording = false; + } + } + } frames++; if (timing.TotalTime - lastFpsTime >= 1.0)