Hello all,
I'm working on an application that should run on Windows 10 and 11.
The code that captures the screen display and camera output needs to run in the background (as a service/scheduled task, etc), regardless of active user sessions. In other words, it must work even when no user is logged in and continue to record through sign out/switch user events.
(Unfortunately, the forum's policy does not allow me to attach files or include URLs as I'm a new user so I had to "mask" the links below to get around it - my sincere apologies for the extea work)
I've looked at sskodje/ScreenRecorderLib on GitHub which uses the MS Media Foundation but due to Session 0 isolation, that does not work at all in a service context (see sskodje/ScreenRecorderLib/issues/197).
I therefore looked into ffmpeg and dshow source filters. I'm aware of two functional ones:
- Screen Capture DirectShow Source Filter from Unreal Streaming Technologies, aka "UScreenCapture"
- GitHub: rdp/screen-capture-recorder-to-video-windows-free
The former is the only one that records the display when there's no active user session (starts recording as soon as logonui is launched). The latter does not capture the output at all (in layman's terms - black screen) until a user logs in (gdigrab
also behaves the same way).
However, due to what I believe is DPI autoscaling, when running in service context, "UScreenCapture" only captures a bit of the screen and in the wrong resolution. It works perfectly well when launched from cmd in an interactive session.
The ffmpeg
command I use is:
ffmpeg -analyzeduration 2147483647 -probesize 2147483647 -rtbufsize 1500M -f dshow -i video="UScreenCapture" -c:v libx264 -profile:v baseline -x264opts level=31 -pix_fmt yuv420p -preset ultrafast -y c:\Temp\yes.mp4
The screen resolution is:
> wmic path Win32_VideoController get VideoModeDescription,CurrentVerticalResolution,CurrentHorizontalResolution /format:value
CurrentHorizontalResolution=3840
CurrentVerticalResolution=2160
VideoModeDescription=3840 x 2160 x 4294967296 colors
And Scale
is set to 300% which Windows deems the recommended value.
I've tried setting the resolution explicty by passing -s 3840x2160
and also experimented with various FFmpeg -vf "scale=
options but to no avail.
I also played with "Override High DPI Scaling Behavior" options as per various Stackoverflow posts but no matter what value I set for that, I cannot get it to work.
I did run the above wmic
command in service context to make sure the resolution is not set differently in that case - it is not.
To run as a service for testing purposes, I use github /winsw/winsw (available as standalone executable - winsw/winsw/releases/tag/v3.0.0-alpha.11).
I use the following xml:
<service>
<id>zj-vid</id>
<name>zj-vid</name>
<description>FFmpeg Screen Recorder</description>
<executable>C:\ffmpeg\bin\ffmpeg</executable>
<arguments> -analyzeduration 2147483647 -probesize 2147483647 -rtbufsize 1500M -f dshow -i video="UScreenCapture" -c:v libx264 -profile:v baseline -x264opts level=31 -pix_fmt yuv420p -preset ultrafast -y c:\Temp\yes.mp4</arguments>
<log mode="roll"></log>
</service>
And configure the service thusly:
> c:\bin\WinSW-x64.exe install c:\bin\zj_vid.xml
I'd appreciate any help in arriving at a working solution. Ideally, I'd rather not use the "UScreenCapture" source filter at all as it is not FOSS and is no longer maintained. However, I can't seem to find any other functional examples (other than the one I referenced which does not work and also cannot be rebuilt with VS 2022). I did look into microsoft/Windows-classic-samples/blob/main/Samples/Win7Samples/multimedia/directshow/filters/pushsource/PushSourceDesktop.cpp but, as the name implies, this was also intended to run on Windows 7 and while I can build strmbasd.lib
(Windows-classic-samples-main\Samples\Win7Samples\multimedia\directshow\baseclasses\baseclasses.sln) with VS 2022 on Windows 10, it does not actually load.
If there's another route of accomplishing the end goal (as stated above), I am certainly happy to take it.
I know that this is technically possible because Echo360 is capable of running this way on Windows 10 and while I do not have access to that code, EchoVideo-Device-Monitor-Overview-Administrators does state:
The EchoVideo Device Service is a service-level version of the Device Monitor software that does not require a user to be logged into the podium PC
I have looked at a machine where it was installed and it's clear that it too is using FFmpeg (though I am not sure what source filter is involved).
Many many thanks in advance for any pointers,