Recording desktop with ffmpeg & AutoHotkey

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
Joe Glines
Posts: 770
Joined: 30 Sep 2013, 20:49
Location: Dallas
Contact:

Recording desktop with ffmpeg & AutoHotkey

19 Sep 2018, 08:55

In my interview with RickC he mentioned he uses ffmpeg & AutoHotkey to record his desktop. He shared his code with me (which included some php as well as other things) . I streamlined the idea and came up with the below which only needs AutoHotkey & ffmpeg. (ffmpeg doesn't "install", you just need the executable on your computer)

Anyway, y'all will want to tweak it to your settings but it shouldn't be too hard to do that. You can see the video tutorial below where I discuss a few of the parameters. Also, while below is a stand-alone script, I actually embedded it into my main AutoHotkey script so I don't have a separate one running! :)

Code: Select all

#SingleInstance,Force ;ensure only 1 version running
SetTitleMatchMode, 3 ;to make sure winMinimize and Sending Control C to ConsoleWindowClass works down below
DetectHiddenWindows,On ;Added becauase minimizing the window

; General Documentation := https://ffmpeg.org/ffmpeg-devices.html#gdigrab  Documentation on gdigrab from ffmpeg.
; Get list of devices ffmpeg:= ffmpeg -list_devices true -f dshow -i dummy
; Cropping specific area := https://stackoverflow.com/questions/6766333/capture-windows-screen-with-ffmpeg/47591299
;********************Control+Shift+R=Start Recording***********************************
^+r::
FileDelete, %A_ScriptDir%\temp.mp4
sleep, 50

ff_params = -rtbufsize 1500M  -thread_queue_size 512 -f gdigrab -video_size 1920x1080  -i desktop -f dshow -i audio="Microphone (Yeti Stereo Microphone)" -crf 0  -filter:a "volume=1.5" -vcodec libx264 temp.mp4
run ffmpeg %ff_params% ;run ffmpeg with command parameters

sleep, 150 ;Wait for Command window to appear
WinMinimize, ahk_class ConsoleWindowClass ;minimize the CMD window
return

;********************Control+Shift+S= Stop Recording***********************************
^+s::
ControlSend, , ^c, ahk_class ConsoleWindowClass  ; send ctrl-c to command window which stops the recording
sleep, 500
InputBox, New_File_Name,File name,What would you like to name your .mp4 file?,,300,130 ;Get a file name for your new video
if (New_File_Name = "") or (Error = 1) ;If you don't give it a name, it won't rename it and won't run it
	return 

Run, explore %A_ScriptDir% ;Open the working folder
FileMove, %A_ScriptDir%\temp.mp4, %A_ScriptDir%\%New_File_Name%.mp4  ; Rename the temp file to your new file.
Run, %A_ScriptDir%\%New_File_Name%.mp4 ;Now play the new file name
return
Sign-up for the 🅰️HK Newsletter

ImageImageImageImage:clap:
AHK Tutorials:Web Scraping | | Webservice APIs | AHK and Excel | Chrome | RegEx | Functions
Training: AHK Webinars Courses on AutoHotkey :ugeek:
YouTube

:thumbup: Quick Access Popup, the powerful Windows folders, apps and documents launcher!
User avatar
AlleyArtwork
Posts: 44
Joined: 09 Jun 2015, 21:08

Re: Recording desktop with ffmpeg & AutoHotkey

19 Sep 2018, 15:08

Trying this out, but I believe it is failing running the ff_params.
I removed the winclose options, but the window still closes immediately.
Added in an if ErrorLevel MsgBox, % "Error=" A_LastError trying to see if i'm able to capture error to find out what parameter in the ff_params might be making it fail, but i get "2" as the error, so still trying to figure that one out. Once i get it working looks like it will actually be pretty handy!
User avatar
Joe Glines
Posts: 770
Joined: 30 Sep 2013, 20:49
Location: Dallas
Contact:

Re: Recording desktop with ffmpeg & AutoHotkey

19 Sep 2018, 15:12

I'd just try and run it from the command prompt to get it running reliably, then switch over to adapting it with AutoHotkey. Mine kep mentiontiong errors w/o the ff_params so I had it there.
Sign-up for the 🅰️HK Newsletter

ImageImageImageImage:clap:
AHK Tutorials:Web Scraping | | Webservice APIs | AHK and Excel | Chrome | RegEx | Functions
Training: AHK Webinars Courses on AutoHotkey :ugeek:
YouTube

:thumbup: Quick Access Popup, the powerful Windows folders, apps and documents launcher!
Asmodeus
Posts: 57
Joined: 19 Oct 2015, 15:53

Re: Recording desktop with ffmpeg & AutoHotkey

19 Sep 2018, 16:03

Hey Joe :roll:

I ran into your script yesterday. I was looking for something like this. I had already some complicated solutions based on powershell and irfanview but I was not satisfied. I needed a "fast quick and dirty screen recorder without audio", so I changed your script a little bit to fit my needs and made it hopefully a little more user friendly. Thanks for sharing! :thumbup:

Code: Select all

#SingleInstance,Force ;ensure only 1 version running
Menu, Tray, Icon, C:\Windows\System32\shell32.dll, 287
CoordMode, ToolTip, Screen
SetTitleMatchMode, 3 ;to make sure winMinimize and Sending Control C to ConsoleWindowClass works down below
DetectHiddenWindows,On ;Added because minimizing the window


;*************************** User Help *******************************************
SplashTextOn,300,100, Screen Recorder, `n* Press Control+Shift+R to Start Recording *`n* Press Control+Shift+S to Stop Recording *`n * Video file is saved on your desktop. *
Sleep 5000
SplashTextOff 
;********************************************************************************


;********************Control+Shift+R= Start Recording***********************************
^+r:: 

    SplashTextOn,300,100, Start Recording, `n* Recording will start in 3 seconds. * `n* Press CTRL+SHIFT+S to stop recording. * 
    Sleep 3000
    SplashTextOff 

    FileName:=A_Desktop . "\" . A_Now . ".mp4" 
    
    ; Change this parameters to meet your needs / hardware
    ff_params = -f gdigrab -video_size 1920x1080 -framerate 10 -i desktop  -pix_fmt yuv420p -f mp4 %FileName%
 
    ; Run ffmpeg and start recording
    Run ffmpeg %ff_params%,,hide UseErrorLevel ;run ffmpeg with command parameters
    if ErrorLevel = ERROR
        MsgBox 0x10, Software Failure, Press OK to continue. `n`nTry this to solve:`n1. Download ffmpeg.exe and place it next to this script.`n2. Edit ff_params to meet your needs / hardware.

return
;********************************************************************************
 
 
;********************Control+Shift+S= Stop Recording***********************************
^+s::
    ControlSend, , ^c, ahk_class ConsoleWindowClass  ; send ctrl-c to command window which stops the recording
 
    SplashTextOn,300,100, Recording Stopped, `n* Check the video file on your desktop. *
    Sleep 3000
    SplashTextOff 
   
return
;********************************************************************************
r2997790
Posts: 71
Joined: 02 Feb 2017, 02:46

Re: Recording desktop with ffmpeg & AutoHotkey

20 Sep 2018, 05:29

Thank to you both for this great script (and amends). FFMPEG is indeed fantastic (and when combined with ImageMagick even more amazing).

Personally I can't get the audio working but I'll nut that out when I have time.

Next steps... to be able to draw a zone it record and to output an animated gif instead of an mp4.

Too many scripts to write and not enough time :)

Thanks everyone for sharing!
User avatar
Joe Glines
Posts: 770
Joined: 30 Sep 2013, 20:49
Location: Dallas
Contact:

Re: Recording desktop with ffmpeg & AutoHotkey

20 Sep 2018, 08:13

Great idea Rick / r2997790! I took your idea and added it into my previous script (as well as dumped it into my main AutoHotkey file.) After it creates the mp4 file, it asks if you want to convert it to an animated gif. I'd probably know at time of recording so I just added it here...

Code: Select all

;********************Record desktop with ffmpeg***********************************
^+r::
folder:="C:\temp"
FileDelete, %folder%\temp.mp4
sleep, 50

ff_params = -rtbufsize 1500M  -thread_queue_size 512 -f gdigrab -video_size 1920x1080  -i desktop -f dshow -i audio="Microphone (Yeti Stereo Microphone)" -crf 0  -filter:a "volume=1.5" -vcodec libx264 %folder%\temp.mp4
run %folder%\ffmpeg %ff_params% ;run ffmpeg with command parameters

sleep, 150 ;Wait for Command window to appear
WinMinimize, ahk_class ConsoleWindowClass ;minimize the CMD window
return

;********************Control+Shift+S= Stop Recording***********************************
^+s::
ControlSend, , ^c, ahk_class ConsoleWindowClass  ; send ctrl-c to command window which stops the recording
sleep, 500
InputBox, New_File_Name,File name,What would you like to name your .mp4 file?,,300,130 ;Get a file name for your new video
if (New_File_Name = "") or (Error = 1) ;If you don't give it a name, it won't rename it and won't run it
	return 

Run, explore %folder% ;Open the working folder
FileMove, %folder%\temp.mp4, %folder%\%New_File_Name%.mp4  ; Rename the temp file to your new file.
sleep, 100
Run, %folder%\%New_File_Name%.mp4 ;Now play the new file name

;********************convert to gif  https://superuser.com/questions/556029/how-do-i-convert-a-video-to-gif-using-ffmpeg-with-reasonable-quality***********************************
msgbox,4,Animated Gif?,Do you want to convert the video to an animaged gif?
IfMsgBox,Yes
{
	gif_param1=-y -ss 0 -t 3 -i %folder%\%New_File_Name%.mp4 -vf fps=10,scale=320:-1:flags=lanczos,palettegen palette.png
	run %folder%\ffmpeg %gif_param1%
	gif_param2=-ss 0 -t 3 -i %folder%\%New_File_Name%.mp4 -i palette.png -filter_complex "fps=10,scale=1024:-1:flags=lanczos[x];[x][1:v]paletteuse" %folder%\%New_File_Name%.gif
	RunWait %folder%\ffmpeg %gif_param2%
	run %folder%\%New_File_Name%.gif
}
return

Sign-up for the 🅰️HK Newsletter

ImageImageImageImage:clap:
AHK Tutorials:Web Scraping | | Webservice APIs | AHK and Excel | Chrome | RegEx | Functions
Training: AHK Webinars Courses on AutoHotkey :ugeek:
YouTube

:thumbup: Quick Access Popup, the powerful Windows folders, apps and documents launcher!
User avatar
Delta Pythagorean
Posts: 627
Joined: 13 Feb 2017, 13:44
Location: Somewhere in the US
Contact:

Re: Recording desktop with ffmpeg & AutoHotkey

22 Sep 2018, 21:19

Great script, but I think I might have a pretty useful edit to the script.

Code: Select all

; Useful and important settings for just about any script.
#NoEnv
#SingleInstance, Force
#KeyHistory, 0
#MaxThreadsPerHotkey, 1
#Persistent
ListLines, Off
SendMode, Input
SetBatchLines, -1
SetWinDelay, -1
SetMouseDelay, -1
SetKeyDelay, -1, -1
SetTitleMatchMode, 3
DetectHiddenWindows, On
SetWorkingDir, % A_ScriptDir
Process, Priority,, High		; Use this setting with caution. It's been known to cause problems with lower end PC's

Menu, Tray, Icon, C:\Windows\System32\imageres.dll, 19
Menu, Tray, Tip, FFMPEG Screen Recorder
Menu, Tray, NoStandard
Menu, Tray, Add, Start Recording, Record
Menu, Tray, Add, Stop Recording, Stop
Menu, Tray, Add
Menu, Tray, Add, Open Settings, Settings
Menu, Tray, Add
Menu, Tray, Add, Exit The Program, Exit
CoordMode, ToolTip, Screen

If (!FileExist(A_ScriptDir "\settings.ini")) {
	FileAppend,
	(LTrim
		[Main]
		Record=^+r
		Stop=^+s

		[Settings]
		fps_cap=30
		type=mp4
		askforsave=1
	), % A_ScriptDir "\settings.ini"
}

IniRead, Hotkey_Record, % A_ScriptDir "\settings.ini", Main, Record, ^+r
IniRead, Hotkey_Stop, % A_ScriptDir "\settings.ini", Main, Stop, ^+s

IniRead, Settings_FPS, % A_ScriptDir "\settings.ini", Settings, fps_cap, 30
IniRead, Settings_Type, % A_ScriptDir "\settings.ini", Settings, type, mp4
IniRead, Settings_AskForSaveTo, % A_ScriptDir "\settings.ini", Settings, askforsave, 1

Hotkey, % Hotkey_Record, Record
Hotkey, % Hotkey_Stop, Stop
OnExit, Exit
Return

Record:
	FormatTime, Time,, dd-M-yyyy h_mm tt
	If (Settings_AskForSaveTo)
		FileSelectFile, FileName, S8, % A_Desktop "\Session [" Time "]." Settings_Type, Save your session..., Video Files (*.%Settings_Type%)
	Else
		FileName := A_Desktop "\Session [" Time "].mp4"

	; A little countdown.
	; You're welcome.
	; - Delta
	SplashTextOff
	Sec := 3
	Loop, 3
	{
		SplashTextOn, 300, 80, Start Recording,
		(Ltrim
		Recording will start in %Sec% seconds.
		Press %HotkeyStop% to stop recording.
		)
		Sec--
		Sleep, 1000
	}
	SplashTextOff


	; Hardware checks are pointless and take forever,
	; just be careful not to go overboard on the FPS and you'll be fine.
	; Also, I added in an auto check for you screen res. If you want to change it, just specify the size.
	; I'm pretty sure it uses the center of the screen like a normal AHK gui, so be aware.
	; - Delta
	ff_params := "-f gdigrab -video_size " A_ScreenWidth "x" A_ScreenHeight " -framerate " Settings_FPS " -i desktop  -vf format=yuv420p -f " Settings_Type " """ FileName """"

	; Run ffmpeg and start recording
	Run, ffmpeg %ff_params%,, Hide UseErrorLevel, ProcessID
	Process, Priority, % ProcessID, High
	; Now uses Process ID instead of a console window. This makes it a lot safer incase you're working with consoles already.
	; - Delta

	If (ErrorLevel = ERROR)
		MsgBox, 0x10, Software Failure,
		(LTrim
		Press OK to continue.

		Try this to solve:
		1. Download ffmpeg.exe and place it in the same directory to this script.
		2. Edit ff_params to meet your needs / hardware.
		)
	Return

Stop:
	ControlSend,, ^c, % "ahk_pid " ProcessID ; Send ctrl-c to command window which stops the recording.
	SplashTextOff
	SplashTextOn, 300, 80, Recording Stopped, Check the video file of where you saved it to and enjoy your recorded session.
	Sleep 3000
	SplashTextOff
	Return

Settings:
	Run, % A_ScriptDir "\settings.ini"
	Return

Exit:
	; Make sure to close ffmpeg as to not cause an overload on the CPU
	Process, Close, % ProcessID
	WinWaitClose, % "ahk_pid " ProcessID
	OnExit
	ExitApp
I added a few other features such as an FPS cap, a file select, and custom hotkeys.
There's no need to check for the screen size, it's done for you!

I hope someone finds this useful!
Remember: You must have FFMPEG installed on your computer, or the executable in the same directory as the script!!
If you want to record audio on your computer, use Audacity. It's free and quick to set up!

EDIT: Used bug spray. Should be gone now.
Last edited by Delta Pythagorean on 26 Sep 2018, 18:44, edited 1 time in total.

[AHK]......: v2.0.12 | 64-bit
[OS].......: Windows 11 | 23H2 (OS Build: 22621.3296)
[GITHUB]...: github.com/DelPyth
[PAYPAL]...: paypal.me/DelPyth
[DISCORD]..: tophatcat

User avatar
Thoughtfu1Tux
Posts: 125
Joined: 31 May 2018, 23:26

Re: Recording desktop with ffmpeg & AutoHotkey

25 Sep 2018, 23:39

Delta Pythagorean wrote:Great script, but I think I might have a pretty useful edit to the script.
Awesome Edits!! I added this to my main AHK tools folder that I use across all my devices. Thanks!! :thumbup:
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: Recording desktop with ffmpeg & AutoHotkey

26 Sep 2018, 19:49

@Joe Glines, @Delta Pythagorean, thanks to both of you for this. Works great.
As a heads-up for anyone else who may have trouble with ffmpeg (I just grabbed one of the four or five .exes that various programs have installed in the past, epic fail), try the advice at this link.
I followed those directions and added ffmpeg/bin to my path using Rapid Environment Editor which is sure easier than editing the path by hand. I then used RefreshEnv.cmd from the chocolatey github repo to refresh the path variables with little effort.
Regards, and thanks again,
burque505
User avatar
Joe Glines
Posts: 770
Joined: 30 Sep 2013, 20:49
Location: Dallas
Contact:

Re: Recording desktop with ffmpeg & AutoHotkey

27 Sep 2018, 05:09

@burgue505- I don't think you would have had a problem as long as you had the AutoHotkey script in the same folder as where the ffmpeg.exe file was located. I don't have ffmpeg.exe as part of my path (nor do I want it there) and it all works fine.
Sign-up for the 🅰️HK Newsletter

ImageImageImageImage:clap:
AHK Tutorials:Web Scraping | | Webservice APIs | AHK and Excel | Chrome | RegEx | Functions
Training: AHK Webinars Courses on AutoHotkey :ugeek:
YouTube

:thumbup: Quick Access Popup, the powerful Windows folders, apps and documents launcher!
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: Recording desktop with ffmpeg & AutoHotkey

27 Sep 2018, 18:37

@Joe Glines, actually I did have a problem with ffmpeg.exe and the script in the same folder, which is exactly what I tried at first. I can understand why you wouldn't want ffmpeg in the path, though. I'm pretty sure the problem was not where it was, but how old it was and its bit-ness.

I have tried it with the new ffmpeg.exe and it works fine, both in the script directory and as part of the path. So you're absolutely right about that part.

The result with the faulty (old? 32-bit?) ffmpeg.exe was that an MP4 kept growing - and growing - and growing - until I finally had to kill the process manually. And it never did create a viewable MP4.
Regards, and thanks again for the script,
burque505
CyL0N
Posts: 211
Joined: 27 Sep 2018, 09:58

Re: Recording desktop with ffmpeg & AutoHotkey

28 Sep 2018, 13:32

Here's my ffmpeg wrapper for any one interested, it acts on all selected files in explorer, it does enough that i no longer have a video conversion utility installed,i use avidemux for all other editing needs...

NOTE: you must configure the name of your own corresponding devices to use the extended recording menu entries beyond basic screen recording(i.e microphone,steromix,webcam...)(See: ffmpeg devices doc) in the INI file created after first run


Hotkey is Ctrl+Shift+Alt+C which spawns a menu that will act on all files selected inside explorer,any converted or output files such as a gif output will be to the same folder as selected files...

Edit:One more thing,recordings are saved to active/lastSavedTo explorer path...

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

#SingleInstance, force
DetectHiddenWindows, on

SetBatchLines, -1

GroupAdd, Explore, ahk_class CabinetWClass			; Add a class to the group

GroupAdd, Explore, ahk_class ExploreWClass			; Add a other class to the group

#ifWinActive,ahk_group Explore  				; Set hotkeys to work in explorer only

Menu, Tray, Icon, C:\Windows\System32\shell32.dll, 85
Menu, Tray, Tip,  %A_ScriptName%`n`nCtrl+Shift+Alt+C : ContextMenu `nCtrl+Shift+Alt+Esc : Interrupt Active Conversion.
TrayTip, [CyLoN] %A_ScriptName%, Ctrl+Shift+Alt+C	:	ContextMenu`n Ctrl+Shift+F11 	:	StopAnyActiveRecording`n Ctrl+Shift+F12	:	Start/Stop Lossless Recording`n `n Ctrl+F9/Ctrl+Shift+F9	--->Start/Stop Recording Tones for OBS.
;OBS Hotkey ToneGenerator thread
SetTimer, obsRecNotifier, 2500

;replace tray menu with created menu
; OnMessage(0x404, "AHK_NOTIFYICON")		;allowing normal tray menu as replacing it makes process termination a tad difficult.

IfNotExist, %A_ScriptName%.README.txt
	FileAppend, Press Ctrl+Shift+Alt+C to trigger menu and select conversion/processing task from the menu.`n For Any command on the menu to work ffmpeg.exe must be placed in the windows directory. `n Ctrl+Shift+Alt+Esc can be used to interrupt any active conversion. Incomplete file needs to be manually deleted though! `n`n Ctrl+Shift+Alt+P toggles progress bar. `n`nUpon Interruption Incomplete File Will Be deleted. `n Ctrl+Shift+F12 to record losless video to last folder that was recorded to `n`t Ctrl+Shift+F11 to stop any active recording`, Sound Tones will signify both actions.	, %A_ScriptName%.README.txt

progressBarActive := True

; Create the popup menu by adding some items to it.
Menu, MyMenu, Add, Convert to Mp3 256k, MenuHandler
Menu, MyMenu, Add  ; Add a separator line.
Menu, MyMenu, Add, Convert to Mp3 48k, MenuHandler
Menu, MyMenu, Add  ; Add a separator line.
Menu, MyMenu, Add, Extract mp3 from Selected (no-conversion), MenuHandler
Menu, MyMenu, Add  ; Add a separator line.
Menu, MyMenu, Add, Extract mp3 from Selected (no-conversion) + VideoThumbnail@30secMark, MenuHandler
Menu, MyMenu, Add  ; Add a separator line.
Menu, MyMenu, Add, Trim Silence from Mp3, MenuHandler
Menu, MyMenu, Add  ; Add a separator line.
Menu, MyMenu, Add, Resync Audio [+/-] prefixed seconds, MenuHandler
Menu, MyMenu, Add  ; Add a separator line below the submenu.
Menu, MyMenu, Add  ; Add a separator line below the submenu.
Menu, MyMenu, Add  ; Add a separator line below the submenu.

; Create another menu destined to become a submenu of the above menu.
Menu, Submenu1, Add, MP4 SourceQuality, MenuHandler
Menu, Submenu1, Add  ; Add a separator line.
Menu, Submenu1, Add, MP4 720p, MenuHandler
Menu, Submenu1, Add  ; Add a separator line.
Menu, Submenu1, Add, MP4 480p, MenuHandler
Menu, Submenu1, Add  ; Add a separator line.
Menu, Submenu1, Add, MP4 360p, MenuHandler
Menu, Submenu1, Add  ; Add a separator line.
Menu, Submenu1, Add, MKV To MP4 SourceQuality, MenuHandler
Menu, Submenu1, Add  ; Add a separator line.
Menu, Submenu1, Add, FLV To MP4 SourceQuality, MenuHandler
Menu, Submenu1, Add  ; Add a separator line.
Menu, Submenu1, Add, TS To MP4 SourceQuality, MenuHandler
Menu, Submenu1, Add  ; Add a separator line.
Menu, Submenu1, Add, DAT To MP4 SourceQuality, MenuHandler
Menu, Submenu1, Add  ; Add a separator line.
Menu, Submenu1, Add, Change Video Container to MP4(Fastest)(Identical Video/Audio to Source) - Limited MediaPlayer Support Based On Source Format, MenuHandler
Menu, Submenu1, Add  ; Add a separator line.
Menu, Submenu1, Add, MP4 Lossless Conversion(Source or Superior Quality and Greatest Size), MenuHandler

Menu, Submenu2, Add, ffmpeg_RECORD_display, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_RECORD_display_activeWindow, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_RECORD_display_mic, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_RECORD_display_stereoMix, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_RECORD_mic, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_RECORD_webcam_mic, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_RECORD_webcam_stereoMix, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_LIST_DEVICES_DEBUG, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_GamePlayRecordingOptimised_30fpsLOCKED_AudioResync@450ms+AllInputs+Win7Inputs, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_GamePlayRecordingOptimised_30fpsLOCKED_AudioResync@450ms, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_LOSLESS_display_GreatestSize_stereoMix_AudioResync@450ms, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_GamePlayRecordingOptimised_30fpsLOCKED, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_LOSLESS_display_GreatestSize_stereoMix, MenuHandler

; Create a submenu in the first menu (a right-arrow indicator). When the user selects it, the second menu is displayed.
Menu, MyMenu, Add, Convert to Mp4, :Submenu1
Try
	Menu, MyMenu, Icon, Convert to Mp4, Shell32.dll, 116, 40
Menu, MyMenu, Add, RECORD, :Submenu2
Try
	Menu, MyMenu, Icon, RECORD, Shell32.dll, 204, 40

Menu, MyMenu, Add  ; Add a separator line below the submenu.
Menu, MyMenu, Add  ; Add a separator line below the submenu.
Menu, MyMenu, Add  ; Add a separator line below the submenu.
Menu, MyMenu, Add, Extract Animated Gif from Video, MenuHandler  ; Add another menu item beneath the submenu.
Menu, MyMenu, Add  ; Add a separator line below the submenu.
Menu, MyMenu, Add, Extract VideoThumbnail from Video@30secMark at Video Resolution, MenuHandler  ; Add another menu item beneath the submenu.
Menu, MyMenu, Add  ; Add a separator line below the submenu.
Menu, MyMenu, Add, Extract clip from video at SourceQuality, MenuHandler  ; Add another menu item beneath the submenu.
Menu, MyMenu, Add  ; Add a separator line below the submenu.
Menu, MyMenu, Add, Delete other file format with Mp3 counterpart i.e(x.avi and x.mp3), MenuHandler  ; Add another menu item beneath the submenu.
Menu, MyMenu, Add  ; Add a separator line below the submenu.
Menu, MyMenu, Add, Delete other file format with Mp4 counterpart i.e(x.avi and x.mp4), MenuHandler  ; Add another menu item beneath the submenu.

;Menu, MyMenu, Show

return  ; End of script's auto-execute section.


+!^c::
Menu, MyMenu, Show
Return



#IfWinActive,ahk_group Explore  				; Set hotkeys to work in explorer only
MButton::
Menu, MyMenu, Show
Return
#IfWinActive

+!^p::
If progressBarActive{
	Progress, off
	progressBarActive := False
}Else{
	progressBarActive := True
	Progress, a t b x0 y0 w%A_ScreenWidth%, [%i%/%listToConvNum%] %OutFileName%, PROCESSING, Conversion Progress	;'b' always ontop off & 't' to give progress bar own button on taskbar
	Progress, % i*100/listToConvNum ; Set the position of the bar to 0-100
}
Return

+!^Esc::
term := True	;send termination signal to current processing loop
Process, Close, ffmpeg.exe
RunWait, %comspec% /c Taskkill /f /t /im ffmpeg.exe, , Hide
MsgBox, 0x40010, %A_ScriptName%, INTERRUPTED!`n`nLastProcessedFile[Incomplete Files Will Be Deleted]: `n%OutFileName%
FileDelete, %OutDir%\%convertTo%
Return


MenuHandler:
;MsgBox You selected %A_ThisMenuItem% from the menu %A_ThisMenu%.
Sleep, 250
sel := Explorer_GetSelected()
path := Explorer_GetPath()

Loop, Parse, sel, `n
{
	SplitPath, A_LoopField, OutFileName, OutDir, OutExtension, OutNameNoExt, OutDrive
	IfEqual, OutExtension, lnk
	{
		FileGetShortcut, %A_LoopField%, OutTarget, OutDir, OutArgs, OutDescription, OutIcon, OutIconNum, OutRunState
		SplitPath, A_LoopField, OutFileName, OutDir, OutExtension, OutNameNoExt, OutDrive
	}
	
	listToConv .= OutExtension != "lnk" ? A_LoopField "`n" : OutTarget "`n"
}

IfEqual, A_ThisMenu, Submenu2
	Goto, recHandler	;jump


MsgBox, 0x40031, %A_ScriptName%, %A_ThisMenuItem%`? `n`n***Invalid files will be ignored`,so they can be included in selection.*** `n`n %listToConv%
IfMsgBox, Cancel
	Return

listToConvNum := ListCount(listToConv)
listToConv := ""


FileAppend, [%TimeString%]	COMMAND	--->	%A_ThisMenuItem% `n, %A_Desktop%\%A_ScriptName%.LOG.log
Loop, Parse, sel, `n
{
	SplitPath, A_LoopField, OutFileName, OutDir, OutExtension, OutNameNoExt, OutDrive
	IfEqual, OutExtension, lnk
	{
		FileGetShortcut, %A_LoopField%, OutTarget, OutDir, OutArgs, OutDescription, OutIcon, OutIconNum, OutRunState
		SplitPath, OutTarget, OutFileName, OutDir, OutExtension, OutNameNoExt, OutDrive
	}
	FormatTime, TimeString, T8 T2 T4 R
	FileAppend, [%TimeString%]	processing --->	%A_LoopField% `n, %A_Desktop%\%A_ScriptName%.LOG.log
	
	i++
	If progressBarActive
	{
		; WinGetActiveTitle, activeTitle
		; Progress, b x0 y0 w%A_ScreenWidth%, %OutFileName%, CONVERTING, This Progress Bar
		Progress, a t b x0 y0 w%A_ScreenWidth%, [%i%/%listToConvNum%] %OutFileName%, PROCESSING, Conversion Progress	;'b' always ontop off & 't' to give progress bar own button on taskbar
		Progress, % i*100/listToConvNum ; Set the position of the bar to 0-100
		; Sleep, 25
		; WinActivate, %activeTitle%	;to prevent progress bar stealing focus while processing files.
	}
	
	
	;mp3 conversions/extractions
	If ( A_ThisMenuItem = "Convert to Mp3 256k" AND A_ThisMenu = "MyMenu" ){
		convertTo = %OutNameNoExt%.mp3
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -acodec libmp3lame -ab 256 "%OutDir%\%OutNameNoExt%.mp3", , Hide
	}Else If ( A_ThisMenuItem = "Convert to Mp3 48k" AND A_ThisMenu = "MyMenu" ){
		convertTo = %OutNameNoExt%.mp3
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -acodec libmp3lame -ab 48k "%OutDir%\%OutNameNoExt%.mp3", , Hide
	}Else If ( A_ThisMenuItem = "Extract mp3 from Selected (no-conversion)" AND A_ThisMenu = "MyMenu" ){
		convertTo = %OutNameNoExt%.mp3
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -vn "%OutDir%\%OutNameNoExt%.mp3", , Hide
	}Else If ( A_ThisMenuItem = "Extract mp3 from Selected (no-conversion) + VideoThumbnail@30secMark" AND A_ThisMenu = "MyMenu" ){
		convertTo = %OutNameNoExt%.mp3
		RunWait, %comspec% /c echo n|ffmpeg -ss 00:00:30 -i "%OutDir%\%OutFileName%" -vframes 1 -q:v 2 "%OutDir%\%OutNameNoExt%.jpg", , Hide
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -vn "%OutDir%\%OutNameNoExt%.mp3", , Hide
	}Else If ( A_ThisMenuItem = "Trim Silence from Mp3" AND A_ThisMenu = "MyMenu" ){
		convertTo = %OutNameNoExt%[noSilence].mp3
		InputBox, threshHold, Input Silence Threshold in dB, Lower is More sensitive & will trim more sound`,i.e -25 will more trimming than -40(which is the default)!, , 636, 136, 538, 416, , , -40
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -af silenceremove=0:0:0:-1:1:%threshHold%dB -y "%OutDir%\%OutNameNoExt%[noSilence].mp3", , Hide
	}Else If ( A_ThisMenuItem = "Resync Audio [+/-] prefixed seconds" AND A_ThisMenu = "MyMenu" ){
		convertTo = %OutNameNoExt%[Resync].mp4
		InputBox, resyncSeconds, Resync Audio, Input Seconds To Pull-Back/Push-Fwd audio with respect to video!`n-->	output video will have [Resync] suffix., , 428, 144, 564, 212, , , -0.45
		If ErrorLevel
			Return
		RunWait, %comspec% /c ffmpeg -i "%OutDir%\%OutFileName%" -itsoffset %resyncSeconds% -i "%OutDir%\%OutFileName%" -map 0:0 -map 1:1  -acodec copy -vcodec copy -y "%OutDir%\%OutNameNoExt%[Resync].mp4", , Hide
	}
	
	
	;Convert to Mp4
	If ( A_ThisMenuItem = "MP4 SourceQuality" AND A_ThisMenu = "Submenu1" ){
		convertTo = %OutNameNoExt%.mp4
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" "%OutDir%\%OutNameNoExt%.mp4", , Hide
	}Else If ( A_ThisMenuItem = "MP4 720p" AND A_ThisMenu = "Submenu1" ){
		convertTo = %OutNameNoExt%[720p].mp4
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -s hd720 "%OutDir%\%OutNameNoExt%[720p].mp4", , Hide
	}Else If ( A_ThisMenuItem = "MP4 480p" AND A_ThisMenu = "Submenu1" ){
		convertTo = %OutNameNoExt%[480p].mp4
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -s hd480 "%OutDir%\%OutNameNoExt%[480p].mp4", , Hide
	}Else If ( A_ThisMenuItem = "MP4 360p" AND A_ThisMenu = "Submenu1" ){
		convertTo = %OutNameNoExt%[360p].mp4
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -s ega "%OutDir%\%OutNameNoExt%[360p].mp4", , Hide
	}Else If ( A_ThisMenuItem = "MKV To MP4 SourceQuality" AND A_ThisMenu = "Submenu1" AND OutExtension = "mkv"){
		convertTo = %OutNameNoExt%.mp4
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" "%OutDir%\%OutNameNoExt%.mp4", , Hide
	}Else If ( A_ThisMenuItem = "FLV To MP4 SourceQuality" AND A_ThisMenu = "Submenu1" AND OutExtension = "flv"){
		convertTo = %OutNameNoExt%.mp4
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -c copy -copyts "%OutDir%\%OutNameNoExt%.mp4", , Hide
	}Else If ( A_ThisMenuItem = "TS To MP4 SourceQuality" AND A_ThisMenu = "Submenu1" AND OutExtension = "ts"){
		convertTo = %OutNameNoExt%.mp4
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -c copy -copyts "%OutDir%\%OutNameNoExt%.mp4", , Hide
	}Else If ( A_ThisMenuItem = "DAT To MP4 SourceQuality" AND A_ThisMenu = "Submenu1" AND OutExtension = "dat" OR  A_ThisMenuItem = "DAT To MP4 SourceQuality" AND A_ThisMenu = "Submenu1" AND OutExtension = "mpg"){
		convertTo = %OutNameNoExt%.mp4
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -c:v libx264 -preset slow -crf 15 -c:a aac -strict experimental -b:a 128k "%OutDir%\%OutNameNoExt%.mp4", , Hide
	}Else If ( A_ThisMenuItem = "Change Video Container to MP4(Fastest)(Identical Video/Audio to Source) - Limited MediaPlayer Support Based On Source Format" AND A_ThisMenu = "Submenu1"){
		convertTo = %OutNameNoExt%.mp4
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -c copy -copyts -scodec mov_text "%OutDir%\%OutNameNoExt%.mp4", , Hide
	}Else If ( A_ThisMenuItem = "MP4 Lossless Conversion(Source or Superior Quality and Greatest Size)" AND A_ThisMenu = "Submenu1"){
		convertTo = %OutNameNoExt%.mp4
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -c:v libx264 -crf 0 -c:a copy -copyts "%OutDir%\%OutNameNoExt%.mp4", , Hide
	}
	
	;Video to Gif
	If ( A_ThisMenuItem = "Extract Animated Gif from Video" AND A_ThisMenu = "MyMenu" ){
		If !timeRangeDefined{
			InputBox, startTime, video2gif, StartTime(time in video where gif will start off)`,`nomitting starttime by clearing the input field will `nconvert full video into gif!`n`nNOTE:gif files are upto 20x the size of a video equivalent..., , , , , , , , 00:01:00
			InputBox, endTime, video2gif, gifLength(how many seconds to encode to gif since start time)`,`n`n10`, means 10 seconds starting from previously input start time will be`nsaved to gif`,so based on previous default value`, gif will be 10seconds`nlong and will start at minute 1 of the video..., , 446, 212, , , , , 10
			timeRangeDefined := True
		}
		If startTime
			RunWait, %comspec% /c echo n| ffmpeg -i "%OutDir%\%OutFileName%" -ss %startTime% -t %endTime% "%OutDir%\%OutNameNoExt%.gif", , Hide
		Else If endTime
			RunWait, %comspec% /c echo n| ffmpeg -i "%OutDir%\%OutFileName%" "%OutDir%\%OutNameNoExt%.gif", , Hide
		Else If (!startTime AND !endTime){
			MsgBox, 0x40010, %A_ScriptName%, Range NOT DEFINED OR INCORRECTLY DEFINED`, TryAGAIN!
		}
	}
	
	;video snapshot
	If ( A_ThisMenuItem = "Extract VideoThumbnail from Video@30secMark at Video Resolution" AND A_ThisMenu = "MyMenu" ){
		RunWait, %comspec% /c echo n|ffmpeg -ss 00:00:30 -i "%OutDir%\%OutFileName%" -vframes 1 -q:v 2 "%OutDir%\%OutNameNoExt%.jpg", , Hide
	}
	
	;extract clip from video
	If ( A_ThisMenuItem = "Extract clip from video at SourceQuality" AND A_ThisMenu = "MyMenu" ){
		If !timeRangeDefined{
			InputBox, startTime, clipExtract, StartTime(time in video where clip will start off)`,`nomitting starttime by clearing the input field will `nextract clip from video begining + n Seconds , , , , , , , , 00:01:00
			InputBox, endTime, clipExtract, clipLength(how many seconds to encode to clip since start time)`,`n`n10`, means 10 seconds starting from previously input start time will be`nsaved to clip`,so based on previous default value`, clip will be 10seconds`nlong and will start at minute 1 of the video..., , 446, 212, , , , , 10
			timeRangeDefined := True
		}
		If startTime
			RunWait, %comspec% /c echo n| ffmpeg -i "%OutDir%\%OutFileName%" -ss %startTime% -t %endTime% "%OutDir%\%OutNameNoExt%.CLIP%A_NOW%.mp4", , Hide
		Else If endTime
			RunWait, %comspec% /c echo n| ffmpeg -i "%OutDir%\%OutFileName%" -ss 00:00:00 -t %endTime% "%OutDir%\%OutNameNoExt%.CLIP%A_NOW%.mp4", , Hide
		Else If (!startTime AND !endTime){
			MsgBox, 0x40010, %A_ScriptName%, Range NOT DEFINED OR INCORRECTLY DEFINED`, TryAGAIN!
		}
	}
	
	;Delete Files with MP4 Counter part
	If ( A_ThisMenuItem = "Delete other file format with Mp4 counterpart i.e(x.avi and x.mp4)" AND A_ThisMenu = "MyMenu" AND OutExtension != "Mp4"){
		FileGetSize, thisFileSize, %OutDir%\%OutNameNoExt%.mp4
		IfExist, %OutDir%\%OutNameNoExt%.mp4		;if the file has an MP4 counterpart delete original,i.e current file.
			If (thisFileSize AND thisFileSize != 0)
				{
					FileDelete, %OutDir%\%OutFileName%
					FormatTime, TimeString, T8 T2 T4 R
					FileAppend, [%TimeString%]	DELETING --->	%A_LoopField% `n, %A_Desktop%\%A_ScriptName%.LOG.log
				}
	}Else If ( A_ThisMenuItem = "Delete other file format with Mp3 counterpart i.e(x.avi and x.mp3)" AND A_ThisMenu = "MyMenu" AND OutExtension != "mp3" AND OutExtension != "jpg" AND OutExtension != "description"){
		FileGetSize, thisFileSize, %OutDir%\%OutNameNoExt%.mp3
		IfExist, %OutDir%\%OutNameNoExt%.mp3		;if the file has an MP4 counterpart delete original,i.e current file.
			If (thisFileSize AND thisFileSize != 0)
				{
					FileDelete, %OutDir%\%OutFileName%
					FormatTime, TimeString, T8 T2 T4 R
					FileAppend, [%TimeString%]	DELETING --->	%A_LoopField% `n, %A_Desktop%\%A_ScriptName%.LOG.log
				}
	}
	
	
	;Zero File Remnant Safeguard
	FileGetSize, convertToSize, %OutDir%\%convertTo%
	If (convertToSize = 0){
		MsgBox, 0x40010, %A_ScriptName%, Conversion To %convertTo% Failed!`n`nPress Ok to delete zerobyte file and proceed with conversion.
		FileDelete, %OutDir%\%convertTo%
	}

	
	
	
	
	If term
	{
		Progress, Off
		stats := ""
		term := ""
		convertTo := ""
		i := ""
		Return
	}
	If !stats
		stats .=  "`n" A_ThisMenuItem  "`n[Only Valid Selected Files below are acted UpOn...Rest are Ignored.]" "`n`n"
	stats .= A_LoopField "`n"
}
Progress, 100 ; Set the position of the bar to 0-100

timeRangeDefined := False	;reset

MsgBox, 0x40040, %A_ScriptName%, CONVERSION COMPLETE! %stats%

Progress, Off

stats := ""
term := ""
convertTo := ""
i := ""
return



/*
	Library for getting info from a specific explorer window (if window handle not specified, the currently active
	window will be used).  Requires AHK_L or similar.  Works with the desktop.  Does not currently work with save
	dialogs and such.
	
	
	Explorer_GetSelected(hwnd="")   - paths of target window's selected items
	Explorer_GetAll(hwnd="")        - paths of all items in the target window's folder
	Explorer_GetPath(hwnd="")       - path of target window's folder
	
	example:
	F1::
	path := Explorer_GetPath()
	all := Explorer_GetAll()
	sel := Explorer_GetSelected()
	MsgBox % path
	MsgBox % all
	MsgBox % sel
	return
	
	Joshua A. Kinnison
	2011-04-27, 16:12
*/

Explorer_GetPath(hwnd="")
{
	if !(window := Explorer_GetWindow(hwnd))
		return ErrorLevel := "ERROR"
	if (window="desktop")
		return A_Desktop
	path := window.LocationURL
	path := RegExReplace(path, "ftp://.*@","ftp://")
	StringReplace, path, path, file:///
	StringReplace, path, path, /, \, All
	
	; thanks to polyethene
	Loop
		If RegExMatch(path, "i)(?<=%)[\da-f]{1,2}", hex)
			StringReplace, path, path, `%%hex%, % Chr("0x" . hex), All
	Else Break
		return path
}
Explorer_GetAll(hwnd="")
{
	return Explorer_Get(hwnd)
}
Explorer_GetSelected(hwnd="")
{
	return Explorer_Get(hwnd,true)
}

Explorer_GetWindow(hwnd="")
{
	; thanks to jethrow for some pointers here
	WinGet, process, processName, % "ahk_id" hwnd := hwnd? hwnd:WinExist("A")
	WinGetClass class, ahk_id %hwnd%
	
	if (process!="explorer.exe")
		return
	if (class ~= "(Cabinet|Explore)WClass")
	{
		for window in ComObjCreate("Shell.Application").Windows
			if (window.hwnd==hwnd)
				return window
	}
	else if (class ~= "Progman|WorkerW")
		return "desktop" ; desktop found
}
Explorer_Get(hwnd="",selection=false)
{
	if !(window := Explorer_GetWindow(hwnd))
		return ErrorLevel := "ERROR"
	if (window="desktop")
	{
		ControlGet, hwWindow, HWND,, SysListView321, ahk_class Progman
		if !hwWindow ; #D mode
			ControlGet, hwWindow, HWND,, SysListView321, A
		ControlGet, files, List, % ( selection ? "Selected":"") "Col1",,ahk_id %hwWindow%
		base := SubStr(A_Desktop,0,1)=="\" ? SubStr(A_Desktop,1,-1) : A_Desktop
		Loop, Parse, files, `n, `r
		{
			path := base "\" A_LoopField
			IfExist %path% ; ignore special icons like Computer (at least for now)
				ret .= path "`n"
		}
	}
	else
	{
		if selection
			collection := window.document.SelectedItems
		else
			collection := window.document.Folder.Items
		for item in collection
			ret .= item.path "`n"
	}
	return Trim(ret,"`n")
}





ListCount(ByRef list){
	StringReplace, list, list, `n, `n, UseErrorLevel
	Return ErrorLevel + 1
}


INI(rw, ini_section, ini_key, key_value:="", key_default_value:="", ini_file:="######.ini"){	;r/w - 'r' to read & 'w' to write to ini
	If (rw = "r"){	;read from ini
		IniRead, thisKey, %ini_file%, %ini_section%, %ini_key%, %key_default_value%
		Return ( thisKey != "ERROR" ? thisKey : "")
	}Else{	;write to ini
		IniWrite, %key_value%, %ini_file%, %ini_section%, %ini_key%
	}
}

;==========================================================
GuiStart:
Gui , font, s8 bold, Verdana
Gui , Add , button , w150 h75 vButton1 gGuiClose, RECORDING...`n`nClick to Terminate Recording!
Gui , -caption
Gui , Show ,AutoSize Center xCenter y0 NA, ffmpeg.RECORDER
Return

GuiClose:
Critical
GuiControl,, Button1, Stopping...
While ( WinExist("ahk_pid " . PID) OR WinExist("ahk_pid " . pid1) OR WinExist("ahk_pid " . pid2) OR WinExist("ahk_pid " . pid3) ){
	WinClose, ahk_pid %PID%
	WinClose, ahk_pid %PID1%
	WinClose, ahk_pid %PID2%
	WinClose, ahk_pid %PID3%
	If (A_Index=10){
		Process, Close, %pid2%	;pid 2 is reserved for audio recording instances that tend to get stuck!!!
		WinActivate, ahk_pid %pid3%
		PostMessage, 0x112, 0xF060,,, ahk_pid %pid3%  ; 0x112 = WM_SYSCOMMAND, 0xF060 = SC_CLOSE
	}
	Sleep, 50
}
Gui, Destroy
Critical, off
MsgBox, 0x40040, %A_ScriptName%, Recording Saved to %SaveDir%\%fileName%
Return

;========================================================

;record menu handlers
recHandler:
msgout:=""

( INI("r", "DEVICES", "PrimaryMicrophone",,, "ffmpeg.rec.ini") ? "" : INI("w", "DEVICES", "PrimaryMicrophone", "Microphone (Realtek High Defini",, "ffmpeg.rec.ini") )
( INI("r", "DEVICES", "SpeakerOutputStereoMix",,, "ffmpeg.rec.ini") ? "" : INI("w", "DEVICES", "SpeakerOutputStereoMix", "Stereo Mix (Realtek High Defini",, "ffmpeg.rec.ini") )
( INI("r", "DEVICES", "USBCamera",,, "ffmpeg.rec.ini") ? "" : INI("w", "DEVICES", "USBCamera", "USB 2.0 Camera",, "ffmpeg.rec.ini") )
( INI("r", "RecordingFPS", "RecordingFPS",,, "ffmpeg.rec.ini") ? "" : INI("w", "RecordingFPS", "RecordingFPS", "30",, "ffmpeg.rec.ini") )
( INI("r", "BufferSize", "BufferSize",,, "ffmpeg.rec.ini") ? "" : INI("w", "BufferSize", "BufferSize", "200M",, "ffmpeg.rec.ini") )
( INI("r", "BufferSize", "RealTimeBufferSize",,, "ffmpeg.rec.ini") ? "" : INI("w", "BufferSize", "RealTimeBufferSize", "1024M",, "ffmpeg.rec.ini") )


path := Explorer_GetPath()
lastSaveDir := INI("r", "LastSaveDir", "LastSaveDir",,, "ffmpeg.rec.ini")
SaveDir := ( InStr(path, ":\") ? path : (lastSaveDir ? lastSaveDir : A_Desktop) )
INI("w", "LastSaveDir", "LastSaveDir", SaveDir,, "ffmpeg.rec.ini")

devMicrophonePrimary := INI("r", "DEVICES", "PrimaryMicrophone",,, "ffmpeg.rec.ini")
devStereoMix := INI("r", "DEVICES", "SpeakerOutputStereoMix",,, "ffmpeg.rec.ini")
devUsbCamera := INI("r", "DEVICES", "USBCamera",,, "ffmpeg.rec.ini")
recFPS := INI("r", "RecordingFPS", "RecordingFPS",,, "ffmpeg.rec.ini")
bufferSize := INI("r", "BufferSize", "BufferSize",,, "ffmpeg.rec.ini")	;-bufsize
rtBufferSize := INI("r", "BufferSize", "RealTimeBufferSize",,, "ffmpeg.rec.ini")	;-rtbufsize
; MsgBox % devMicrophonePrimary "`n" devStereoMix "`n" devUsbCamera "`n" recFPS "`n" bufferSize

If (A_ThisMenu = "Submenu2" AND A_ThisMenuItem != "ffmpeg_LIST_DEVICES_DEBUG"){
	WinGet, activeProcess, ProcessName, A
	InputBox, fileName, SaveAs  (mp4 for HD`,any other for LowRes), Input file name to save to desktop(including extension):, , 350, 136, , , , , %activeProcess%[%A_Now%].mp4
	If ErrorLevel
		Return
}Else If ( fileName="" || !InStr(fileName, ".") ){	;if cancel or no extension defined
	If (A_ThisMenuItem != "ffmpeg_LIST_DEVICES_DEBUG"){
		MsgBox, 0x40010, %A_ScriptName%, Invalid FileName or No File Extension Given`, Aborting!
		Return
	}
}
If ( A_ThisMenuItem = "ffmpeg_RECORD_display" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg -f gdigrab -framerate %recFPS% -i desktop "%SaveDir%\%fileName%" -y, , Hide, PID
}Else If ( A_ThisMenuItem = "ffmpeg_RECORD_display_activeWindow" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	Sleep, 2500
	WinGetActiveTitle, _activeWindow
	RunWait, %comspec% /c ffmpeg -f gdigrab -framerate %recFPS% -i title="%_activeWindow%" "%SaveDir%\%fileName%" -y, , Hide, PID
}Else If ( A_ThisMenuItem = "ffmpeg_RECORD_display_mic" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg -f dshow -i audio="%devMicrophonePrimary%" -itsoffset 0.45 -f gdigrab -framerate %recFPS% -i desktop -y "%SaveDir%\%fileName%", , Hide, pid
}Else If ( A_ThisMenuItem = "ffmpeg_RECORD_display_stereoMix" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg -f dshow -i audio="%devStereoMix%" -itsoffset 0.45 -f gdigrab -framerate %recFPS% -i desktop -y "%SaveDir%\%fileName%", , Hide, pid
}Else If ( A_ThisMenuItem = "ffmpeg_RECORD_mic" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg -f dshow -i audio="%devMicrophonePrimary%" -y "%SaveDir%\%fileName%.mp3", , Hide, PID2
}Else If ( A_ThisMenuItem = "ffmpeg_RECORD_webcam_mic" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg -f dshow -i video="%devUsbCamera%"`:audio="%devMicrophonePrimary%" -framerate %recFPS% -y "%SaveDir%\%fileName%", , Hide, PID3
}Else If ( A_ThisMenuItem = "ffmpeg_RECORD_webcam_stereoMix" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg -f dshow -i video="%devUsbCamera%"`:audio="%devStereoMix%" -framerate %recFPS% -y "%SaveDir%\%fileName%", , Hide, PID3
	; Gosub, GuiClose
}Else If (A_ThisMenuItem = "ffmpeg_LIST_DEVICES_DEBUG" AND A_ThisMenu = "Submenu2" ){
	Run, %comspec% /k ffmpeg -list_devices true -f dshow -i dummy
}Else If (A_ThisMenuItem = "ffmpeg_GamePlayRecordingOptimised_30fpsLOCKED_AudioResync@450ms+AllInputs+Win7Inputs" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg  -rtbufsize %rtBufferSize% -loglevel info   -f dshow  -video_device_number 0 -i video="screen-capture-recorder"  -f dshow -audio_device_number 0 -i audio="virtual-audio-capturer"  -f dshow -audio_device_number 0 -i audio="%devMicrophonePrimary%"  -filter_complex amix=inputs=2  -vcodec libx264  -pix_fmt yuv420p  -preset ultrafast -vsync vfr -acodec libmp3lame -f mp4 -y "%SaveDir%\%fileName%", , Hide, PID
}Else If (A_ThisMenuItem = "ffmpeg_GamePlayRecordingOptimised_30fpsLOCKED_AudioResync@450ms" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg -f dshow -i audio="%devStereoMix%" -itsoffset 0.45 -f gdigrab -framerate 30 -i desktop -c:v libx264 -preset ultrafast -crf 1 -maxrate 20M -bufsize %bufferSize% -vsync vfr -acodec libmp3lame -f mp4 -y "%SaveDir%\%fileName%", , Hide, PID
}Else If (A_ThisMenuItem = "ffmpeg_LOSLESS_display_GreatestSize_stereoMix_AudioResync@450ms" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg -f dshow -i audio="%devStereoMix%" -itsoffset 0.45 -f gdigrab -framerate %recFPS% -draw_mouse 1 -i desktop -c:v libx264 -qp 0 -pix_fmt yuv444p -preset ultrafast -y "%SaveDir%\%fileName%", , Hide, PID
}Else If (A_ThisMenuItem = "ffmpeg_GamePlayRecordingOptimised_30fpsLOCKED" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg -f dshow -i audio="%devStereoMix%" -f gdigrab -framerate 30 -i desktop -c:v libx264 -preset ultrafast -crf 1 -maxrate 20M -bufsize  %bufferSize% -y "%SaveDir%\%fileName%", , Hide, PID
}Else If (A_ThisMenuItem = "ffmpeg_LOSLESS_display_GreatestSize_stereoMix" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg -f dshow -i audio="%devStereoMix%" -f gdigrab -framerate %recFPS% -draw_mouse 1 -i desktop -c:v libx264 -qp 0 -pix_fmt yuv444p -preset ultrafast -y "%SaveDir%\%fileName%", , Hide, PID
}
Return
; -itsoffset 0.45 will advance the input on it's left with respect to the input on it's right., in the cases above audio advances by 450ms

^+F12::
Gosub, HotkeyRecStart
Gosub, GuiStart
Run, %comspec% /c ffmpeg -f dshow -i audio="%devStereoMix%" -f gdigrab -framerate %recFPS% -draw_mouse 1 -i desktop -c:v libx264 -qp 0 -pix_fmt yuv444p -preset ultrafast -y "%SaveDir%\%fileName%", , Hide, PID
Return

^+F10::
Gosub, HotkeyRecStart
Gosub, GuiStart
; RunWait, %comspec% /c ffmpeg   -loglevel info   -f dshow  -video_device_number 0 -i video="screen-capture-recorder"  -f dshow -audio_device_number 0 -i audio="virtual-audio-capturer"  -f dshow -audio_device_number 0 -i audio="%devMicrophonePrimary%"  -filter_complex amix=inputs=2  -vcodec libx264  -pix_fmt yuv420p  -preset ultrafast -vsync vfr -acodec libmp3lame -f mp4 -y "%SaveDir%\%fileName%", , Hide, PID
RunWait, %comspec% /c ffmpeg -rtbufsize 1024M -f dshow -i video="UScreenCapture":audio="%devStereoMix%" -r 40 -vcodec libx264 -threads 0 -crf 0 -preset ultrafast -tune zerolatency -acodec libmp3lame -y "%SaveDir%\%fileName%.flv", , Hide, PID
Return

^+F11::
Gosub, GuiClose
SoundBeep, 500
Return

HotkeyRecStart:
Loop, 2
	SoundBeep, 1000
lastSaveDir := INI("r", "LastSaveDir", "LastSaveDir",,, "ffmpeg.rec.ini")
SaveDir := ( InStr(path, ":\") ? path : (lastSaveDir ? lastSaveDir : A_Desktop) )
devMicrophonePrimary := INI("r", "DEVICES", "PrimaryMicrophone",,, "ffmpeg.rec.ini")
devStereoMix := INI("r", "DEVICES", "SpeakerOutputStereoMix",,, "ffmpeg.rec.ini")
devUsbCamera := INI("r", "DEVICES", "USBCamera",,, "ffmpeg.rec.ini")
recFPS := INI("r", "RecordingFPS", "RecordingFPS",,, "ffmpeg.rec.ini")
bufferSize := INI("r", "BufferSize", "BufferSize",,, "ffmpeg.rec.ini")	;-bufsize
rtBufferSize := INI("r", "BufferSize", "RealTimeBufferSize",,, "ffmpeg.rec.ini")	;-rtbufsize
WinGet, activeProcess, ProcessName, A
fileName := activeProcess . "[" . A_Now . "].mp4"
Return

;=========================================================================================================================
~^F9::
~^+F9::	;mcgee's setup
recording := ( !recording AND WinExist("ahk_exe obs64.exe") ? ToneRec() : (WinExist("ahk_exe obs64.exe") ? ToneRecStopped() : ToneRecErr()) )
Return
obsRecNotifier(){
	Global
	If ( GetKeyState("Ctrl") AND GetKeyState("F9") ){
		recording := ( !recording AND WinExist("ahk_exe obs64.exe") ? ToneRec() : (WinExist("ahk_exe obs64.exe") ? ToneRecStopped() : ToneRecErr()) 30 -i 
	if (window=RealTimeBufferSize)
	}Else If ( ProcessExist("obs64.exe") AND ProcessExist("ffmpeg-mux64.exe") ){
		recording := True
	}Else If ( ProcessExist("obs64.exe") AND !ProcessExist("ffmpeg-mux64.exe") ){
		recording := False
	}
}
ToneRec(){
	SoundBeep, 2000
	Return True
}
ToneRecStopped(){
	SoundBeep, 500
	Return False
}
ToneRecErr(){
	SoundBeep, 1500, 1000
}
;=========================================================================================================================
ProcessExist(procName){
	Process, Exist, %procName%
	Return ErrorLevel
}

AHK_NOTIFYICON(wParam, lParam)
{
	if (lParam = 0x205){ ; WM_RBUTTONUP
		Menu, MyMenu, Show
		Return 0
	}
}

live ? long & prosper : regards
User avatar
Epialis
Posts: 858
Joined: 02 Aug 2020, 22:44

Re: Recording desktop with ffmpeg & AutoHotkey

28 Dec 2020, 19:18

Great additions. Anyone think of also adding audio to the recordings? Thank you all for the hard work.
User avatar
Joe Glines
Posts: 770
Joined: 30 Sep 2013, 20:49
Location: Dallas
Contact:

Re: Recording desktop with ffmpeg & AutoHotkey

03 Jan 2021, 11:02

Epialis wrote:
28 Dec 2020, 19:18
Great additions. Anyone think of also adding audio to the recordings? Thank you all for the hard work.
Perhaps I'm missing something. I don't think an animated gif can have audio. The post started off recording your desktop in mp4 format (which includes audio)
Sign-up for the 🅰️HK Newsletter

ImageImageImageImage:clap:
AHK Tutorials:Web Scraping | | Webservice APIs | AHK and Excel | Chrome | RegEx | Functions
Training: AHK Webinars Courses on AutoHotkey :ugeek:
YouTube

:thumbup: Quick Access Popup, the powerful Windows folders, apps and documents launcher!
User avatar
Epialis
Posts: 858
Joined: 02 Aug 2020, 22:44

Re: Recording desktop with ffmpeg & AutoHotkey

03 Jan 2021, 14:35

Joe Glines wrote:
03 Jan 2021, 11:02
Epialis wrote:
28 Dec 2020, 19:18
Great additions. Anyone think of also adding audio to the recordings? Thank you all for the hard work.
Perhaps I'm missing something. I don't think an animated gif can have audio. The post started off recording your desktop in mp4 format (which includes audio)
Sorry, I didn't mean to be confusing. Yes, it records the desktop, but there isn't any sound that is recorded with it; unless I am doing something wrong. I tried just steriomix but no sound
MancioDellaVega
Posts: 83
Joined: 16 May 2020, 12:27
Location: Italy

Re: Recording desktop with ffmpeg & AutoHotkey

04 Jan 2021, 12:27

Someone can add the option to pause and resume the recording?...if is possible. Thanks
Courses on AutoHotkey
swub
Posts: 19
Joined: 25 Feb 2019, 09:16

Re: Recording desktop with ffmpeg & AutoHotkey

28 Dec 2021, 14:28

CyL0N-
I have tried to use this script but I get an error pointing to line 634 - Missing "}"
Here is that section:

Code: Select all

;=========================================================================================================================
~^F9::
~^+F9::	;mcgee's setup
recording := ( !recording AND WinExist("ahk_exe obs64.exe") ? ToneRec() : (WinExist("ahk_exe obs64.exe") ? ToneRecStopped() : ToneRecErr()) )
Return
obsRecNotifier(){
	Global
	If ( GetKeyState("Ctrl") AND GetKeyState("F9") ){
		recording := ( !recording AND WinExist("ahk_exe obs64.exe") ? ToneRec() : (WinExist("ahk_exe obs64.exe") ? ToneRecStopped() : ToneRecErr()) 30 -i    ; <-- Line 634 but I am not sure where the missing bracket needs to go.
	if (window=RealTimeBufferSize)
	} Else If ( ProcessExist("obs64.exe") AND ProcessExist("ffmpeg-mux64.exe") ){
		recording := True
	} Else If ( ProcessExist("obs64.exe") AND !ProcessExist("ffmpeg-mux64.exe") ){
		recording := False
	}
}
Do you happen to know where I need to put one in at?
Thank You,
swub
CyL0N wrote:
28 Sep 2018, 13:32
Here's my ffmpeg wrapper for any one interested, it acts on all selected files in explorer, it does enough that i no longer have a video conversion utility installed,i use avidemux for all other editing needs...

NOTE: you must configure the name of your own corresponding devices to use the extended recording menu entries beyond basic screen recording(i.e microphone,steromix,webcam...)(See: ffmpeg devices doc) in the INI file created after first run


Hotkey is Ctrl+Shift+Alt+C which spawns a menu that will act on all files selected inside explorer,any converted or output files such as a gif output will be to the same folder as selected files...

Edit:One more thing,recordings are saved to active/lastSavedTo explorer path...

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

#SingleInstance, force
DetectHiddenWindows, on

SetBatchLines, -1

GroupAdd, Explore, ahk_class CabinetWClass			; Add a class to the group

GroupAdd, Explore, ahk_class ExploreWClass			; Add a other class to the group

#ifWinActive,ahk_group Explore  				; Set hotkeys to work in explorer only

Menu, Tray, Icon, C:\Windows\System32\shell32.dll, 85
Menu, Tray, Tip,  %A_ScriptName%`n`nCtrl+Shift+Alt+C : ContextMenu `nCtrl+Shift+Alt+Esc : Interrupt Active Conversion.
TrayTip, [CyLoN] %A_ScriptName%, Ctrl+Shift+Alt+C	:	ContextMenu`n Ctrl+Shift+F11 	:	StopAnyActiveRecording`n Ctrl+Shift+F12	:	Start/Stop Lossless Recording`n `n Ctrl+F9/Ctrl+Shift+F9	--->Start/Stop Recording Tones for OBS.
;OBS Hotkey ToneGenerator thread
SetTimer, obsRecNotifier, 2500

;replace tray menu with created menu
; OnMessage(0x404, "AHK_NOTIFYICON")		;allowing normal tray menu as replacing it makes process termination a tad difficult.

IfNotExist, %A_ScriptName%.README.txt
	FileAppend, Press Ctrl+Shift+Alt+C to trigger menu and select conversion/processing task from the menu.`n For Any command on the menu to work ffmpeg.exe must be placed in the windows directory. `n Ctrl+Shift+Alt+Esc can be used to interrupt any active conversion. Incomplete file needs to be manually deleted though! `n`n Ctrl+Shift+Alt+P toggles progress bar. `n`nUpon Interruption Incomplete File Will Be deleted. `n Ctrl+Shift+F12 to record losless video to last folder that was recorded to `n`t Ctrl+Shift+F11 to stop any active recording`, Sound Tones will signify both actions.	, %A_ScriptName%.README.txt

progressBarActive := True

; Create the popup menu by adding some items to it.
Menu, MyMenu, Add, Convert to Mp3 256k, MenuHandler
Menu, MyMenu, Add  ; Add a separator line.
Menu, MyMenu, Add, Convert to Mp3 48k, MenuHandler
Menu, MyMenu, Add  ; Add a separator line.
Menu, MyMenu, Add, Extract mp3 from Selected (no-conversion), MenuHandler
Menu, MyMenu, Add  ; Add a separator line.
Menu, MyMenu, Add, Extract mp3 from Selected (no-conversion) + VideoThumbnail@30secMark, MenuHandler
Menu, MyMenu, Add  ; Add a separator line.
Menu, MyMenu, Add, Trim Silence from Mp3, MenuHandler
Menu, MyMenu, Add  ; Add a separator line.
Menu, MyMenu, Add, Resync Audio [+/-] prefixed seconds, MenuHandler
Menu, MyMenu, Add  ; Add a separator line below the submenu.
Menu, MyMenu, Add  ; Add a separator line below the submenu.
Menu, MyMenu, Add  ; Add a separator line below the submenu.

; Create another menu destined to become a submenu of the above menu.
Menu, Submenu1, Add, MP4 SourceQuality, MenuHandler
Menu, Submenu1, Add  ; Add a separator line.
Menu, Submenu1, Add, MP4 720p, MenuHandler
Menu, Submenu1, Add  ; Add a separator line.
Menu, Submenu1, Add, MP4 480p, MenuHandler
Menu, Submenu1, Add  ; Add a separator line.
Menu, Submenu1, Add, MP4 360p, MenuHandler
Menu, Submenu1, Add  ; Add a separator line.
Menu, Submenu1, Add, MKV To MP4 SourceQuality, MenuHandler
Menu, Submenu1, Add  ; Add a separator line.
Menu, Submenu1, Add, FLV To MP4 SourceQuality, MenuHandler
Menu, Submenu1, Add  ; Add a separator line.
Menu, Submenu1, Add, TS To MP4 SourceQuality, MenuHandler
Menu, Submenu1, Add  ; Add a separator line.
Menu, Submenu1, Add, DAT To MP4 SourceQuality, MenuHandler
Menu, Submenu1, Add  ; Add a separator line.
Menu, Submenu1, Add, Change Video Container to MP4(Fastest)(Identical Video/Audio to Source) - Limited MediaPlayer Support Based On Source Format, MenuHandler
Menu, Submenu1, Add  ; Add a separator line.
Menu, Submenu1, Add, MP4 Lossless Conversion(Source or Superior Quality and Greatest Size), MenuHandler

Menu, Submenu2, Add, ffmpeg_RECORD_display, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_RECORD_display_activeWindow, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_RECORD_display_mic, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_RECORD_display_stereoMix, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_RECORD_mic, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_RECORD_webcam_mic, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_RECORD_webcam_stereoMix, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_LIST_DEVICES_DEBUG, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_GamePlayRecordingOptimised_30fpsLOCKED_AudioResync@450ms+AllInputs+Win7Inputs, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_GamePlayRecordingOptimised_30fpsLOCKED_AudioResync@450ms, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_LOSLESS_display_GreatestSize_stereoMix_AudioResync@450ms, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_GamePlayRecordingOptimised_30fpsLOCKED, MenuHandler
Menu, Submenu2, Add  ; Add a separator line.
Menu, Submenu2, Add, ffmpeg_LOSLESS_display_GreatestSize_stereoMix, MenuHandler

; Create a submenu in the first menu (a right-arrow indicator). When the user selects it, the second menu is displayed.
Menu, MyMenu, Add, Convert to Mp4, :Submenu1
Try
	Menu, MyMenu, Icon, Convert to Mp4, Shell32.dll, 116, 40
Menu, MyMenu, Add, RECORD, :Submenu2
Try
	Menu, MyMenu, Icon, RECORD, Shell32.dll, 204, 40

Menu, MyMenu, Add  ; Add a separator line below the submenu.
Menu, MyMenu, Add  ; Add a separator line below the submenu.
Menu, MyMenu, Add  ; Add a separator line below the submenu.
Menu, MyMenu, Add, Extract Animated Gif from Video, MenuHandler  ; Add another menu item beneath the submenu.
Menu, MyMenu, Add  ; Add a separator line below the submenu.
Menu, MyMenu, Add, Extract VideoThumbnail from Video@30secMark at Video Resolution, MenuHandler  ; Add another menu item beneath the submenu.
Menu, MyMenu, Add  ; Add a separator line below the submenu.
Menu, MyMenu, Add, Extract clip from video at SourceQuality, MenuHandler  ; Add another menu item beneath the submenu.
Menu, MyMenu, Add  ; Add a separator line below the submenu.
Menu, MyMenu, Add, Delete other file format with Mp3 counterpart i.e(x.avi and x.mp3), MenuHandler  ; Add another menu item beneath the submenu.
Menu, MyMenu, Add  ; Add a separator line below the submenu.
Menu, MyMenu, Add, Delete other file format with Mp4 counterpart i.e(x.avi and x.mp4), MenuHandler  ; Add another menu item beneath the submenu.

;Menu, MyMenu, Show

return  ; End of script's auto-execute section.


+!^c::
Menu, MyMenu, Show
Return



#IfWinActive,ahk_group Explore  				; Set hotkeys to work in explorer only
MButton::
Menu, MyMenu, Show
Return
#IfWinActive

+!^p::
If progressBarActive{
	Progress, off
	progressBarActive := False
}Else{
	progressBarActive := True
	Progress, a t b x0 y0 w%A_ScreenWidth%, [%i%/%listToConvNum%] %OutFileName%, PROCESSING, Conversion Progress	;'b' always ontop off & 't' to give progress bar own button on taskbar
	Progress, % i*100/listToConvNum ; Set the position of the bar to 0-100
}
Return

+!^Esc::
term := True	;send termination signal to current processing loop
Process, Close, ffmpeg.exe
RunWait, %comspec% /c Taskkill /f /t /im ffmpeg.exe, , Hide
MsgBox, 0x40010, %A_ScriptName%, INTERRUPTED!`n`nLastProcessedFile[Incomplete Files Will Be Deleted]: `n%OutFileName%
FileDelete, %OutDir%\%convertTo%
Return


MenuHandler:
;MsgBox You selected %A_ThisMenuItem% from the menu %A_ThisMenu%.
Sleep, 250
sel := Explorer_GetSelected()
path := Explorer_GetPath()

Loop, Parse, sel, `n
{
	SplitPath, A_LoopField, OutFileName, OutDir, OutExtension, OutNameNoExt, OutDrive
	IfEqual, OutExtension, lnk
	{
		FileGetShortcut, %A_LoopField%, OutTarget, OutDir, OutArgs, OutDescription, OutIcon, OutIconNum, OutRunState
		SplitPath, A_LoopField, OutFileName, OutDir, OutExtension, OutNameNoExt, OutDrive
	}
	
	listToConv .= OutExtension != "lnk" ? A_LoopField "`n" : OutTarget "`n"
}

IfEqual, A_ThisMenu, Submenu2
	Goto, recHandler	;jump


MsgBox, 0x40031, %A_ScriptName%, %A_ThisMenuItem%`? `n`n***Invalid files will be ignored`,so they can be included in selection.*** `n`n %listToConv%
IfMsgBox, Cancel
	Return

listToConvNum := ListCount(listToConv)
listToConv := ""


FileAppend, [%TimeString%]	COMMAND	--->	%A_ThisMenuItem% `n, %A_Desktop%\%A_ScriptName%.LOG.log
Loop, Parse, sel, `n
{
	SplitPath, A_LoopField, OutFileName, OutDir, OutExtension, OutNameNoExt, OutDrive
	IfEqual, OutExtension, lnk
	{
		FileGetShortcut, %A_LoopField%, OutTarget, OutDir, OutArgs, OutDescription, OutIcon, OutIconNum, OutRunState
		SplitPath, OutTarget, OutFileName, OutDir, OutExtension, OutNameNoExt, OutDrive
	}
	FormatTime, TimeString, T8 T2 T4 R
	FileAppend, [%TimeString%]	processing --->	%A_LoopField% `n, %A_Desktop%\%A_ScriptName%.LOG.log
	
	i++
	If progressBarActive
	{
		; WinGetActiveTitle, activeTitle
		; Progress, b x0 y0 w%A_ScreenWidth%, %OutFileName%, CONVERTING, This Progress Bar
		Progress, a t b x0 y0 w%A_ScreenWidth%, [%i%/%listToConvNum%] %OutFileName%, PROCESSING, Conversion Progress	;'b' always ontop off & 't' to give progress bar own button on taskbar
		Progress, % i*100/listToConvNum ; Set the position of the bar to 0-100
		; Sleep, 25
		; WinActivate, %activeTitle%	;to prevent progress bar stealing focus while processing files.
	}
	
	
	;mp3 conversions/extractions
	If ( A_ThisMenuItem = "Convert to Mp3 256k" AND A_ThisMenu = "MyMenu" ){
		convertTo = %OutNameNoExt%.mp3
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -acodec libmp3lame -ab 256 "%OutDir%\%OutNameNoExt%.mp3", , Hide
	}Else If ( A_ThisMenuItem = "Convert to Mp3 48k" AND A_ThisMenu = "MyMenu" ){
		convertTo = %OutNameNoExt%.mp3
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -acodec libmp3lame -ab 48k "%OutDir%\%OutNameNoExt%.mp3", , Hide
	}Else If ( A_ThisMenuItem = "Extract mp3 from Selected (no-conversion)" AND A_ThisMenu = "MyMenu" ){
		convertTo = %OutNameNoExt%.mp3
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -vn "%OutDir%\%OutNameNoExt%.mp3", , Hide
	}Else If ( A_ThisMenuItem = "Extract mp3 from Selected (no-conversion) + VideoThumbnail@30secMark" AND A_ThisMenu = "MyMenu" ){
		convertTo = %OutNameNoExt%.mp3
		RunWait, %comspec% /c echo n|ffmpeg -ss 00:00:30 -i "%OutDir%\%OutFileName%" -vframes 1 -q:v 2 "%OutDir%\%OutNameNoExt%.jpg", , Hide
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -vn "%OutDir%\%OutNameNoExt%.mp3", , Hide
	}Else If ( A_ThisMenuItem = "Trim Silence from Mp3" AND A_ThisMenu = "MyMenu" ){
		convertTo = %OutNameNoExt%[noSilence].mp3
		InputBox, threshHold, Input Silence Threshold in dB, Lower is More sensitive & will trim more sound`,i.e -25 will more trimming than -40(which is the default)!, , 636, 136, 538, 416, , , -40
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -af silenceremove=0:0:0:-1:1:%threshHold%dB -y "%OutDir%\%OutNameNoExt%[noSilence].mp3", , Hide
	}Else If ( A_ThisMenuItem = "Resync Audio [+/-] prefixed seconds" AND A_ThisMenu = "MyMenu" ){
		convertTo = %OutNameNoExt%[Resync].mp4
		InputBox, resyncSeconds, Resync Audio, Input Seconds To Pull-Back/Push-Fwd audio with respect to video!`n-->	output video will have [Resync] suffix., , 428, 144, 564, 212, , , -0.45
		If ErrorLevel
			Return
		RunWait, %comspec% /c ffmpeg -i "%OutDir%\%OutFileName%" -itsoffset %resyncSeconds% -i "%OutDir%\%OutFileName%" -map 0:0 -map 1:1  -acodec copy -vcodec copy -y "%OutDir%\%OutNameNoExt%[Resync].mp4", , Hide
	}
	
	
	;Convert to Mp4
	If ( A_ThisMenuItem = "MP4 SourceQuality" AND A_ThisMenu = "Submenu1" ){
		convertTo = %OutNameNoExt%.mp4
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" "%OutDir%\%OutNameNoExt%.mp4", , Hide
	}Else If ( A_ThisMenuItem = "MP4 720p" AND A_ThisMenu = "Submenu1" ){
		convertTo = %OutNameNoExt%[720p].mp4
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -s hd720 "%OutDir%\%OutNameNoExt%[720p].mp4", , Hide
	}Else If ( A_ThisMenuItem = "MP4 480p" AND A_ThisMenu = "Submenu1" ){
		convertTo = %OutNameNoExt%[480p].mp4
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -s hd480 "%OutDir%\%OutNameNoExt%[480p].mp4", , Hide
	}Else If ( A_ThisMenuItem = "MP4 360p" AND A_ThisMenu = "Submenu1" ){
		convertTo = %OutNameNoExt%[360p].mp4
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -s ega "%OutDir%\%OutNameNoExt%[360p].mp4", , Hide
	}Else If ( A_ThisMenuItem = "MKV To MP4 SourceQuality" AND A_ThisMenu = "Submenu1" AND OutExtension = "mkv"){
		convertTo = %OutNameNoExt%.mp4
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" "%OutDir%\%OutNameNoExt%.mp4", , Hide
	}Else If ( A_ThisMenuItem = "FLV To MP4 SourceQuality" AND A_ThisMenu = "Submenu1" AND OutExtension = "flv"){
		convertTo = %OutNameNoExt%.mp4
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -c copy -copyts "%OutDir%\%OutNameNoExt%.mp4", , Hide
	}Else If ( A_ThisMenuItem = "TS To MP4 SourceQuality" AND A_ThisMenu = "Submenu1" AND OutExtension = "ts"){
		convertTo = %OutNameNoExt%.mp4
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -c copy -copyts "%OutDir%\%OutNameNoExt%.mp4", , Hide
	}Else If ( A_ThisMenuItem = "DAT To MP4 SourceQuality" AND A_ThisMenu = "Submenu1" AND OutExtension = "dat" OR  A_ThisMenuItem = "DAT To MP4 SourceQuality" AND A_ThisMenu = "Submenu1" AND OutExtension = "mpg"){
		convertTo = %OutNameNoExt%.mp4
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -c:v libx264 -preset slow -crf 15 -c:a aac -strict experimental -b:a 128k "%OutDir%\%OutNameNoExt%.mp4", , Hide
	}Else If ( A_ThisMenuItem = "Change Video Container to MP4(Fastest)(Identical Video/Audio to Source) - Limited MediaPlayer Support Based On Source Format" AND A_ThisMenu = "Submenu1"){
		convertTo = %OutNameNoExt%.mp4
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -c copy -copyts -scodec mov_text "%OutDir%\%OutNameNoExt%.mp4", , Hide
	}Else If ( A_ThisMenuItem = "MP4 Lossless Conversion(Source or Superior Quality and Greatest Size)" AND A_ThisMenu = "Submenu1"){
		convertTo = %OutNameNoExt%.mp4
		RunWait, %comspec% /c echo n|ffmpeg -i "%OutDir%\%OutFileName%" -c:v libx264 -crf 0 -c:a copy -copyts "%OutDir%\%OutNameNoExt%.mp4", , Hide
	}
	
	;Video to Gif
	If ( A_ThisMenuItem = "Extract Animated Gif from Video" AND A_ThisMenu = "MyMenu" ){
		If !timeRangeDefined{
			InputBox, startTime, video2gif, StartTime(time in video where gif will start off)`,`nomitting starttime by clearing the input field will `nconvert full video into gif!`n`nNOTE:gif files are upto 20x the size of a video equivalent..., , , , , , , , 00:01:00
			InputBox, endTime, video2gif, gifLength(how many seconds to encode to gif since start time)`,`n`n10`, means 10 seconds starting from previously input start time will be`nsaved to gif`,so based on previous default value`, gif will be 10seconds`nlong and will start at minute 1 of the video..., , 446, 212, , , , , 10
			timeRangeDefined := True
		}
		If startTime
			RunWait, %comspec% /c echo n| ffmpeg -i "%OutDir%\%OutFileName%" -ss %startTime% -t %endTime% "%OutDir%\%OutNameNoExt%.gif", , Hide
		Else If endTime
			RunWait, %comspec% /c echo n| ffmpeg -i "%OutDir%\%OutFileName%" "%OutDir%\%OutNameNoExt%.gif", , Hide
		Else If (!startTime AND !endTime){
			MsgBox, 0x40010, %A_ScriptName%, Range NOT DEFINED OR INCORRECTLY DEFINED`, TryAGAIN!
		}
	}
	
	;video snapshot
	If ( A_ThisMenuItem = "Extract VideoThumbnail from Video@30secMark at Video Resolution" AND A_ThisMenu = "MyMenu" ){
		RunWait, %comspec% /c echo n|ffmpeg -ss 00:00:30 -i "%OutDir%\%OutFileName%" -vframes 1 -q:v 2 "%OutDir%\%OutNameNoExt%.jpg", , Hide
	}
	
	;extract clip from video
	If ( A_ThisMenuItem = "Extract clip from video at SourceQuality" AND A_ThisMenu = "MyMenu" ){
		If !timeRangeDefined{
			InputBox, startTime, clipExtract, StartTime(time in video where clip will start off)`,`nomitting starttime by clearing the input field will `nextract clip from video begining + n Seconds , , , , , , , , 00:01:00
			InputBox, endTime, clipExtract, clipLength(how many seconds to encode to clip since start time)`,`n`n10`, means 10 seconds starting from previously input start time will be`nsaved to clip`,so based on previous default value`, clip will be 10seconds`nlong and will start at minute 1 of the video..., , 446, 212, , , , , 10
			timeRangeDefined := True
		}
		If startTime
			RunWait, %comspec% /c echo n| ffmpeg -i "%OutDir%\%OutFileName%" -ss %startTime% -t %endTime% "%OutDir%\%OutNameNoExt%.CLIP%A_NOW%.mp4", , Hide
		Else If endTime
			RunWait, %comspec% /c echo n| ffmpeg -i "%OutDir%\%OutFileName%" -ss 00:00:00 -t %endTime% "%OutDir%\%OutNameNoExt%.CLIP%A_NOW%.mp4", , Hide
		Else If (!startTime AND !endTime){
			MsgBox, 0x40010, %A_ScriptName%, Range NOT DEFINED OR INCORRECTLY DEFINED`, TryAGAIN!
		}
	}
	
	;Delete Files with MP4 Counter part
	If ( A_ThisMenuItem = "Delete other file format with Mp4 counterpart i.e(x.avi and x.mp4)" AND A_ThisMenu = "MyMenu" AND OutExtension != "Mp4"){
		FileGetSize, thisFileSize, %OutDir%\%OutNameNoExt%.mp4
		IfExist, %OutDir%\%OutNameNoExt%.mp4		;if the file has an MP4 counterpart delete original,i.e current file.
			If (thisFileSize AND thisFileSize != 0)
				{
					FileDelete, %OutDir%\%OutFileName%
					FormatTime, TimeString, T8 T2 T4 R
					FileAppend, [%TimeString%]	DELETING --->	%A_LoopField% `n, %A_Desktop%\%A_ScriptName%.LOG.log
				}
	}Else If ( A_ThisMenuItem = "Delete other file format with Mp3 counterpart i.e(x.avi and x.mp3)" AND A_ThisMenu = "MyMenu" AND OutExtension != "mp3" AND OutExtension != "jpg" AND OutExtension != "description"){
		FileGetSize, thisFileSize, %OutDir%\%OutNameNoExt%.mp3
		IfExist, %OutDir%\%OutNameNoExt%.mp3		;if the file has an MP4 counterpart delete original,i.e current file.
			If (thisFileSize AND thisFileSize != 0)
				{
					FileDelete, %OutDir%\%OutFileName%
					FormatTime, TimeString, T8 T2 T4 R
					FileAppend, [%TimeString%]	DELETING --->	%A_LoopField% `n, %A_Desktop%\%A_ScriptName%.LOG.log
				}
	}
	
	
	;Zero File Remnant Safeguard
	FileGetSize, convertToSize, %OutDir%\%convertTo%
	If (convertToSize = 0){
		MsgBox, 0x40010, %A_ScriptName%, Conversion To %convertTo% Failed!`n`nPress Ok to delete zerobyte file and proceed with conversion.
		FileDelete, %OutDir%\%convertTo%
	}

	
	
	
	
	If term
	{
		Progress, Off
		stats := ""
		term := ""
		convertTo := ""
		i := ""
		Return
	}
	If !stats
		stats .=  "`n" A_ThisMenuItem  "`n[Only Valid Selected Files below are acted UpOn...Rest are Ignored.]" "`n`n"
	stats .= A_LoopField "`n"
}
Progress, 100 ; Set the position of the bar to 0-100

timeRangeDefined := False	;reset

MsgBox, 0x40040, %A_ScriptName%, CONVERSION COMPLETE! %stats%

Progress, Off

stats := ""
term := ""
convertTo := ""
i := ""
return



/*
	Library for getting info from a specific explorer window (if window handle not specified, the currently active
	window will be used).  Requires AHK_L or similar.  Works with the desktop.  Does not currently work with save
	dialogs and such.
	
	
	Explorer_GetSelected(hwnd="")   - paths of target window's selected items
	Explorer_GetAll(hwnd="")        - paths of all items in the target window's folder
	Explorer_GetPath(hwnd="")       - path of target window's folder
	
	example:
	F1::
	path := Explorer_GetPath()
	all := Explorer_GetAll()
	sel := Explorer_GetSelected()
	MsgBox % path
	MsgBox % all
	MsgBox % sel
	return
	
	Joshua A. Kinnison
	2011-04-27, 16:12
*/

Explorer_GetPath(hwnd="")
{
	if !(window := Explorer_GetWindow(hwnd))
		return ErrorLevel := "ERROR"
	if (window="desktop")
		return A_Desktop
	path := window.LocationURL
	path := RegExReplace(path, "ftp://.*@","ftp://")
	StringReplace, path, path, file:///
	StringReplace, path, path, /, \, All
	
	; thanks to polyethene
	Loop
		If RegExMatch(path, "i)(?<=%)[\da-f]{1,2}", hex)
			StringReplace, path, path, `%%hex%, % Chr("0x" . hex), All
	Else Break
		return path
}
Explorer_GetAll(hwnd="")
{
	return Explorer_Get(hwnd)
}
Explorer_GetSelected(hwnd="")
{
	return Explorer_Get(hwnd,true)
}

Explorer_GetWindow(hwnd="")
{
	; thanks to jethrow for some pointers here
	WinGet, process, processName, % "ahk_id" hwnd := hwnd? hwnd:WinExist("A")
	WinGetClass class, ahk_id %hwnd%
	
	if (process!="explorer.exe")
		return
	if (class ~= "(Cabinet|Explore)WClass")
	{
		for window in ComObjCreate("Shell.Application").Windows
			if (window.hwnd==hwnd)
				return window
	}
	else if (class ~= "Progman|WorkerW")
		return "desktop" ; desktop found
}
Explorer_Get(hwnd="",selection=false)
{
	if !(window := Explorer_GetWindow(hwnd))
		return ErrorLevel := "ERROR"
	if (window="desktop")
	{
		ControlGet, hwWindow, HWND,, SysListView321, ahk_class Progman
		if !hwWindow ; #D mode
			ControlGet, hwWindow, HWND,, SysListView321, A
		ControlGet, files, List, % ( selection ? "Selected":"") "Col1",,ahk_id %hwWindow%
		base := SubStr(A_Desktop,0,1)=="\" ? SubStr(A_Desktop,1,-1) : A_Desktop
		Loop, Parse, files, `n, `r
		{
			path := base "\" A_LoopField
			IfExist %path% ; ignore special icons like Computer (at least for now)
				ret .= path "`n"
		}
	}
	else
	{
		if selection
			collection := window.document.SelectedItems
		else
			collection := window.document.Folder.Items
		for item in collection
			ret .= item.path "`n"
	}
	return Trim(ret,"`n")
}





ListCount(ByRef list){
	StringReplace, list, list, `n, `n, UseErrorLevel
	Return ErrorLevel + 1
}


INI(rw, ini_section, ini_key, key_value:="", key_default_value:="", ini_file:="######.ini"){	;r/w - 'r' to read & 'w' to write to ini
	If (rw = "r"){	;read from ini
		IniRead, thisKey, %ini_file%, %ini_section%, %ini_key%, %key_default_value%
		Return ( thisKey != "ERROR" ? thisKey : "")
	}Else{	;write to ini
		IniWrite, %key_value%, %ini_file%, %ini_section%, %ini_key%
	}
}

;==========================================================
GuiStart:
Gui , font, s8 bold, Verdana
Gui , Add , button , w150 h75 vButton1 gGuiClose, RECORDING...`n`nClick to Terminate Recording!
Gui , -caption
Gui , Show ,AutoSize Center xCenter y0 NA, ffmpeg.RECORDER
Return

GuiClose:
Critical
GuiControl,, Button1, Stopping...
While ( WinExist("ahk_pid " . PID) OR WinExist("ahk_pid " . pid1) OR WinExist("ahk_pid " . pid2) OR WinExist("ahk_pid " . pid3) ){
	WinClose, ahk_pid %PID%
	WinClose, ahk_pid %PID1%
	WinClose, ahk_pid %PID2%
	WinClose, ahk_pid %PID3%
	If (A_Index=10){
		Process, Close, %pid2%	;pid 2 is reserved for audio recording instances that tend to get stuck!!!
		WinActivate, ahk_pid %pid3%
		PostMessage, 0x112, 0xF060,,, ahk_pid %pid3%  ; 0x112 = WM_SYSCOMMAND, 0xF060 = SC_CLOSE
	}
	Sleep, 50
}
Gui, Destroy
Critical, off
MsgBox, 0x40040, %A_ScriptName%, Recording Saved to %SaveDir%\%fileName%
Return

;========================================================

;record menu handlers
recHandler:
msgout:=""

( INI("r", "DEVICES", "PrimaryMicrophone",,, "ffmpeg.rec.ini") ? "" : INI("w", "DEVICES", "PrimaryMicrophone", "Microphone (Realtek High Defini",, "ffmpeg.rec.ini") )
( INI("r", "DEVICES", "SpeakerOutputStereoMix",,, "ffmpeg.rec.ini") ? "" : INI("w", "DEVICES", "SpeakerOutputStereoMix", "Stereo Mix (Realtek High Defini",, "ffmpeg.rec.ini") )
( INI("r", "DEVICES", "USBCamera",,, "ffmpeg.rec.ini") ? "" : INI("w", "DEVICES", "USBCamera", "USB 2.0 Camera",, "ffmpeg.rec.ini") )
( INI("r", "RecordingFPS", "RecordingFPS",,, "ffmpeg.rec.ini") ? "" : INI("w", "RecordingFPS", "RecordingFPS", "30",, "ffmpeg.rec.ini") )
( INI("r", "BufferSize", "BufferSize",,, "ffmpeg.rec.ini") ? "" : INI("w", "BufferSize", "BufferSize", "200M",, "ffmpeg.rec.ini") )
( INI("r", "BufferSize", "RealTimeBufferSize",,, "ffmpeg.rec.ini") ? "" : INI("w", "BufferSize", "RealTimeBufferSize", "1024M",, "ffmpeg.rec.ini") )


path := Explorer_GetPath()
lastSaveDir := INI("r", "LastSaveDir", "LastSaveDir",,, "ffmpeg.rec.ini")
SaveDir := ( InStr(path, ":\") ? path : (lastSaveDir ? lastSaveDir : A_Desktop) )
INI("w", "LastSaveDir", "LastSaveDir", SaveDir,, "ffmpeg.rec.ini")

devMicrophonePrimary := INI("r", "DEVICES", "PrimaryMicrophone",,, "ffmpeg.rec.ini")
devStereoMix := INI("r", "DEVICES", "SpeakerOutputStereoMix",,, "ffmpeg.rec.ini")
devUsbCamera := INI("r", "DEVICES", "USBCamera",,, "ffmpeg.rec.ini")
recFPS := INI("r", "RecordingFPS", "RecordingFPS",,, "ffmpeg.rec.ini")
bufferSize := INI("r", "BufferSize", "BufferSize",,, "ffmpeg.rec.ini")	;-bufsize
rtBufferSize := INI("r", "BufferSize", "RealTimeBufferSize",,, "ffmpeg.rec.ini")	;-rtbufsize
; MsgBox % devMicrophonePrimary "`n" devStereoMix "`n" devUsbCamera "`n" recFPS "`n" bufferSize

If (A_ThisMenu = "Submenu2" AND A_ThisMenuItem != "ffmpeg_LIST_DEVICES_DEBUG"){
	WinGet, activeProcess, ProcessName, A
	InputBox, fileName, SaveAs  (mp4 for HD`,any other for LowRes), Input file name to save to desktop(including extension):, , 350, 136, , , , , %activeProcess%[%A_Now%].mp4
	If ErrorLevel
		Return
}Else If ( fileName="" || !InStr(fileName, ".") ){	;if cancel or no extension defined
	If (A_ThisMenuItem != "ffmpeg_LIST_DEVICES_DEBUG"){
		MsgBox, 0x40010, %A_ScriptName%, Invalid FileName or No File Extension Given`, Aborting!
		Return
	}
}
If ( A_ThisMenuItem = "ffmpeg_RECORD_display" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg -f gdigrab -framerate %recFPS% -i desktop "%SaveDir%\%fileName%" -y, , Hide, PID
}Else If ( A_ThisMenuItem = "ffmpeg_RECORD_display_activeWindow" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	Sleep, 2500
	WinGetActiveTitle, _activeWindow
	RunWait, %comspec% /c ffmpeg -f gdigrab -framerate %recFPS% -i title="%_activeWindow%" "%SaveDir%\%fileName%" -y, , Hide, PID
}Else If ( A_ThisMenuItem = "ffmpeg_RECORD_display_mic" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg -f dshow -i audio="%devMicrophonePrimary%" -itsoffset 0.45 -f gdigrab -framerate %recFPS% -i desktop -y "%SaveDir%\%fileName%", , Hide, pid
}Else If ( A_ThisMenuItem = "ffmpeg_RECORD_display_stereoMix" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg -f dshow -i audio="%devStereoMix%" -itsoffset 0.45 -f gdigrab -framerate %recFPS% -i desktop -y "%SaveDir%\%fileName%", , Hide, pid
}Else If ( A_ThisMenuItem = "ffmpeg_RECORD_mic" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg -f dshow -i audio="%devMicrophonePrimary%" -y "%SaveDir%\%fileName%.mp3", , Hide, PID2
}Else If ( A_ThisMenuItem = "ffmpeg_RECORD_webcam_mic" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg -f dshow -i video="%devUsbCamera%"`:audio="%devMicrophonePrimary%" -framerate %recFPS% -y "%SaveDir%\%fileName%", , Hide, PID3
}Else If ( A_ThisMenuItem = "ffmpeg_RECORD_webcam_stereoMix" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg -f dshow -i video="%devUsbCamera%"`:audio="%devStereoMix%" -framerate %recFPS% -y "%SaveDir%\%fileName%", , Hide, PID3
	; Gosub, GuiClose
}Else If (A_ThisMenuItem = "ffmpeg_LIST_DEVICES_DEBUG" AND A_ThisMenu = "Submenu2" ){
	Run, %comspec% /k ffmpeg -list_devices true -f dshow -i dummy
}Else If (A_ThisMenuItem = "ffmpeg_GamePlayRecordingOptimised_30fpsLOCKED_AudioResync@450ms+AllInputs+Win7Inputs" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg  -rtbufsize %rtBufferSize% -loglevel info   -f dshow  -video_device_number 0 -i video="screen-capture-recorder"  -f dshow -audio_device_number 0 -i audio="virtual-audio-capturer"  -f dshow -audio_device_number 0 -i audio="%devMicrophonePrimary%"  -filter_complex amix=inputs=2  -vcodec libx264  -pix_fmt yuv420p  -preset ultrafast -vsync vfr -acodec libmp3lame -f mp4 -y "%SaveDir%\%fileName%", , Hide, PID
}Else If (A_ThisMenuItem = "ffmpeg_GamePlayRecordingOptimised_30fpsLOCKED_AudioResync@450ms" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg -f dshow -i audio="%devStereoMix%" -itsoffset 0.45 -f gdigrab -framerate 30 -i desktop -c:v libx264 -preset ultrafast -crf 1 -maxrate 20M -bufsize %bufferSize% -vsync vfr -acodec libmp3lame -f mp4 -y "%SaveDir%\%fileName%", , Hide, PID
}Else If (A_ThisMenuItem = "ffmpeg_LOSLESS_display_GreatestSize_stereoMix_AudioResync@450ms" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg -f dshow -i audio="%devStereoMix%" -itsoffset 0.45 -f gdigrab -framerate %recFPS% -draw_mouse 1 -i desktop -c:v libx264 -qp 0 -pix_fmt yuv444p -preset ultrafast -y "%SaveDir%\%fileName%", , Hide, PID
}Else If (A_ThisMenuItem = "ffmpeg_GamePlayRecordingOptimised_30fpsLOCKED" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg -f dshow -i audio="%devStereoMix%" -f gdigrab -framerate 30 -i desktop -c:v libx264 -preset ultrafast -crf 1 -maxrate 20M -bufsize  %bufferSize% -y "%SaveDir%\%fileName%", , Hide, PID
}Else If (A_ThisMenuItem = "ffmpeg_LOSLESS_display_GreatestSize_stereoMix" AND A_ThisMenu = "Submenu2" ){
	Gosub, GuiStart
	RunWait, %comspec% /c ffmpeg -f dshow -i audio="%devStereoMix%" -f gdigrab -framerate %recFPS% -draw_mouse 1 -i desktop -c:v libx264 -qp 0 -pix_fmt yuv444p -preset ultrafast -y "%SaveDir%\%fileName%", , Hide, PID
}
Return
; -itsoffset 0.45 will advance the input on it's left with respect to the input on it's right., in the cases above audio advances by 450ms

^+F12::
Gosub, HotkeyRecStart
Gosub, GuiStart
Run, %comspec% /c ffmpeg -f dshow -i audio="%devStereoMix%" -f gdigrab -framerate %recFPS% -draw_mouse 1 -i desktop -c:v libx264 -qp 0 -pix_fmt yuv444p -preset ultrafast -y "%SaveDir%\%fileName%", , Hide, PID
Return

^+F10::
Gosub, HotkeyRecStart
Gosub, GuiStart
; RunWait, %comspec% /c ffmpeg   -loglevel info   -f dshow  -video_device_number 0 -i video="screen-capture-recorder"  -f dshow -audio_device_number 0 -i audio="virtual-audio-capturer"  -f dshow -audio_device_number 0 -i audio="%devMicrophonePrimary%"  -filter_complex amix=inputs=2  -vcodec libx264  -pix_fmt yuv420p  -preset ultrafast -vsync vfr -acodec libmp3lame -f mp4 -y "%SaveDir%\%fileName%", , Hide, PID
RunWait, %comspec% /c ffmpeg -rtbufsize 1024M -f dshow -i video="UScreenCapture":audio="%devStereoMix%" -r 40 -vcodec libx264 -threads 0 -crf 0 -preset ultrafast -tune zerolatency -acodec libmp3lame -y "%SaveDir%\%fileName%.flv", , Hide, PID
Return

^+F11::
Gosub, GuiClose
SoundBeep, 500
Return

HotkeyRecStart:
Loop, 2
	SoundBeep, 1000
lastSaveDir := INI("r", "LastSaveDir", "LastSaveDir",,, "ffmpeg.rec.ini")
SaveDir := ( InStr(path, ":\") ? path : (lastSaveDir ? lastSaveDir : A_Desktop) )
devMicrophonePrimary := INI("r", "DEVICES", "PrimaryMicrophone",,, "ffmpeg.rec.ini")
devStereoMix := INI("r", "DEVICES", "SpeakerOutputStereoMix",,, "ffmpeg.rec.ini")
devUsbCamera := INI("r", "DEVICES", "USBCamera",,, "ffmpeg.rec.ini")
recFPS := INI("r", "RecordingFPS", "RecordingFPS",,, "ffmpeg.rec.ini")
bufferSize := INI("r", "BufferSize", "BufferSize",,, "ffmpeg.rec.ini")	;-bufsize
rtBufferSize := INI("r", "BufferSize", "RealTimeBufferSize",,, "ffmpeg.rec.ini")	;-rtbufsize
WinGet, activeProcess, ProcessName, A
fileName := activeProcess . "[" . A_Now . "].mp4"
Return

;=========================================================================================================================
~^F9::
~^+F9::	;mcgee's setup
recording := ( !recording AND WinExist("ahk_exe obs64.exe") ? ToneRec() : (WinExist("ahk_exe obs64.exe") ? ToneRecStopped() : ToneRecErr()) )
Return
obsRecNotifier(){
	Global
	If ( GetKeyState("Ctrl") AND GetKeyState("F9") ){
		recording := ( !recording AND WinExist("ahk_exe obs64.exe") ? ToneRec() : (WinExist("ahk_exe obs64.exe") ? ToneRecStopped() : ToneRecErr()) 30 -i 
	if (window=RealTimeBufferSize)
	}Else If ( ProcessExist("obs64.exe") AND ProcessExist("ffmpeg-mux64.exe") ){
		recording := True
	}Else If ( ProcessExist("obs64.exe") AND !ProcessExist("ffmpeg-mux64.exe") ){
		recording := False
	}
}
ToneRec(){
	SoundBeep, 2000
	Return True
}
ToneRecStopped(){
	SoundBeep, 500
	Return False
}
ToneRecErr(){
	SoundBeep, 1500, 1000
}
;=========================================================================================================================
ProcessExist(procName){
	Process, Exist, %procName%
	Return ErrorLevel
}

AHK_NOTIFYICON(wParam, lParam)
{
	if (lParam = 0x205){ ; WM_RBUTTONUP
		Menu, MyMenu, Show
		Return 0
	}
}


Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: tony01 and 112 guests