Author Topic: FFcapture V 2.00 (Code compatible WD16+)  (Read 172 times)

Patrice Terrier

  • Administrator
  • *****
  • Posts: 1874
    • zapsolution
FFcapture V 2.00 (Code compatible WD16+)
« on: August 24, 2021, 07:35:52 pm »
Version 2.00

Nouveautés :
Le code a été modifié en profondeur pour détecter en temps réel l'ouverture et la fermeture des applications du bureau.
La fonction "ExeRun" de WINDEV a été remplacée par "ProcessCreate" (GDImage) qui permet de modifier les paramètres de lancement de la console FFmpeg, celle-ci est désormais lancée en mode masqué ce qui la rend indétectable.
La fonction "PidToHandle" permet de retrouver le handle de n'importe quel fenêtre à partir de son identifiant PID.
On peut ajuster le canal alpha de n'importe quel vignette DWM, ce qui dans le cas de vignettes multiples permet de montrer facilement celle qui est active.

A propos du format .mp4 utilisé :
Celui-ci est compatible avec "Microsoft Media Foundation".
Ce qui permet d'utiliser "Films et TV" pour voir les vidéos qui sont enregistrées dans le dossier "C:\Users\VotreNom\Videos\FFcapture".


Version 1.00

Ce projet est destiné à être utilisé avec FFplayer version 1.03+ (disponible sur www.objreader.com),
ou tout player vidéo disposant des bons codecs (VLC par exemple).



FFcapture est basé sur FFmpeg, pour créer des captures vidéo d'applications fonctionnant sous Windows.
Une combo permet de sélectionner la cible, qui est visualisée sous forme de vignette DWM.
Un bouton permet de démarrer la capture qui est stockée dans le dossier "Video" de Windows.

Pendant toute la durée de la capture, l'application est réduite sur la barre des tâches.
L'enregistrement cesse dès que FFcapture est réaffiché.

Le projet est au format WD16, et fonctionne (en théorie) avec toutes les versions WinDev supérieures.

Note : Le projet fonctionne uniquement en mode 64-bit.

La partie la plus importante du programme se trouve dans CreateCaptureProcess :
Code: [Select]
FUNCTION CreateCaptureProcess()
bRet is boolean
IF gP.hStdOutput THEN
bRet = API(KERNEL32, "FreeConsole")
END

IF gP.hConsole THEN
SetWindowLongPtr(gP.hConsole, GWL_EXSTYLE, gP.OldStyle)
SetWindowLongPtr(gP.hConsole, GWL_HWNDPARENT, gP.OldParent)
gP.hConsole = 0
END

hConsole is system int = 0

lpGUID is stGUID
////sFOLDERID_PublicVideos = "{2400183A-6185-49FB-A2D8-4A392A602BA3}"
//lpGUID.D1 = 0x2400183A
//lpGUID.D2 = 0x6185
//lpGUID.D3 = 0x49FB
//lpGUID.D4[1] = 0xA2
//lpGUID.D4[2] = 0xD8
//lpGUID.D4[3] = 0x4A
//lpGUID.D4[4] = 0x39
//lpGUID.D4[5] = 0x2A
//lpGUID.D4[6] = 0x60
//lpGUID.D4[7] = 0x2B
//lpGUID.D4[8] = 0xA3

//sFOLDERID_UserVideos = {18989B1D-99B5-455B-841C-AB7C74E4DDFC}
lpGUID.D1 = 0x18989B1D
lpGUID.D2 = 0x99B5
lpGUID.D3 = 0x455B
lpGUID.D4[1] = 0x84
lpGUID.D4[2] = 0x1C
lpGUID.D4[3] = 0xAB
lpGUID.D4[4] = 0x7C
lpGUID.D4[5] = 0x74
lpGUID.D4[6] = 0xE4
lpGUID.D4[7] = 0xDD
lpGUID.D4[8] = 0xFc

