Created
December 7, 2023 11:28
-
-
Save glebov21/8aa8ff606cf92263272e65df1fa259e5 to your computer and use it in GitHub Desktop.
ffmpeg c# capture application with multiple monitors (screens) (no black screen)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private string AppName = "MyApp"; | |
public void StartRecording() | |
{ | |
StopRecording(); | |
WinProcess.OnGetAllWindowsResult += WinProcess_OnGetAllWindowsResult; | |
WinProcess.GetAllWindows(); //user32 EnumWindows | |
} | |
private void WinProcess_OnGetAllWindowsResult() | |
{ | |
WinProcess.OnGetAllWindowsResult -= WinProcess_OnGetAllWindowsResult; | |
WinProcessRECT rect = new WinProcessRECT(); | |
var primaryScreenDPI = PresentationSource.FromVisual(this).CompositionTarget.TransformToDevice.M11; | |
var primaryScreenWidth = (int)(SystemParameters.PrimaryScreenWidth * primaryScreenDPI); | |
var primaryScreenHeight = (int)(SystemParameters.PrimaryScreenHeight * primaryScreenDPI); | |
double appScreenDPI = primaryScreenDPI; //default | |
Rect appScreenBounds = new Rect(0, 0, primaryScreenWidth, primaryScreenHeight); //default | |
bool isAutogrammaFound = false; | |
WinProcess.WinProc autogrammaWindow = default(WinProcess.WinProc); | |
foreach (var wnd in WinProcess.GetAllWindowsResult) | |
{ | |
if (wnd.Title == AppName) | |
{ | |
autogrammaWindow = wnd; | |
WinProcess.GetWindowExtenedeFrameBounds(wnd.Handle, ref rect); //Note: windows without invisible borders | |
//=> dwmapi.dll DwmGetWindowAttribute(handle, (int)DwmWindowAttribute.DWMWA_EXTENDED_FRAME_BOUNDS, out lpRect, size); | |
WinProcess.MonitorInfoEx appMonitorInfo = new WinProcess.MonitorInfoEx(); | |
var hMonitor = GetNearestMonitorToWindow(wnd.Handle); // => user32.dll MonitorFromWindow(hwnd, 0x00000002); | |
WinProcess.GetMonitorInfo(hMonitor, appMonitorInfo); // => user32.dll GetMonitorInfo | |
appScreenDPI = WinProcess.GetDisplayScaleFactor(wnd.Handle); // => user32.dll GetDpiForWindow(windowHandle) / 96f | |
var dpiKoeff = appScreenDPI / primaryScreenDPI; | |
appScreenBounds = new Rect( | |
(int)(appMonitorInfo.WorkArea.Left * dpiKoeff), | |
(int)(appMonitorInfo.WorkArea.Top * dpiKoeff), | |
(int)((appMonitorInfo.WorkArea.Right - appMonitorInfo.WorkArea.Left) * dpiKoeff), | |
(int)((appMonitorInfo.WorkArea.Bottom - appMonitorInfo.WorkArea.Top) * dpiKoeff)); | |
if (rect.Left < -10000) //minimized | |
{ | |
; | |
} | |
else | |
{ | |
isAutogrammaFound = true; | |
} | |
break; | |
} | |
} | |
if (!isAutogrammaFound) | |
{ | |
_errorMessage = "Окно "+AppName+" не найдено"; | |
StopRecording(); | |
} | |
else | |
{ | |
//Clamp | |
rect.Right = (int)Clamp(rect.Right, appScreenBounds.Left, appScreenBounds.Right); | |
rect.Left = (int)Clamp(rect.Left, appScreenBounds.Left, appScreenBounds.Right); | |
rect.Bottom = (int)Clamp(rect.Bottom, appScreenBounds.Top, appScreenBounds.Bottom); | |
rect.Top = (int)Clamp(rect.Top, appScreenBounds.Top, appScreenBounds.Bottom); | |
WinProcess.SetForegroundWindow(autogrammaWindow.Handle); | |
StartRecording(rect); | |
} | |
} | |
private void StartRecording(WinProcessRECT rect) | |
{ | |
StopRecording(); | |
IsRecordingNow = true; | |
var captureApp = "desktop"; | |
//var captureApp = "title=MyApp"; //note: black screen | |
var width = rect.Right - rect.Left - 1; | |
var height = rect.Bottom - rect.Top - 1; | |
//need div 2 size (or error) | |
if (width % 2 != 0) | |
width -= 1; | |
if (height % 2 != 0) | |
height -= 1; | |
_currentVideoPath = SaveFilePathWithDate; | |
var args = $" -y -f gdigrab -offset_x {rect.Left} -offset_y {rect.Top} -video_size {width}x{height} -i {captureApp} {_vcodec} -vf \"setpts={(1f / _speed).ToString(CultureInfo.InvariantCulture)}*PTS\" \"{_currentVideoPath}\""; | |
try | |
{ | |
var processStartString = _recordingExeFilePath + args; | |
Debug.WriteLine(processStartString); | |
_recordingProcess = WinProcess.Start(processStartString, Path.GetDirectoryName(_recordingExeFilePath), true); //DEBUG | |
} | |
catch (Exception ex) | |
{ | |
Debug.WriteLine(ex); | |
_errorMessage = "Ошибка записи"; | |
StopRecording(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment