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

Screen recording doesn't stop and gets corrupted #223

Closed ranwer-dev closed 1 year ago

ranwer-dev commented 1 year ago

It's completely random, but many times during recording when I press Stop, it doesn't stop recording. Mostly this happens when I am recording audio in and audio out with my desktop. And if I exit the program, the recording will be corrupted and will not play.

These are the options I use for recording

RecorderOptions.OutputOptions.RecorderMode = RecorderMode.Video;

RecorderOptions.VideoEncoderOptions.Framerate = 30;
RecorderOptions.VideoEncoderOptions.IsFixedFramerate = true;
RecorderOptions.VideoEncoderOptions.Quality = 80;
RecorderOptions.VideoEncoderOptions.Encoder = new H264VideoEncoder
{
    BitrateMode = H264BitrateControlMode.Quality,
    EncoderProfile = H264Profile.High
};

RecorderOptions.AudioOptions.IsAudioEnabled = true;
RecorderOptions.AudioOptions.IsInputDeviceEnabled = true;
RecorderOptions.AudioOptions.IsOutputDeviceEnabled = true;
RecorderOptions.AudioOptions.AudioInputDevice = (AudioDeviceComboBox.SelectedItem as AudioDevice).DeviceName;
RecorderOptions.AudioOptions.AudioOutputDevice = (SystemAudioDeviceComboBox.SelectedItem as AudioDevice).DeviceName;
RecorderOptions.AudioOptions.InputVolume = 1;
RecorderOptions.AudioOptions.OutputVolume = 1;

RecorderOptions.MouseOptions.IsMousePointerEnabled = true;

RecorderOptions.SourceOptions.RecordingSources = new List<RecordingSourceBase>
    {
        new DisplayRecordingSource(monitor)
        {
            OutputSize = monitor.OutputSize,
            Position = monitor.Position,
            RecorderApi = RecorderApi.WindowsGraphicsCapture,
            IsBorderRequired = false
        }
    };
}
sskodje commented 1 year ago

It sounds like a hardware encoder issue. I'd try disabling hardware encoder in VideoEncoderOptions to check if the problem goes away. If it's the hardware encoder, updating or reinstalling graphics drivers may fix the issue.

ranwer-dev commented 1 year ago

I have added RecorderOptions.VideoEncoderOptions.IsHardwareEncodingEnabled = false; but still video recording hung and clicking Finish didn't do anything.

ranwer-dev commented 1 year ago