sCaptureFile is string
nPath is system int = Null
nRet is int = API("Shell32.dll", "SHGetKnownFolderPath", &lpGUID, 0, 0, &nPath)
IF nRet = 0 THEN
sCaptureFile = StringRetrieve(nPath, srUNICODEAddress)
sCaptureFile = sCaptureFile + "\FFcapture"
fMakeDir(sCaptureFile)
sCaptureFile = CompleteDir(sCaptureFile) + ClassName[Combo_Capture] + ".mp4"
ELSE
sCaptureFile = ExePath() + "capture.mp4"
END
EDT_CaptureFile = sCaptureFile

sExeName is string = ExePath() + "ffmpeg.exe"

tmi is MONITORINFO
hMonitor is int = MonitorFromWindow(gP.hCapture, MONITOR_DEFAULTTONEAREST)
tmi.cbSize = Dimension(tmi)
GetMonitorInfo(hMonitor, tmi)
screenWidth is int = Abs(tmi.rcMonitor.nRight - tmi.rcMonitor.nLeft)
screenHeight is int = Abs(tmi.rcMonitor.nBottom - tmi.rcMonitor.nTop)
x is int = tmi.rcMonitor.nLeft
y is int = tmi.rcMonitor.nTop
w is int = Abs(tmi.rcMonitor.nRight - tmi.rcMonitor.nLeft)
h is int = Abs(tmi.rcMonitor.nBottom - tmi.rcMonitor.nTop)

fDelete(sCaptureFile)

//Display devices list
//ffmpeg -list_devices true -f dshow -i dummy

//Recording from camera using the microphone
//ffmpeg -f dshow -i video="USB2.0 HD UVC WebCam":audio="Microphone (Realtek High Definition Audio)" test.mp4

sAudioDevice is string = Quote + Combo_Audio..DisplayedValue + Quote
//r is RECT; GetWindowRect(gP.hCapture, r)
//x = r.nLeft
//y = r.nTop
//w = Width(r)
//h = Height(r)
//sCmdLine is string = StringBuild(" -f dshow -i audio=%1 -f gdigrab -itsoffset %2 -framerate film -offset_x %3 -offset_y %4 -video_size %5x%6 -i desktop %7", sAudioDevice, "00:00:0.6", NumToString(x), NumToString(y), NumToString(w), NumToString(h), sCaptureFile)
sCmdLine is string = StringBuild(" -f dshow -i audio=%1 -f gdigrab -itsoffset %2 -framerate 30 -offset_x %3 -offset_y %4 -video_size %5x%6 -i desktop %7", sAudioDevice, "00:00:0.6", NumToString(x), NumToString(y), NumToString(w), NumToString(h), sCaptureFile)
nTickMax is unsigned int = GetTickCount() + 4000

pid is unsigned int = ExeRun(sExeName + sCmdLine, exeActive, exePID)
IF pid THEN
WHILE hConsole = 0
Sleep(5)
// Detect console
hConsole = FindWindow("ConsoleWindowClass", sExeName)
IF hConsole THEN
w = 979; h = 512; x = 0; y = -h
MoveWindow(hConsole, x, y, w, h, 0)
END
IF GetTickCount() > nTickMax THEN BREAK // Avoid infinite loop
END
END

IF hConsole THEN
gP.hConsole = hConsole

gP.OldStyle = GetWindowLongPtr(gP.hConsole, GWL_EXSTYLE)
SetWindowLongPtr(gP.hConsole, GWL_EXSTYLE, gP.OldStyle | WS_EX_TOOLWINDOW)// | 0x00000004)//WS_EX_NOPARENTNOTIFY)
gP.OldParent = GetWindowLongPtr(gP.hConsole, GWL_HWNDPARENT)
SetWindowLongPtr(gP.hConsole, GWL_HWNDPARENT, gP.hMain)

IF AttachConsole(pid) THEN
gP.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE)
bRet = GetConsoleScreenBufferInfo(gP.hStdOutput, &gP.bif) //Get console row and column
END
END

RESULT hConsole
« Last Edit: September 06, 2021, 02:55:09 pm by Patrice Terrier »
Patrice
(Always working with the latest Windows version available...)