Skip to content

Instantly share code, notes, and snippets.

@donal56
Last active October 18, 2025 01:08
Show Gist options
  • Select an option

  • Save donal56/27435f73c2e038f61a839b44f7f041ea to your computer and use it in GitHub Desktop.

Select an option

Save donal56/27435f73c2e038f61a839b44f7f041ea to your computer and use it in GitHub Desktop.
Wizard to compress videos with ffmpeg and ffprobe
:: Ayudame a crear un script de bash (.bat) tipo wizard que me ayude a llamar a disminuir el tamaño de videos usando ffmpeg y ffprobe.
:: El script estar seccionado a como se describe y todos los comentarios y salidas a consola serán en ingles.
:: Señalo aqui el proceso del programa:
::
:: 1.- El programa se llamara cleanVideo y tomara como argumento un video. Opcionalmente podra tomar el argumento -s o --silent, que se salta todas las opciones del wizard.
::
:: 2.- Se realizaran validaciones básicas.
:: 2.1.- Verificar que la cadena de argumentos sea válida.
:: 2.2.- Verificar que el video sea un archivo existente.
:: 2.3.- Verificar que el video tenga una extension de video válida.
:: 2.4.- Verificar que se tenga ffmpeg u ffprobe instalado.
:: 3.- Recupera información metadata del video e imprimela a consola. Si alguno de los datos no se puede recuerar o te retorna un valor vació entonces fallara el programa y mostrara un mensaje describiendo porque. Datos:
:: - Nombre del archivo incluyendo extensión
:: - Duración del video
:: - Codec de video
:: - Resolución
:: - Aspecto ratio (Si no es una relacion de aspecto común puedes aproximar)
:: - Bitrate de video
:: - Bitrate de audio
:: - Bitrate total
:: 4.- Si el video tiene una proporción 16:9 o 9:16, entonces preguntara:
:: "Would you like to downscale the video?
:: Type [1] for 2560x1440
:: Type [2] for 1920x1080
:: Type [3] for 1280x720
:: Type anthing else to skip"
:: Este ejemplo fue para orientacion horizontal, si se es vertical muesta las resoluciones al reves, por ejemplo 1440x2560.
:: Si el video tiene una proporcion 4:3 o 3:4 aplica la misma lógica usando las siguientes resoluciones estandar: 800x600, 1024x768, 2048x1536.
:: Si el video no tiene ninguna de estas proporciones entonces pregunta el porcentaje de resolución que quieres que se use. Si el cálculo de la nueva resolución no te da un valor entero exacto eres libre de redondear. El usuario tambien saltar este paso si ingresa un valor no válido.
:: 5.- Pregunta si se desea modificar el bitrate de video o no. Si se ingresa un numero entonces usar ese birate como kbps, cualquier otra tecla salta ese paso.
:: 6.- Añade un paso donde el usuario pueda cortar el video. Primero pregunta por el timestamp de inicio en mm:ss, si el usuario no ingresa un tiempo entonces este sera el inicio del video (00:00). de la misma manera pregunta por el final, si el usuario no ingreso un tiempo entonces asume el final del video. Si no se ingresa un valor para ambas preguntas entonces omite el cortar el video
:: 7.- Pregunta si se desea remover el audio del video (si el video tiene canal de audio)
:: 8.- Finalmente ejecuta el comando. Para cualquier caso sin importar lo que se haya respondido en el wizard, agrega los siguiente valores en el comando:
:: Usa el codec de video libx265
:: La salida sera en contenedor mp4
:: El nombre de salida sera el mismo nombre de entrada más el postfijo " new"
:: Si ya existe un archivo con el mismo nombre entonces el postfijo será "new2" y así consecutivamente
:: El crf sera de 27
:: TODO
:: Fix "Enter percentage scale"
:: Modify cleanVideos to fail if an argument is passed
:: Add file size to metadata screen
@echo off
setlocal enabledelayedexpansion
:: Wizard to compress videos with ffmpeg and ffprobe
:: By ChatGPT - cleanVideo.bat
:: =============================
:: 1. Parse arguments
:: =============================
set "VIDEO=%~1"
set "SILENT=0"
if "%~2"=="-s" set SILENT=1
if "%~2"=="--silent" set SILENT=1
:: =============================
:: 2. Basic validations
:: =============================
if "%VIDEO%"=="" (
echo Error: No video file provided.
exit /b 1
)
if not exist "%VIDEO%" (
echo Error: File does not exist: %VIDEO%
exit /b 1
)
set "EXT=%~x1"
set "VALID_EXT=.mp4 .mov .avi .mkv .webm .flv .ts"
set "FOUND=0"
for %%e in (%VALID_EXT%) do (
if /I "%%e"=="%EXT%" set FOUND=1
)
if %FOUND%==0 (
echo Error: Invalid video file extension: %EXT%
exit /b 1
)
where ffmpeg >nul 2>nul || (echo Error: ffmpeg not found & exit /b 1)
where ffprobe >nul 2>nul || (echo Error: ffprobe not found & exit /b 1)
:: =============================
:: 3. Extract and display metadata
:: =============================
for /f "tokens=1,* delims==" %%a in ('"ffprobe -v error -select_streams v:0 -show_entries stream=width,height,codec_name,bit_rate,display_aspect_ratio -of default=noprint_wrappers=1 "%VIDEO%""') do set "%%a=%%b"
for /f "tokens=1,* delims==" %%a in ('"ffprobe -v error -select_streams a:0 -show_entries stream=bit_rate -of default=noprint_wrappers=1 "%VIDEO%""') do set "AUDIO_%%a=%%b"
for /f "tokens=1,* delims==" %%a in ('"ffprobe -v error -show_entries format=duration,bit_rate -of default=noprint_wrappers=1 "%VIDEO%""') do set "%%a=%%b"
set "filename=%~nx1"
if "!filename!"=="" echo Error: Could not retrieve filename & exit /b 1
if "!duration!"=="" echo Error: Could not retrieve duration & exit /b 1
if "!codec_name!"=="" echo Error: Could not retrieve codec & exit /b 1
if "!width!"=="" echo Error: Could not retrieve resolution & exit /b 1
if "!bit_rate!"=="" echo Error: Could not retrieve video bitrate & exit /b 1
if "!duration!"=="" (
if !duration! GEQ 60 (
set /a !minutes!=!duration! / 60
set /a !seconds!=!duration! % 60
set !duration!= !minutes!m !seconds!s
)
else {
set !duration!= !duration!s
}
)
set /a TOTAL_bit_rate=!bit_rate!
if "!AUDIO_bit_rate!"=="" (
set "AUDIO_bit_rate=N/A"
set "HAS_AUDIO=0"
) else (
set "HAS_AUDIO=1"
set /a AUDIO_bit_rate=!AUDIO_bit_rate! / 1024
set /a bit_rate= !TOTAL_bit_rate! - !AUDIO_bit_rate!
)
set /a bit_rate= !bit_rate! / 1024
set /a TOTAL_bit_rate= !TOTAL_bit_rate! / 1024
set /a ratio=!width!*100/!height!
if !ratio! GEQ 175 if !ratio! LEQ 178 set "ASPECT=16:9"
if !ratio! GEQ 132 if !ratio! LEQ 135 set "ASPECT=4:3"
if !ratio! GEQ 55 if !ratio! LEQ 58 set "ASPECT=9:16"
if !ratio! GEQ 74 if !ratio! LEQ 77 set "ASPECT=3:4"
if "!ratio!"=="100" set "ASPECT=1:1"
if not defined ASPECT set "ASPECT=custom"
echo.
echo ===== VIDEO METADATA =====
echo File: !filename!
echo Duration: !duration!
echo Codec: !codec_name!
echo Resolution: !width!x!height!
echo Aspect Ratio: !ASPECT!
echo Video Bitrate: !bit_rate! kbps
echo Audio Bitrate: !AUDIO_bit_rate! kbps
echo Total Bitrate: !TOTAL_bit_rate! kbps
echo ============================
:: =============================
:: 4. Resolution wizard
:: =============================
set "DOWNSCALE="
if "!ASPECT!"=="16:9" set "ORIENT=H"
if "!ASPECT!"=="9:16" set "ORIENT=V"
if "!ASPECT!"=="4:3" set "ORIENT=H43"
if "!ASPECT!"=="3:4" set "ORIENT=V43"
if "!ASPECT!"=="1:1" set "ORIENT=SQUARE"
if defined ORIENT (
echo Would you like to downscale the video?
if "!ORIENT!"=="H" (
echo [1] 2560x1440
echo [2] 1920x1080
echo [3] 1280x720
echo [4] 800x450
) else if "!ORIENT!"=="V" (
echo [1] 1440x2560
echo [2] 1080x1920
echo [3] 720x1280
echo [3] 450x800
) else if "!ORIENT!"=="H43" (
echo [1] 2048x1536
echo [2] 1024x768
echo [3] 800x600
) else if "!ORIENT!"=="V43" (
echo [1] 1536x2048
echo [2] 768x1024
echo [3] 600x800
) else if "!ORIENT!"=="SQUARE" (
echo [1] 1200x1200
echo [2] 1000x1000
echo [3] 800x800
echo [4] 600x600
)
set /p OPTION=Choose option [1-3] or any other key to skip:
if "!ORIENT!"=="H" (
if "!OPTION!"=="1" (
set "DOWNSCALE=2560:1440"
) else if "!OPTION!"=="2" (
set "DOWNSCALE=1920:1080"
) else if "!OPTION!"=="3" (
set "DOWNSCALE=1280:720"
) else if "!OPTION!"=="4" (
set "DOWNSCALE=800:450"
)
) else if "!ORIENT!"=="V" (
if "!OPTION!"=="1" (
set "DOWNSCALE=1440:2560"
) else if "!OPTION!"=="2" (
set "DOWNSCALE=1080:1920"
) else if "!OPTION!"=="3" (
set "DOWNSCALE=720:1280"
) else if "!OPTION!"=="4" (
set "DOWNSCALE=450:800"
)
) else if "!ORIENT!"=="H43" (
if "!OPTION!"=="1" (
set "DOWNSCALE=2048:1536"
) else if "!OPTION!"=="2" (
set "DOWNSCALE=1024:768"
) else if "!OPTION!"=="3" (
set "DOWNSCALE=800:600"
)
) else if "!ORIENT!"=="V43" (
if "!OPTION!"=="1" (
set "DOWNSCALE=1536:2048"
) else if "!OPTION!"=="2" (
set "DOWNSCALE=768:1024"
) else if "!OPTION!"=="3" (
set "DOWNSCALE=600:800"
)
) else if "!ORIENT!"=="SQUARE" (
if "!OPTION!"=="1" (
set "DOWNSCALE=1200:1200"
) else if "!OPTION!"=="2" (
set "DOWNSCALE=1000:1000"
) else if "!OPTION!"=="3" (
set "DOWNSCALE=800:800"
) else if "!OPTION!"=="4" (
set "DOWNSCALE=600:600"
)
)
) else (
set /p SCALEPCT="Enter percentage scale (e.g. 50 for 50%%) or anything else to skip:"
set /a SCALED_W=!width! * !SCALEPCT! / 100
set /a SCALED_H=!height! * !SCALEPCT! / 100
set "DOWNSCALE=!SCALED_W!:!SCALED_H!"
)
:: =============================
:: 5. Bitrate change
:: =============================
set /p NEWBR=Enter new video bitrate in kbps or press enter to skip:
:: =============================
:: 6. Trimming
:: =============================
set /p START=Enter start timestamp (mm:ss) or press enter to start from 00:00:
set /p END=Enter end timestamp (mm:ss) or press enter to go to end:
:: =============================
:: 7. Remove audio
:: =============================
if !HAS_AUDIO! EQU 1 set /p REMOVE_AUDIO=Remove audio? (y/n):
:: =============================
:: 8. Encode
:: =============================
:encode
set "OUTFILE=%~dpn1 new.mp4"
set /a COUNT=2
:checkexist
if exist "%OUTFILE%" (
set "OUTFILE=%~dpn1 new!COUNT!.mp4"
set /a COUNT+=1
goto checkexist
)
set "CMD=ffmpeg -v quiet -stats"
set "CMD=!CMD! -i "%VIDEO%""
:: ss before input may be faster but can result in length mismatches
if defined START set "CMD=!CMD! -ss !START!"
if defined END set "CMD=!CMD! -to !END!"
if defined DOWNSCALE if not "!OPTION!"=="" set "CMD=!CMD! -vf "scale=!DOWNSCALE!""
if defined NEWBR set "CMD=!CMD! -b:v !NEWBR!k"
if /I "!REMOVE_AUDIO!"=="y" set "CMD=!CMD! -an"
if not defined REMOVE_AUDIO set "CMD=!CMD! -map 0 -c:s copy"
set "CMD=!CMD! -c:v libx265 "
if not defined NEWBR set "CMD=!CMD! -crf 27 "
set "CMD=!CMD! -y "%OUTFILE%""
echo Running:
echo !CMD!
!CMD!
echo.
echo Done. Output saved to: !OUTFILE!
endlocal
exit /b 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment