Skip to content

Instantly share code, notes, and snippets.

@Nachtalb
Last active November 1, 2021 20:10
Show Gist options
  • Save Nachtalb/bb7a4c75c9f24f0741e4ad4ecd26e698 to your computer and use it in GitHub Desktop.
Save Nachtalb/bb7a4c75c9f24f0741e4ad4ecd26e698 to your computer and use it in GitHub Desktop.
Create windows explorer ffmpeg context menu entries
# 1. Change paths in the "template" variable, be sure to have to correct number of backslashes
# 2. python quick_ffmpeg_explorer.py > quick_ffmpeg_explorer.reg
# 3. Double click the "quick_ffmpeg_explorer.reg" file
import re
structure = {
'00_FFMPEG': {
'keys': { 'SubCommands': '', 'MUIVerb': 'FFMPEG' },
'folders': {
'shell': {
'folders': {
'00_to_gif': {'args': {'post_args': '-loop 0', "ext": "gif"}, 'keys': {'MUIVerb': 'to .gif'}},
'01_to_webp': {'args': {"ext": "webp"}, 'keys': {'MUIVerb': 'to .webp'}},
'02_to_looped_webp': {'args': {'post_args': '-loop 0', "ext": "webp"}, 'keys': {'MUIVerb': 'to looped .webp'}},
'03_to_webm': {'args': {"ext": "webm"}, 'keys': {'MUIVerb': 'to .webm'}},
'04_to_mp4': {'args': {'post_args': '-vcodec libx264 -preset fast', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4'}},
'05_to_mp4_hevc': {'args': {'post_args': '-vcodec libx265 -preset fast', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (HEVC)'}},
'06_to_mp3': {'args': {'post_args': '-preset fast', "ext": "mp3"}, 'keys': {'MUIVerb': 'to .mp3'}},
'07_to_flac': {'args': {'post_args': '-preset fast', "ext": "flac"}, 'keys': {'MUIVerb': 'to .flac'}},
'08_extract_1_frame': {'args': {'post_args': '-vframes 1', "ext": "jpg", 'filename_addon': '_frame_1'}, 'keys': {'MUIVerb': 'Extract 1st frame (JPG)'}},
'09_extract_x_frame': {'args': {'pre_command': 'md -Force &quot&basename-frames&quot && ', 'full_filename': '&quot&basename-frames/image-%%05d.jpg&quot'}, 'keys': {'MUIVerb': 'Extract all frame (JPG)'}},
'10_extract_x_frame_p':{'args': {'pre_command': 'md -Force &quot&basename-frames&quot && ', 'full_filename': '&quot&basename-frames/image-%%05d.png&quot'}, 'keys': {'MUIVerb': 'Extract all frame (PNG)'}},
},
}
}
},
'01_FFMPEG_extended': {
'keys': { 'SubCommands': '', 'MUIVerb': 'FFMPEG h264' },
'folders': {
'shell': {
'folders': {
'00_to_mp4_h264_copy': {'args': {'post_args': '-c copy', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (copy)'}},
'01_to_mp4_h264_CPU_slow': {'args': {'post_args': '-vcodec libx264 -preset slow', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (CPU slow)'}},
'02_to_mp4_h264_CPU': {'args': {'post_args': '-vcodec libx264', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (CPU)'}},
'03_to_mp4_h264_CPU_fast': {'args': {'post_args': '-vcodec libx264 -preset fast', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (CPU fast)'}},
'04_to_mp4_h264_GPU_slow': {'args': {'post_args': '-vcodec h264_nvenc -preset slow', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (GPU slow)'}},
'05_to_mp4_h264_GPU': {'args': {'post_args': '-vcodec h264_nvenc', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (GPU)'}},
'06_to_mp4_h264_GPU_fast': {'args': {'post_args': '-vcodec h264_nvenc -preset fast', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (GPU fast)'}},
'07_to_mp4_h264_FULL_GPU_slow': {'args': {'pre_args': '-hwaccel cuda -hwaccel_output_format cuda', 'post_args': '-vcodec h264_nvenc -preset slow', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (FULL GPU slow)'}},
'09_to_mp4_h264_FULL_GPU': {'args': {'pre_args': '-hwaccel cuda -hwaccel_output_format cuda', 'post_args': '-vcodec h264_nvenc', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (FULL GPU)'}},
'10_to_mp4_h264_FULL_GPU_fast': {'args': {'pre_args': '-hwaccel cuda -hwaccel_output_format cuda', 'post_args': '-vcodec h264_nvenc -preset fast', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (FULL GPU fast)'}},
},
}
}
},
'02_FFMPEG_extended': {
'keys': { 'SubCommands': '', 'MUIVerb': 'FFMPEG hevc' },
'folders': {
'shell': {
'folders': {
'00_to_mp4_hevc_CPU_copy': {'args': {'post_args': '-c copy', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (copy)'}},
'01_to_mp4_hevc_CPU_slow': {'args': {'post_args': '-vcodec libx265 -preset slow', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (CPU slow)'}},
'02_to_mp4_hevc_CPU': {'args': {'post_args': '-vcodec libx265', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (CPU)'}},
'03_to_mp4_hevc_CPU_fast': {'args': {'post_args': '-vcodec libx265 -preset fast', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (CPU fast)'}},
'04_to_mp4_hevc_GPU_slow': {'args': {'post_args': '-vcodec hevc_nvenc -preset slow', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (GPU slow)'}},
'05_to_mp4_hevc_GPU': {'args': {'post_args': '-vcodec hevc_nvenc', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (GPU)'}},
'06_to_mp4_hevc_GPU_fast': {'args': {'post_args': '-vcodec hevc_nvenc -preset fast', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (GPU fast)'}},
'07_to_mp4_hevc_FULL_GPU_slow': {'args': {'pre_args': '-hwaccel cuda -hwaccel_output_format cuda', 'post_args': '-vcodec hevc_nvenc -preset slow', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (FULL GPU slow)'}},
'08_to_mp4_hevc_FULL_GPU': {'args': {'pre_args': '-hwaccel cuda -hwaccel_output_format cuda', 'post_args': '-vcodec hevc_nvenc', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (FULL GPU)'}},
'09_to_mp4_hevc_FULL_GPU_fast': {'args': {'pre_args': '-hwaccel cuda -hwaccel_output_format cuda', 'post_args': '-vcodec hevc_nvenc -preset fast', "ext": "mp4"}, 'keys': {'MUIVerb': 'to .mp4 (FULL GPU fast)'}},
},
}
}
},
}
basename = '$((Get-Item &quot%V&quot).basename)'
filename_template = '&quot&basename{filename_addon}.{ext}&quot'
template = 'C:\\\\Users\\\\nicko\\\\AppData\\\\Local\\\\Microsoft\\\\WindowsApps\\\\Microsoft.PowerShellPreview_8wekyb3d8bbwe\\\\pwsh.exe -c \\"[console]::WindowWidth=100; {pre_command}C:\\\\ProgramData\\\\scoop\\\\shims\\\\ffmpeg.EXE {pre_args} -i &quot%V&quot {post_args} -y {full_filename} || pause\\"'
print('Windows Registry Editor Version 5.00\n')
def construct_command(title, options):
default = {
'pre_args': '',
'post_args': '',
'filename_addon': '',
'ext': '',
'pre_command': '',
}
if '(' in title:
default['filename_addon'] = '_' + re.findall('\((.*)\)', title)[0].replace(' ', '_')
default.update(options)
if 'full_filename' not in options:
default['full_filename'] = filename_template.format(**default)
return template.format(**default).replace('&basename', basename).replace('&quot', '\\\\\\"')
def print_shiz(options, location=''):
for key, item in options.items():
args = item.pop('args', None)
folders = item.pop('folders', None)
keys = item.pop('keys', None)
if not location:
print(f'[-HKEY_CLASSES_ROOT\\*\\shell{location}\\{key}]')
print(f'[HKEY_CLASSES_ROOT\\*\\shell{location}\\{key}]')
if keys:
for entry_name, entry_value in keys.items():
if entry_value.startswith(('dword:')):
print(f'"{entry_name}"={entry_value}')
else:
print(f'"{entry_name}"="{entry_value}"')
if folders:
print()
print_shiz(folders, f'{location}\\{key}')
if args:
print()
print(f'[HKEY_CLASSES_ROOT\\*\\shell{location}\\{key}\\command]')
command = construct_command(keys.get('MUIVerb', ''), args)
print(f'@="{command}"')
print()
print_shiz(structure)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment