Files
express-video-encoder/encode-for-express.bat
2026-08-09 11:07:22 +03:00

487 lines
15 KiB
Batchfile
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@echo off
chcp 65001 >nul
setlocal EnableExtensions EnableDelayedExpansion
rem ============================================================
rem Express Video Encoder
rem Подготовка видео для отправки через мессенджер Express
rem ============================================================
set "TARGET_BYTES=39500000"
set "TARGET_MB=39.5"
set "AUDIO_KBPS=128"
set "OVERHEAD_KBPS=20"
set "FIRST_PASS_PRESET=8"
set "SECOND_PASS_PRESET=3"
if "%~1"=="" (
echo.
echo Перетащите видеофайл на encode-for-express.bat.
echo.
pause
exit /b 1
)
if not exist "%~f1" (
echo.
echo ОШИБКА: исходный файл не найден.
echo.
pause
exit /b 1
)
rem ============================================================
rem Поиск FFmpeg
rem ============================================================
set "FFMPEG="
set "FFPROBE="
if exist "%~dp0ffmpeg\ffmpeg.exe" set "FFMPEG=%~dp0ffmpeg\ffmpeg.exe"
if exist "%~dp0ffmpeg\ffprobe.exe" set "FFPROBE=%~dp0ffmpeg\ffprobe.exe"
if not defined FFMPEG (
where ffmpeg.exe >nul 2>&1
if not errorlevel 1 set "FFMPEG=ffmpeg.exe"
)
if not defined FFPROBE (
where ffprobe.exe >nul 2>&1
if not errorlevel 1 set "FFPROBE=ffprobe.exe"
)
if not defined FFMPEG (
echo.
echo ОШИБКА: ffmpeg.exe не найден.
echo Положите его в папку:
echo %~dp0ffmpeg
echo или добавьте FFmpeg в системный PATH.
echo.
pause
exit /b 1
)
if not defined FFPROBE (
echo.
echo ОШИБКА: ffprobe.exe не найден.
echo Положите его в папку:
echo %~dp0ffmpeg
echo или добавьте FFmpeg в системный PATH.
echo.
pause
exit /b 1
)
"%FFMPEG%" -hide_banner -encoders 2>nul | findstr /I /C:"libsvtav1" >nul
if errorlevel 1 (
echo.
echo ОШИБКА: эта сборка FFmpeg не содержит libsvtav1.
echo Нужна сборка FFmpeg с поддержкой SVT-AV1.
echo.
pause
exit /b 1
)
rem ============================================================
rem Чтение параметров исходного файла
rem Используем временные файлы вместо FOR /F вокруг команды ffprobe.
rem Это надежно работает с пробелами и русскими символами в путях.
rem ============================================================
set "PROBE_DIR=%TEMP%\express_video_encoder_%RANDOM%_%RANDOM%"
mkdir "%PROBE_DIR%" >nul 2>&1
set "SRC_VCODEC=Н/Д"
set "SRC_PROFILE=Н/Д"
set "SRC_WIDTH=Н/Д"
set "SRC_HEIGHT=Н/Д"
set "SRC_FPS_RAW=Н/Д"
set "SRC_FPS=Н/Д"
set "SRC_PIXFMT=Н/Д"
set "SRC_VBIT_BPS="
set "SRC_VBIT_KBPS=Н/Д"
set "DURATION="
"%FFPROBE%" -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 "%~f1" > "%PROBE_DIR%\vcodec.txt" 2>nul
"%FFPROBE%" -v error -select_streams v:0 -show_entries stream=profile -of default=noprint_wrappers=1:nokey=1 "%~f1" > "%PROBE_DIR%\profile.txt" 2>nul
"%FFPROBE%" -v error -select_streams v:0 -show_entries stream=width -of default=noprint_wrappers=1:nokey=1 "%~f1" > "%PROBE_DIR%\width.txt" 2>nul
"%FFPROBE%" -v error -select_streams v:0 -show_entries stream=height -of default=noprint_wrappers=1:nokey=1 "%~f1" > "%PROBE_DIR%\height.txt" 2>nul
"%FFPROBE%" -v error -select_streams v:0 -show_entries stream=avg_frame_rate -of default=noprint_wrappers=1:nokey=1 "%~f1" > "%PROBE_DIR%\fps.txt" 2>nul
"%FFPROBE%" -v error -select_streams v:0 -show_entries stream=pix_fmt -of default=noprint_wrappers=1:nokey=1 "%~f1" > "%PROBE_DIR%\pixfmt.txt" 2>nul
"%FFPROBE%" -v error -select_streams v:0 -show_entries stream=bit_rate -of default=noprint_wrappers=1:nokey=1 "%~f1" > "%PROBE_DIR%\vbit.txt" 2>nul
"%FFPROBE%" -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "%~f1" > "%PROBE_DIR%\duration.txt" 2>nul
set /p SRC_VCODEC=<"%PROBE_DIR%\vcodec.txt"
set /p SRC_PROFILE=<"%PROBE_DIR%\profile.txt"
set /p SRC_WIDTH=<"%PROBE_DIR%\width.txt"
set /p SRC_HEIGHT=<"%PROBE_DIR%\height.txt"
set /p SRC_FPS_RAW=<"%PROBE_DIR%\fps.txt"
set /p SRC_PIXFMT=<"%PROBE_DIR%\pixfmt.txt"
set /p SRC_VBIT_BPS=<"%PROBE_DIR%\vbit.txt"
set /p DURATION=<"%PROBE_DIR%\duration.txt"
if not defined DURATION (
rd /s /q "%PROBE_DIR%" >nul 2>&1
echo.
echo ОШИБКА: не удалось определить длительность видео.
echo.
pause
exit /b 1
)
for /f "delims=" %%A in ('powershell.exe -NoProfile -Command "$p='!SRC_FPS_RAW!'.Split('/'); if($p.Count -eq 2 -and [double]$p[1] -ne 0){[math]::Round([double]$p[0]/[double]$p[1],3)}else{'!SRC_FPS_RAW!'}"') do set "SRC_FPS=%%A"
if defined SRC_VBIT_BPS (
for /f "delims=" %%A in ('powershell.exe -NoProfile -Command "[math]::Round([double]'!SRC_VBIT_BPS!'/1000)"') do set "SRC_VBIT_KBPS=%%A"
)
rem ============================================================
rem Аудио
rem ============================================================
set "SRC_ACODEC=Нет"
set "SRC_ABIT_BPS="
set "SRC_ABIT_KBPS=Н/Д"
set "SRC_SAMPLE_RATE=Н/Д"
set "SRC_CHANNELS=Н/Д"
set "HAS_AUDIO=0"
"%FFPROBE%" -v error -select_streams a:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 "%~f1" > "%PROBE_DIR%\acodec.txt" 2>nul
for %%F in ("%PROBE_DIR%\acodec.txt") do if %%~zF GTR 0 set "HAS_AUDIO=1"
if "!HAS_AUDIO!"=="1" (
set /p SRC_ACODEC=<"%PROBE_DIR%\acodec.txt"
"%FFPROBE%" -v error -select_streams a:0 -show_entries stream=bit_rate -of default=noprint_wrappers=1:nokey=1 "%~f1" > "%PROBE_DIR%\abit.txt" 2>nul
"%FFPROBE%" -v error -select_streams a:0 -show_entries stream=sample_rate -of default=noprint_wrappers=1:nokey=1 "%~f1" > "%PROBE_DIR%\arate.txt" 2>nul
"%FFPROBE%" -v error -select_streams a:0 -show_entries stream=channels -of default=noprint_wrappers=1:nokey=1 "%~f1" > "%PROBE_DIR%\channels.txt" 2>nul
set /p SRC_ABIT_BPS=<"%PROBE_DIR%\abit.txt"
set /p SRC_SAMPLE_RATE=<"%PROBE_DIR%\arate.txt"
set /p SRC_CHANNELS=<"%PROBE_DIR%\channels.txt"
if defined SRC_ABIT_BPS (
for /f "delims=" %%A in ('powershell.exe -NoProfile -Command "[math]::Round([double]'!SRC_ABIT_BPS!'/1000)"') do set "SRC_ABIT_KBPS=%%A"
)
)
rd /s /q "%PROBE_DIR%" >nul 2>&1
for /f "delims=" %%A in ('powershell.exe -NoProfile -Command "$s=[double]::Parse('!DURATION!',[Globalization.CultureInfo]::InvariantCulture); [TimeSpan]::FromSeconds($s).ToString('hh\:mm\:ss\.fff')"') do set "DURATION_FORMATTED=%%A"
cls
echo.
echo ============================================================
echo ИСХОДНЫЙ ФАЙЛ
echo ============================================================
echo Файл : %~nx1
echo Длительность : !DURATION_FORMATTED!
echo.
echo ВИДЕО
echo Кодек : !SRC_VCODEC!
echo Профиль : !SRC_PROFILE!
echo Разрешение : !SRC_WIDTH!x!SRC_HEIGHT!
echo Частота кадров : !SRC_FPS! FPS
echo Формат пикселей : !SRC_PIXFMT!
echo Видеобитрейт : !SRC_VBIT_KBPS! кбит/с
echo.
echo АУДИО
echo Кодек : !SRC_ACODEC!
echo Аудиобитрейт : !SRC_ABIT_KBPS! кбит/с
echo Частота : !SRC_SAMPLE_RATE! Гц
echo Каналы : !SRC_CHANNELS!
echo ============================================================
echo.
pause
rem ============================================================
rem Выбор разрешения
rem ============================================================
cls
echo.
echo ============================================================
echo ВЫБЕРИТЕ ВЫХОДНОЕ РАЗРЕШЕНИЕ
echo ============================================================
echo [1] 1920x1080 - Full HD
echo [2] 1600x900
echo [3] 1536x864
echo [4] 1280x720 - HD
echo [5] Указать вручную
echo ============================================================
echo.
:resolution_menu
set "RES_CHOICE="
set /p "RES_CHOICE=Выберите 1, 2, 3, 4 или 5: "
if "!RES_CHOICE!"=="1" (
set "OUT_WIDTH=1920"
set "OUT_HEIGHT=1080"
goto resolution_selected
)
if "!RES_CHOICE!"=="2" (
set "OUT_WIDTH=1600"
set "OUT_HEIGHT=900"
goto resolution_selected
)
if "!RES_CHOICE!"=="3" (
set "OUT_WIDTH=1536"
set "OUT_HEIGHT=864"
goto resolution_selected
)
if "!RES_CHOICE!"=="4" (
set "OUT_WIDTH=1280"
set "OUT_HEIGHT=720"
goto resolution_selected
)
if "!RES_CHOICE!"=="5" goto custom_resolution
echo.
echo Неверный выбор. Введите число от 1 до 5.
echo.
goto resolution_menu
:custom_resolution
echo.
set /p "OUT_WIDTH=Введите ширину: "
set /p "OUT_HEIGHT=Введите высоту: "
if not defined OUT_WIDTH goto invalid_resolution
if not defined OUT_HEIGHT goto invalid_resolution
echo(!OUT_WIDTH!| findstr /R "^[0-9][0-9]*$" >nul || goto invalid_resolution
echo(!OUT_HEIGHT!| findstr /R "^[0-9][0-9]*$" >nul || goto invalid_resolution
goto resolution_selected
:invalid_resolution
echo.
echo ОШИБКА: ширина и высота должны быть целыми положительными числами.
echo.
pause
exit /b 1
:resolution_selected
rem ============================================================
rem Выбор FPS
rem ============================================================
cls
echo.
echo ============================================================
echo ВЫБЕРИТЕ ЧАСТОТУ КАДРОВ
echo ============================================================
echo Исходная частота: !SRC_FPS! FPS
echo.
echo [1] 24 FPS
echo [2] 30 FPS
echo [3] Оставить исходную
echo [4] Указать вручную
echo ============================================================
echo.
:fps_menu
set "FPS_CHOICE="
set /p "FPS_CHOICE=Выберите 1, 2, 3 или 4: "
if "!FPS_CHOICE!"=="1" (
set "FPS=24"
goto fps_selected
)
if "!FPS_CHOICE!"=="2" (
set "FPS=30"
goto fps_selected
)
if "!FPS_CHOICE!"=="3" (
set "FPS=!SRC_FPS!"
goto fps_selected
)
if "!FPS_CHOICE!"=="4" goto custom_fps
echo.
echo Неверный выбор. Введите число от 1 до 4.
echo.
goto fps_menu
:custom_fps
echo.
set /p "FPS=Введите FPS: "
if not defined FPS (
echo.
echo ОШИБКА: FPS не указан.
echo.
pause
exit /b 1
)
:fps_selected
if "!HAS_AUDIO!"=="0" set "AUDIO_KBPS=0"
rem ============================================================
rem Расчет видеобитрейта
rem ============================================================
for /f "delims=" %%B in ('powershell.exe -NoProfile -Command "$d=[double]::Parse('!DURATION!',[Globalization.CultureInfo]::InvariantCulture); [math]::Floor((!TARGET_BYTES!*8/1000/$d)-!AUDIO_KBPS!-!OVERHEAD_KBPS!)"') do set "VIDEO_KBPS=%%B"
if not defined VIDEO_KBPS (
echo.
echo ОШИБКА: не удалось рассчитать видеобитрейт.
echo.
pause
exit /b 1
)
if !VIDEO_KBPS! LSS 300 (
echo.
echo ОШИБКА: рассчитанный видеобитрейт слишком низкий.
echo Получено: !VIDEO_KBPS! кбит/с
echo Выберите меньшее разрешение или увеличьте целевой размер.
echo.
pause
exit /b 1
)
for /f "delims=" %%I in ('powershell.exe -NoProfile -Command "Get-Date -Format yyyy-MM-dd_HH-mm-ss"') do set "TODAY=%%I"
set "OUTPUT_DIR=%~dp0output"
if not exist "!OUTPUT_DIR!" mkdir "!OUTPUT_DIR!" >nul 2>&1
set "OUT=!OUTPUT_DIR!\!TODAY!_Express_!OUT_WIDTH!x!OUT_HEIGHT!_!FPS!fps.mp4"
set "PASSLOG=%TEMP%\express_svtpass_!RANDOM!_!RANDOM!"
set "VIDEO_FILTER=fps=!FPS!,scale=!OUT_WIDTH!:!OUT_HEIGHT!:force_original_aspect_ratio=decrease:flags=lanczos,pad=!OUT_WIDTH!:!OUT_HEIGHT!:(ow-iw)/2:(oh-ih)/2"
cls
echo.
echo ============================================================
echo ПОДГОТОВКА ВИДЕО ДЛЯ EXPRESS
echo ============================================================
echo Разрешение : !OUT_WIDTH!x!OUT_HEIGHT!
echo Частота кадров : !FPS! FPS
echo Видеокодек : AV1 (SVT-AV1)
echo Видеобитрейт : !VIDEO_KBPS! кбит/с
if "!HAS_AUDIO!"=="1" (
echo Аудио : AAC, !AUDIO_KBPS! кбит/с, стерео
) else (
echo Аудио : отсутствует
)
echo Формат пикселей : yuv420p10le
echo Целевой размер : около !TARGET_MB! МБ
echo Первый проход : preset !FIRST_PASS_PRESET!
echo Второй проход : preset !SECOND_PASS_PRESET!
echo.
echo Результат будет сохранен в:
echo !OUTPUT_DIR!
echo ============================================================
echo.
:confirm_menu
set "CONFIRM="
set /p "CONFIRM=Начать кодирование? [Y/N]: "
if /I "!CONFIRM!"=="Y" goto start_encoding
if /I "!CONFIRM!"=="N" (
echo.
echo Кодирование отменено.
echo.
pause
exit /b 0
)
echo.
echo Введите Y или N.
echo.
goto confirm_menu
:start_encoding
echo.
echo [1/2] Анализ видео...
echo.
"%FFMPEG%" -y -i "%~f1" ^
-map 0:v:0 ^
-vf "!VIDEO_FILTER!" ^
-c:v libsvtav1 ^
-b:v !VIDEO_KBPS!k ^
-preset !FIRST_PASS_PRESET! ^
-pass 1 ^
-passlogfile "!PASSLOG!" ^
-pix_fmt yuv420p10le ^
-an ^
-f null NUL
if errorlevel 1 goto error
echo.
echo [2/2] Кодирование видео...
echo.
if "!HAS_AUDIO!"=="1" (
"%FFMPEG%" -y -i "%~f1" ^
-map 0:v:0 ^
-map 0:a:0? ^
-vf "!VIDEO_FILTER!" ^
-c:v libsvtav1 ^
-b:v !VIDEO_KBPS!k ^
-preset !SECOND_PASS_PRESET! ^
-pass 2 ^
-passlogfile "!PASSLOG!" ^
-pix_fmt yuv420p10le ^
-tag:v av01 ^
-c:a aac ^
-b:a !AUDIO_KBPS!k ^
-ac 2 ^
-movflags +faststart ^
-f mp4 ^
"!OUT!"
) else (
"%FFMPEG%" -y -i "%~f1" ^
-map 0:v:0 ^
-vf "!VIDEO_FILTER!" ^
-c:v libsvtav1 ^
-b:v !VIDEO_KBPS!k ^
-preset !SECOND_PASS_PRESET! ^
-pass 2 ^
-passlogfile "!PASSLOG!" ^
-pix_fmt yuv420p10le ^
-tag:v av01 ^
-an ^
-movflags +faststart ^
-f mp4 ^
"!OUT!"
)
if errorlevel 1 goto error
del /q "!PASSLOG!*" >nul 2>&1
for %%F in ("!OUT!") do set "FINAL_BYTES=%%~zF"
for /f "delims=" %%M in ('powershell.exe -NoProfile -Command "[math]::Round(!FINAL_BYTES!/1000000,2)"') do set "FINAL_MB=%%M"
echo.
echo ============================================================
echo ГОТОВО
echo ============================================================
echo Файл : !OUT!
echo Размер : !FINAL_MB! МБ
echo ============================================================
echo.
pause
exit /b 0
:error
del /q "!PASSLOG!*" >nul 2>&1
if defined OUT if exist "!OUT!" del /q "!OUT!" >nul 2>&1
echo.
echo ============================================================
echo ОШИБКА КОДИРОВАНИЯ
echo ============================================================
echo FFmpeg завершил работу с ошибкой.
echo.
pause
exit /b 1