One more instance. I was trying to record a youtube video of 7 minutes, with just the speaker audio, and no mic audio. When I stopped it, it failed :(

Attaching the log here 20230127.log

ranwer-dev commented 1 year ago

One more. While recording a Youtube video, with both Mic & Speaker audio. In task manage it was taking 7% CPU, suddenly it dropped to less than 1% and when I clicked Finish, it failed to stop. Here's the log file failed-20230127.log

sskodje commented 1 year ago

I fixed a couple memory leaks that may be related to your problems, but unfortunately i haven't been able to reproduce it. From your logs, it looks like a complete meltdown in Windows Graphics Capture.

Does it work better if you use Desktop Duplication api?

ranwer-dev commented 1 year ago

It happened again. This time with Desktop Duplication. Here is the log 20230204.log

I was recording the screen with both mic & speaker sound.

Mic Microphone Properties 2023-02-04 at 8 43 04 AM

Speaker Speakers Properties 2023-02-04 at 8 43 25 AM

ranwer-dev commented 1 year ago

Now I just started recording Speaker sound and no mic. But it still hung after almost 3 minutes of recording. Here's log 20230204.log

ranwer-dev commented 1 year ago

Anything else I can do to help you debug this?

ranwer-dev commented 1 year ago

I think I can reproduce this every time now. Steps to reproduce

  1. Play a youtube video
  2. Start recording screen with only Speaker Audio
  3. After a few seconds, refresh the page. Youtube will refresh and start playing videos again.
  4. After a few moments, the video gets stuck and will not Finish recording now.

See the demo video

https://user-images.githubusercontent.com/92986100/216749163-b911641f-a17f-44b5-bd0e-631269747613.mp4

sskodje commented 1 year ago

It would be helpful if you can do a failed recording and setting LogOptions with LogSeverityLevel set to Trace. Also, you can open dxdiag.exe and choose the "save all information" option, which should produce a .txt file with your system information.

ranwer-dev commented 1 year ago

Here's another failed recording with the trace log

20230218.log and dxdiag info DxDiag.txt

https://user-images.githubusercontent.com/92986100/219827360-edaba4c9-508c-452c-b9ae-8e8826dd79a1.mp4

sskodje commented 1 year ago

After you get an buffer underrun on your audio capture, there's no more logging for 9 whole seconds, meaning the capture loop must have stopped somewhere. The reason the stop command is not working, is because the entire thread is deadlocked.

I pushed some more logging and replaced some suspect infinite waits with timeouts, so we can try coax a more descriptive error out of it.

ranwer-dev commented 1 year ago

Now I see the C++ Runtime error when I try to stop the video in the above scenario image

Here's the log file Log.txt

sskodje commented 1 year ago

Do you see where the code breaks on that error?

ranwer-dev commented 1 year ago

The app just crashes. I tried the Abort, Retry, and Ignore options but it crashes in all cases. Here's the video

https://user-images.githubusercontent.com/92986100/220369076-8a9eecd6-47ca-43db-88b6-0559fc410b1f.mp4

sskodje commented 1 year ago

If you click "retry", don't the debugger break at a line, so you get a stack trace? Perhaps check if "enable native code debugging" is enabled under project properties -> debug for the test app.

ranwer-dev commented 1 year ago

enable native code debugging has worked. It breaks here

[[noreturn]] inline void rethrow_exception(_In_ exception_ptr _Ptr) {
    __ExceptionPtrRethrow(&_Ptr);
}

Call Stack

    ScreenRecorderLib.dll!std::rethrow_exception(std::exception_ptr _Ptr) Line 312  C++
    ScreenRecorderLib.dll!Concurrency::details::_ExceptionHolder::_RethrowUserException() Line 796  C++
    ScreenRecorderLib.dll!Concurrency::details::_Task_impl_base::_Wait() Line 1622  C++
    ScreenRecorderLib.dll!Concurrency::task<unsigned char>::wait() Line 3306    C++
    ScreenRecorderLib.dll!Concurrency::task<void>::wait() Line 4228 C++
    ScreenRecorderLib.dll!LoopbackCapture::StopCapture() Line 451   C++
    ScreenRecorderLib.dll!LoopbackCapture::~LoopbackCapture() Line 16   C++
    [External Code] 
    ScreenRecorderLib.dll!AudioManager::~AudioManager() Line 14 C++
    [External Code] 
    ScreenRecorderLib.dll!RecordingManager::StartRecorderLoop(const std::vector<RECORDING_SOURCE *,std::allocator<RECORDING_SOURCE *>> & sources, const std::vector<RECORDING_OVERLAY *,std::allocator<RECORDING_OVERLAY *>> & overlays, IStream * pStream) Line 756    C++
    ScreenRecorderLib.dll!RecordingManager::BeginRecording::__l2::<lambda>() Line 243   C++
    [External Code] 
    [Async Call]    
    ScreenRecorderLib.dll!RecordingManager::BeginRecording(std::wstring path, IStream * stream) Line 230    C++
    ScreenRecorderLib.dll!RecordingManager::BeginRecording(std::wstring path) Line 192  C++

Perhaps with line numbers, it will be more helpful

ScreenRecorderLib.dll!std::rethrow_exception(std::exception_ptr _Ptr) Line 312
    at C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.34.31933\include\exception(312)
ScreenRecorderLib.dll!Concurrency::details::_ExceptionHolder::_RethrowUserException() Line 796
    at C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.34.31933\include\ppltasks.h(796)
ScreenRecorderLib.dll!Concurrency::details::_Task_impl_base::_Wait() Line 1622
    at C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.34.31933\include\ppltasks.h(1622)
ScreenRecorderLib.dll!Concurrency::task<unsigned char>::wait() Line 3306
    at C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.34.31933\include\ppltasks.h(3306)
ScreenRecorderLib.dll!Concurrency::task<void>::wait() Line 4228
    at C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.34.31933\include\ppltasks.h(4228)
ScreenRecorderLib.dll!LoopbackCapture::StopCapture() Line 451
    at ScreenRecorderLib\ScreenRecorderLibNative\LoopbackCapture.cpp(451)
ScreenRecorderLib.dll!LoopbackCapture::~LoopbackCapture() Line 16
    at ScreenRecorderLib\ScreenRecorderLibNative\LoopbackCapture.cpp(16)
[External Code]
ScreenRecorderLib.dll!AudioManager::~AudioManager() Line 14
    at ScreenRecorderLib\ScreenRecorderLibNative\AudioManager.cpp(14)
[External Code]
ScreenRecorderLib.dll!RecordingManager::StartRecorderLoop(const std::vector<RECORDING_SOURCE *,std::allocator<RECORDING_SOURCE *>> & sources, const std::vector<RECORDING_OVERLAY *,std::allocator<RECORDING_OVERLAY *>> & overlays, IStream * pStream) Line 756
    at ScreenRecorderLib\ScreenRecorderLibNative\RecordingManager.cpp(756)
ScreenRecorderLib.dll!RecordingManager::BeginRecording::__l2::<lambda>() Line 243
    at ScreenRecorderLib\ScreenRecorderLibNative\RecordingManager.cpp(243)
[External Code]
[Async Call]
ScreenRecorderLib.dll!RecordingManager::BeginRecording(std::wstring path, IStream * stream) Line 230
    at ScreenRecorderLib\ScreenRecorderLibNative\RecordingManager.cpp(230)
ScreenRecorderLib.dll!RecordingManager::BeginRecording(std::wstring path) Line 192
    at ScreenRecorderLib\ScreenRecorderLibNative\RecordingManager.cpp(192)
sskodje commented 1 year ago

I added some more error handling with 7d5ee86 and 2fa35fe, it should hopefully stop the crashing.

ranwer-dev commented 1 year ago

I have tried several recordings and unable to reproduce the issue. It seems to be working fine now 👍