Skip to content

Instantly share code, notes, and snippets.

@ephbaum
Last active September 6, 2025 02:04
Show Gist options
  • Select an option

  • Save ephbaum/9e3300747fb32e50f3a42924aa48a78b to your computer and use it in GitHub Desktop.

Select an option

Save ephbaum/9e3300747fb32e50f3a42924aa48a78b to your computer and use it in GitHub Desktop.
MKV → MP4 Drag‑and‑Drop FFMPEG Remuxer with Auto File Sorting & Sleep Prevention for OBS Matroska Files
:: ==============================================================================
:: MKV → MP4 Drag‑and‑Drop Remuxer with Auto Date Detection, Sorting & Sleep Prevention
::
:: WHAT IT DOES:
:: - Accepts one or more MKV files via drag‑and‑drop from ANY location (local, network, USB).
:: - Always uses the ffmpeg.exe located in the same folder as this script (no PATH required).
:: - Temporarily disables Windows sleep (AC/DC) while running, then restores original settings.
:: - Determines target date folder by:
:: 1. Using the first 10 characters of the filename if in YYYY‑MM‑DD format, OR
:: 2. Falling back to the file’s last modified date if no valid date in filename.
:: - Creates folders (relative to this script’s location): YYYY‑MM‑DD\mp4 and YYYY‑MM‑DD\mkv.
:: - Remuxes MKV → MP4 without re‑encoding (fast, lossless).
:: - Skips conversion if MP4 already exists; will not overwrite existing MKVs.
:: - Moves original MKV into the matching \mkv folder (unless already there).
:: - Logs successes, failures, and skips into /logs with today’s date.
::
:: REQUIREMENTS:
:: - Windows 10/11
:: - ffmpeg.exe in the same folder as this script (recommended) or accessible via PATH.
::
:: DOWNLOAD FFMPEG:
:: https://ffmpeg.org/download.html
:: Windows builds (Gyan.dev): https://www.gyan.dev/ffmpeg/builds/
::
:: USAGE:
:: 1. Place ffmpeg.exe in the same folder as this script (or ensure it’s in your PATH).
:: 2. Drag and drop MKV files onto this .bat file from anywhere.
:: 3. The script will auto‑detect dates, sort into folders, remux, move, and log automatically.
::
:: NO‑FAULT / AS‑IS LICENSE:
:: This script is provided “AS IS”, without warranty of any kind, express or implied.
:: The author(s) assume no responsibility for errors or omissions, or for any loss,
:: damage, or data corruption resulting from the use or misuse of this script.
:: By using this script, you agree to do so entirely at your own risk.
::
:: ==============================================================================
@echo off
setlocal enabledelayedexpansion
REM ===== CONFIG =====
set "scriptdir=%~dp0"
set "ffmpegexe=%scriptdir%ffmpeg.exe"
REM ===== Save current sleep settings =====
for /f "tokens=6" %%a in ('powercfg /query SCHEME_CURRENT SUB_SLEEP STANDBYIDLE ^| findstr /i "AC Power"') do set "OLD_AC_HEX=%%a"
for /f "tokens=6" %%a in ('powercfg /query SCHEME_CURRENT SUB_SLEEP STANDBYIDLE ^| findstr /i "DC Power"') do set "OLD_DC_HEX=%%a"
if defined OLD_AC_HEX set /a OLD_AC_MIN=%OLD_AC_HEX%
if defined OLD_DC_HEX set /a OLD_DC_MIN=%OLD_DC_HEX%
REM ===== Disable sleep =====
powercfg -change -standby-timeout-ac 0 >nul 2>&1
powercfg -change -standby-timeout-dc 0 >nul 2>&1
REM ===== Prepare logs =====
set "logdir=%scriptdir%logs"
if not exist "%logdir%" mkdir "%logdir%"
for /f %%i in ('powershell -NoProfile -Command Get-Date -Format yyyy-MM-dd') do set "today=%%i"
set "successlog=%logdir%\success_%today%.txt"
set "faillog=%logdir%\fail_%today%.txt"
set "skiplog=%logdir%\skipped_%today%.txt"
REM ===== Count total files =====
set /a total=0
for %%C in (%*) do set /a total+=1
set /a count=0
REM ===== Process each dropped file =====
:loop
if "%~1"=="" goto done
set /a count+=1
call :process "%~1"
shift
goto loop
:process
set "fullpath=%~1"
echo [!count!/%total%] Processing: "%~nx1"
REM Try to get date from filename (first 10 chars)
set "fname=%~n1"
set "filedate=!fname:~0,10!"
REM Validate format YYYY-MM-DD using findstr regex
echo "!filedate!" | findstr /r "^[0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9]$" >nul
if errorlevel 1 (
REM No valid date in filename → use last modified date
for /f %%d in ('powershell -NoProfile -Command "(Get-Item '%fullpath%').LastWriteTime.ToString('yyyy-MM-dd')"') do set "filedate=%%d"
)
REM Target folders (relative to script location)
set "mp4dir=%scriptdir%!filedate!\mp4"
set "mkvdir=%scriptdir%!filedate!\mkv"
if not exist "!mp4dir!" mkdir "!mp4dir!"
if not exist "!mkvdir!" mkdir "!mkvdir!"
set "outmp4=!mp4dir!\%~n1.mp4"
REM Skip if MP4 exists
if exist "!outmp4!" (
echo SKIP: MP4 exists -> "!outmp4!"
echo SKIP_MP4_EXISTS: %~nx1 >> "%skiplog%"
exit /b
)
REM Remux MKV → MP4 using local ffmpeg
"%ffmpegexe%" -i "%fullpath%" -c copy "!outmp4!"
if errorlevel 1 (
echo FAIL: %~nx1 >> "%faillog%"
echo Conversion failed.
exit /b
)
REM Move MKV if not already in mkv folder
if /i not "%~dp1"=="!mkvdir!\" (
if not exist "!mkvdir!\%~nx1" (
move "%fullpath%" "!mkvdir!\">nul
) else (
echo SKIP: MKV exists -> "!mkvdir!\%~nx1"
echo SKIP_MKV_EXISTS: %~nx1 >> "%skiplog%"
)
)
echo SUCCESS: %~nx1 >> "%successlog%"
exit /b
:done
REM ===== Restore sleep settings =====
if defined OLD_AC_MIN powercfg -change -standby-timeout-ac %OLD_AC_MIN% >nul 2>&1
if defined OLD_DC_MIN powercfg -change -standby-timeout-dc %OLD_DC_MIN% >nul 2>&1
echo.
echo All done. Logs in "%logdir%".
pause
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment