sskodje / ScreenRecorderLib

A .NET library for screen recording in Windows, using native Microsoft Media Foundation for realtime encoding to h264 video or PNG images.
MIT License
414 stars 94 forks source link

Black frames at start if recording is Paused on start #248

Closed ranwer-dev closed 1 year ago

ranwer-dev commented 1 year ago

After this ticket https://github.com/sskodje/ScreenRecorderLib/issues/233, the initial pause option was added. So now if we call ScreenRecorder.Pause(); right after ScreenRecorder.Record(); the recording remains in Pause state which can be resumed later.

But I have seen on Windows 10, that if this Pause option is used, it adds a black screen for 0.5/1 second at the start of recording.

Also sometimes if a partial screen is recorded, it adds fullscreen frames for 0.5/1 second before using the correct area.

How this can be fixed?

https://github.com/sskodje/ScreenRecorderLib/assets/92986100/4ea0c0e5-5d65-48a0-b584-bf8f5311fe2b

sskodje commented 1 year ago

I'm not able to reproduce. Here's a small example code i used to test.


using ScreenRecorderLib;
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;

    class Program
    {
        static void Main(string[] args)
        {
            var source = DisplayRecordingSource.MainMonitor;
            source.RecorderApi = RecorderApi.WindowsGraphicsCapture;
            var opts = new RecorderOptions
            {
                SourceOptions = new SourceOptions
                {
                    RecordingSources = { { source } }
                }
            };
            Recorder rec = Recorder.CreateRecorder(opts);
            Recorder rec2 = Recorder.CreateRecorder(opts);
            rec.OnRecordingComplete += (source, e) =>
            {
                Console.WriteLine($"Recording complete: {e.FilePath}");
            };
            rec2.OnRecordingComplete += (source, e) =>
            {
                Console.WriteLine($"Recording complete: {e.FilePath}");
            };

            Console.WriteLine("Press ENTER to start recording or ESC to exit");
            while (true)
            {
                ConsoleKeyInfo info = Console.ReadKey(true);
                if (info.Key == ConsoleKey.Enter)
                {
                    break;
                }
                else if (info.Key == ConsoleKey.Escape)
                {
                    return;
                }
            }
            ManualResetEvent completionEvent = new ManualResetEvent(false);
            string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss");
            Console.WriteLine("Starting recording");
            int count = 5;
            Task.Run(async () =>
                {
                    for (int i = 0; i < count; i++)
                    {
                        var currentRecorder = i % 2 == 0 ? rec : rec2;
                        var nextRecorder = i % 2 == 0 ? rec2 : rec;

                        if (currentRecorder.Status == RecorderStatus.Paused)
                        {
                            currentRecorder.Resume();
                        }
                        else
                        {
                            currentRecorder.Record(Path.Combine(Path.GetTempPath(), "ScreenRecorder", timestamp, i + ".mp4"));
                        }

                        await WaitForIdle(nextRecorder);
                        if (i < count)
                        {
                            nextRecorder.Record(Path.Combine(Path.GetTempPath(), "ScreenRecorder", timestamp, i + 1 + ".mp4"));
                            nextRecorder.Pause();
                        }
                        await Task.Delay(5000);
                        currentRecorder.Stop();
                    }
                    completionEvent.Set();
                });

            completionEvent.WaitOne();
            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }

        private static async Task WaitForIdle(Recorder rec)
        {
            if (rec.Status == RecorderStatus.Idle)
            {
                return;
            }
            else
            {
                SemaphoreSlim semaphore = new SemaphoreSlim(0, 1);
                EventHandler<RecordingStatusEventArgs> handler = delegate (object s, RecordingStatusEventArgs args)
                {
                    if (args.Status == RecorderStatus.Idle)
                    {
                        semaphore.Release();
                    }
                };
                rec.OnStatusChanged += handler;
                await semaphore.WaitAsync();
                rec.OnStatusChanged -= handler;
            }
        }
    }
ranwer-dev commented 1 year ago

After updating to the latest master branch, the issue is no more happening.