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
408 stars 93 forks source link

Intermittent failures when starting a recording #257

Closed BigHodge closed 2 months ago

BigHodge commented 1 year ago

I'm using ScreenRecorderLib to record the screen on a Windows Server 2019 Azure virtual machine during some automated UI tests. These tests run via NUnit and start the recorder; perform some actions on an application for 4-5 minutes; then stop the recorder. Once the recorder is Idle, if the test passed then the recorded mp4 file is deleted and NUnit moves onto the next test. Rinse and repeat. This all works perfectly - about 99% of the time. But occasionally the call to File.Delete fails with "System.UnauthorizedAccessException: Access to the path 'D:\.mp4' is denied."

I've got some output from the log and it looks like the recording fails almost as soon as it starts:

2023-07-22 00:27:49.148 [INFO]  [RecordingManager.cpp(RecordingManager:91)] >> Media Foundation started
2023-07-22 00:27:49.148 [DEBUG] [RecordingManager.cpp(ConfigureOutputDir:145)] >> Video output folder is ready
2023-07-22 00:27:49.148 [INFO]  [RecordingManager.cpp(operator ():230)] >> Starting recording task
2023-07-22 00:27:49.199 [ERROR] [OutputManager.cpp(InitializeVideoSinkWriter:427)] >> RETURN_ON_BAD_HR: hr=0xc00d36b4, error is: The data specified for the media type is invalid, inconsistent, or not supported by this object.
2023-07-22 00:27:49.199 [ERROR] [OutputManager.cpp(BeginRecording:73)] >> RETURN_ON_BAD_HR: hr=0xc00d36b4, error is: The data specified for the media type is invalid, inconsistent, or not supported by this object.
2023-07-22 00:27:49.200 [ERROR] [RecordingManager.cpp(StartRecorderLoop:411)] >> RETURN_RESULT_ON_BAD_HR: hr=0xc00d36b4, error is: The data specified for the media type is invalid, inconsistent, or not supported by this object.
2023-07-22 00:27:49.206 [DEBUG] [ScreenCaptureManager.cpp(CaptureThreadProc:799)] >> Exiting CaptureThreadProc
2023-07-22 00:27:49.207 [INFO]  [OutputManager.cpp(FinalizeRecording:102)] >> Cleaning up resources
2023-07-22 00:27:49.207 [INFO]  [OutputManager.cpp(FinalizeRecording:103)] >> Finalizing recording
2023-07-22 00:27:49.207 [INFO]  [RecordingManager.cpp(operator ():250)] >> Exiting recording task
2023-07-22 00:27:49.207 [DEBUG] [RecordingManager.cpp(SetRecordingCompleteStatus:349)] >> Changed Recording Status to Idle
2023-07-22 00:27:49.208 [DEBUG] [RecordingManager.cpp(SetRecordingCompleteStatus:377)] >> Sent Recording Failed callback
2023-07-22 00:27:53.598 [INFO]  [RecordingManager.cpp(~RecordingManager:117)] >> Media Foundation shut down

Any ideas what might be causing this? It sounds like the error reported in issue #29 from 4 years ago, which might have been a graphics driver issue? These tests are running across a number of Azure VMs, which are using some sort of Microsoft Hyper-V Video adapter, and I'm seeing this problem happening across multiple different machines. The problem does not happen very often - maybe only once or twice in 100 tests. And despite one test failing to start the recorder, the next test will record perfectly fine.

Normally the message that appears directly after "Starting recording task" is "Starting mouse click polling task" so maybe it is related to that? I am using these mouse options IsMouseClicksDetected = true, MouseLeftClickDetectionColor = "#FFFF00", MouseRightClickDetectionColor = "#FFFF00", MouseClickDetectionRadius = 30, MouseClickDetectionDuration = 100, IsMousePointerEnabled = true

I'm currently using v5.1.4 of ScreenRecorderLib. If I try upgrading to 5.2/5.3 then all the recordings come out as a totally black screen, with the mouse clicks all showing up in the top left corner. Was there a breaking change between these releases? I'm building a c# class library, targeting .NET Framework 4.8.

Thanks

sskodje commented 1 year ago

Hey! The black screen issue turned out to be bug that happens when using mouse click detection with "polling" option. I'll push a fix when i'm home from my vacation, or you can switch to using the "mouse hook" option in the mean time.

As for the intermittent errors, i don't have a good answer unfortunately. I've experience the issue before, the problem is the errors returned from Media Foundation is very generic and non-helpful. I can test with 10 000 recordings in a row without error, and it suddenly pops up again somewhere. It could be a race condition issue, a memory leak or some other resource leak. The reason you get the "access denied" error to the file path, is probably because the video encoder errors out internally and does not release the lock on the file.

Things you can try to debug the issue, is for example

BigHodge commented 1 year ago

Thanks for the feedback. These type of random failures are the worst to try to track down, so I appreciate the suggestions.

I did try switching to using WGC but the recorder fails with "Windows Graphics Capture requires Windows 10 version 1903 or greater". I'm using Server 2019 Build 1809 and have installed Media Foundation via Server Manager. Is there anything else I'd need to do to get this working? Or is Server 2019 not supported at all? (A comment on issue 238 suggested it was)

sskodje commented 1 year ago

I believe WGC should work on server 2019 from version 5.2.0 or later. So you might want to upgrade to the latest version and check if it works for you. Mouse click detection should work on the latest version when changing MouseClickDetectionMode to Hook.

BigHodge commented 1 year ago

Still no luck I'm afraid. I've upgraded to 5.3.0 but I'm still getting the same error about WGC requiring Windows 10. This is the version of Server 2019 that I have.

Server2019

But at least I can confirm that MouseDetectionMode.Hook is working correctly in this build and doesn't suffer from the issue with recordings just producing a black screen

sskodje commented 1 year ago

It seems the error indeed is correct. Server 2019 does not support WGC, as it's based on the Windows 10 1809 code base, while WGC requires version 1903.

sskodje commented 1 year ago

I'm leaning towards a resource leak or conflict, given the erratic nature of the error. I would make absolutely sure the previous recording is completed and the file is written before starting a new. You can use the OnRecordingComplete and OnRecordingFailed callbacks for this. There are system wide hard limits on concurrent instances of both Desktop Duplication and hardware transforms.