Полностью офлайн: те же операции в ffmpeg
Браузерная версия уже работает локально, а ffmpeg в терминале снимает даже зависимость от вкладки. Здесь собраны готовые команды для macOS, Windows и Linux, повторяющие все режимы инструмента.
Если файлов много, они очень большие или нужен скрипт, удобнее считать локально через ffmpeg. Ниже те же режимы, что и на сайте: дублирование, смешивание и интерполяция по движению. Замените имена файлов на свои.
Во всех командах F - кратность замедления (8 или 16), FPS - частота кадров результата (60 для x8, 30 для x16), а INPUT и OUTPUT - имена исходного и итогового файлов. В командах для Windows те же два файла называются IN и OUT: в PowerShell $input - зарезервированная системная переменная, и использовать её под своё имя нельзя.
Нажмите «Скопировать», чтобы забрать команду целиком.
Установка ffmpeg
Один раз ставим ffmpeg, дальше всё работает офлайн. Проверить установку можно командой ffmpeg -version.
macOS
brew install ffmpeg
ffmpeg -version
brew tap homebrew-ffmpeg/ffmpeg && brew install homebrew-ffmpeg/ffmpeg/ffmpeg --with-zimg
Сборка из Homebrew включает libx264, libx265 и videotoolbox, поэтому все режимы замедления работают сразу. Но zimg в неё НЕ входит: фильтра zscale там нет, и цепочка тонмаппинга HDR не запустится. Проверить: ffmpeg -hide_banner -filters | grep zscale. Если строки нет, а HDR обрабатывать надо, поставьте сборку из тапа третьей командой. Если Homebrew ещё нет, поставьте его по инструкции с brew.sh.
Windows
winget install Gyan.FFmpeg
ffmpeg -version
chcp 65001
После установки закройте терминал и откройте новый, иначе PATH не подхватится. Сборка Gyan.FFmpeg собрана с libx264, libx265, zimg и поддержкой nvenc, qsv и amf. Третья команда переключает cmd.exe на UTF-8: без неё русские и эмодзи в именах файлов превращаются в вопросительные знаки.
Linux
sudo apt update && sudo apt install ffmpeg
ffmpeg -version
curl -L -O https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz && tar xf ffmpeg-release-amd64-static.tar.xz && sudo install -m 755 ffmpeg-*-amd64-static/ffmpeg ffmpeg-*-amd64-static/ffprobe /usr/local/bin/
В Debian и Ubuntu версия из репозитория часто отстаёт на год-полтора. Если ffmpeg -version показывает 4.x, ставьте статическую сборку johnvansickle.com третьей командой: она распаковывается в один каталог, ни с чем не конфликтует и включает libx264, libx265 и zimg. В Fedora dnf install ffmpeg, в Arch pacman -S ffmpeg.
Посмотреть параметры файла
Сначала смотрим кодек, разрешение, частоту кадров и поворот: от них зависят все следующие команды.
macOS
INPUT="input.mp4"; OUTPUT="output.mp4"; F=8; FPS=60
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name,width,height,r_frame_rate,avg_frame_rate,nb_frames,color_transfer:stream_tags=rotate -of json "$INPUT"
color_transfer со значением arib-std-b67 это HLG, smpte2084 это PQ. И то и другое - HDR, см. шаг про тонмаппинг.
Windows
$IN="input.mp4"; $OUT="output.mp4"; $F=8; $FPS=60
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name,width,height,r_frame_rate,avg_frame_rate,nb_frames,color_transfer:stream_tags=rotate -of json "$IN"
color_transfer со значением arib-std-b67 это HLG, smpte2084 это PQ. И то и другое - HDR, см. шаг про тонмаппинг.
Linux
INPUT="input.mp4"; OUTPUT="output.mp4"; F=8; FPS=60
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name,width,height,r_frame_rate,avg_frame_rate,nb_frames,color_transfer:stream_tags=rotate -of json "$INPUT"
color_transfer со значением arib-std-b67 это HLG, smpte2084 это PQ. И то и другое - HDR, см. шаг про тонмаппинг.
Замедление дублированием кадров
Самый быстрый и надёжный способ: кадры повторяются, артефактов нет, движение выглядит ступенчатым.
macOS
INPUT="input.mp4"; OUTPUT="output.mp4"; F=8; FPS=60
ffmpeg -i "$INPUT" -vf "setpts=${F}*PTS,fps=${FPS}" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -an "$OUTPUT"
setpts обязан стоять ПЕРЕД fps. Поставите наоборот - fps сработает на исходных метках, setpts растянет уже прореженный поток, и замедления не будет вовсе.
Windows
$IN="input.mp4"; $OUT="output.mp4"; $F=8; $FPS=60
ffmpeg -i "$IN" -vf "setpts=${F}*PTS,fps=${FPS}" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -an "$OUT"
setpts обязан стоять ПЕРЕД fps. Поставите наоборот - fps сработает на исходных метках, setpts растянет уже прореженный поток, и замедления не будет вовсе.
Linux
INPUT="input.mp4"; OUTPUT="output.mp4"; F=8; FPS=60
ffmpeg -i "$INPUT" -vf "setpts=${F}*PTS,fps=${FPS}" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -an "$OUTPUT"
setpts обязан стоять ПЕРЕД fps. Поставите наоборот - fps сработает на исходных метках, setpts растянет уже прореженный поток, и замедления не будет вовсе.
Замедление со смешиванием
Соседние кадры смешиваются, рывки превращаются в мягкий смаз. Считается почти так же быстро, как дублирование.
macOS
INPUT="input.mp4"; OUTPUT="output.mp4"; F=8; FPS=60
ffmpeg -i "$INPUT" -vf "setpts=${F}*PTS,minterpolate=fps=${FPS}:mi_mode=blend" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -an "$OUTPUT"
Порядок тот же: setpts, потом minterpolate. Параметр fps внутри minterpolate задаёт частоту результата, отдельный фильтр fps здесь не нужен.
Windows
$IN="input.mp4"; $OUT="output.mp4"; $F=8; $FPS=60
ffmpeg -i "$IN" -vf "setpts=${F}*PTS,minterpolate=fps=${FPS}:mi_mode=blend" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -an "$OUT"
Порядок тот же: setpts, потом minterpolate. Параметр fps внутри minterpolate задаёт частоту результата, отдельный фильтр fps здесь не нужен.
Linux
INPUT="input.mp4"; OUTPUT="output.mp4"; F=8; FPS=60
ffmpeg -i "$INPUT" -vf "setpts=${F}*PTS,minterpolate=fps=${FPS}:mi_mode=blend" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -an "$OUTPUT"
Порядок тот же: setpts, потом minterpolate. Параметр fps внутри minterpolate задаёт частоту результата, отдельный фильтр fps здесь не нужен.
Интерполяция по движению
Фильтр minterpolate достраивает промежуточные кадры по векторам движения. Результат лучший, но расчёт долгий, а на воде, листве и склейках возможны искажения.
macOS
INPUT="input.mp4"; OUTPUT="output.mp4"; F=8; FPS=60
ffmpeg -i "$INPUT" -vf "setpts=${F}*PTS,minterpolate=fps=${FPS}:mi_mode=mci:mc_mode=aobmc:me_mode=bidir:vsbmc=1" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -an "$OUTPUT"
Прогоните сначала десять секунд через -ss 0 -t 10, посмотрите на результат и только потом запускайте весь файл. Переделывать двухчасовой просчёт обидно.
Windows
$IN="input.mp4"; $OUT="output.mp4"; $F=8; $FPS=60
ffmpeg -i "$IN" -vf "setpts=${F}*PTS,minterpolate=fps=${FPS}:mi_mode=mci:mc_mode=aobmc:me_mode=bidir:vsbmc=1" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -an "$OUT"
Прогоните сначала десять секунд через -ss 0 -t 10, посмотрите на результат и только потом запускайте весь файл. Переделывать двухчасовой просчёт обидно.
Linux
INPUT="input.mp4"; OUTPUT="output.mp4"; F=8; FPS=60
ffmpeg -i "$INPUT" -vf "setpts=${F}*PTS,minterpolate=fps=${FPS}:mi_mode=mci:mc_mode=aobmc:me_mode=bidir:vsbmc=1" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -an "$OUTPUT"
Прогоните сначала десять секунд через -ss 0 -t 10, посмотрите на результат и только потом запускайте весь файл. Переделывать двухчасовой просчёт обидно.
Переменная частота кадров
Записи с экрана и видео с телефонов часто идут с плавающим FPS. Приводим их к постоянной частоте, иначе замедление разъедется со звуком.
macOS
INPUT="input.mp4"; OUTPUT="output.mp4"; F=8; FPS=60
ffmpeg -i "$INPUT" -vf "fps=30,setpts=${F}*PTS,minterpolate=fps=${FPS}:mi_mode=mci" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -an "$OUTPUT"
Первое число 30 в fps=30 - это исходная частота из ffprobe, а не целевая. Целевая стоит внутри minterpolate. Их легко перепутать местами, и тогда файл просто не замедлится.
Windows
$IN="input.mp4"; $OUT="output.mp4"; $F=8; $FPS=60
ffmpeg -i "$IN" -vf "fps=30,setpts=${F}*PTS,minterpolate=fps=${FPS}:mi_mode=mci" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -an "$OUT"
Первое число 30 в fps=30 - это исходная частота из ffprobe, а не целевая. Целевая стоит внутри minterpolate. Их легко перепутать местами, и тогда файл просто не замедлится.
Linux
INPUT="input.mp4"; OUTPUT="output.mp4"; F=8; FPS=60
ffmpeg -i "$INPUT" -vf "fps=30,setpts=${F}*PTS,minterpolate=fps=${FPS}:mi_mode=mci" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -an "$OUTPUT"
Первое число 30 в fps=30 - это исходная частота из ffprobe, а не целевая. Целевая стоит внутри minterpolate. Их легко перепутать местами, и тогда файл просто не замедлится.
HDR в SDR
Материал с iPhone в HLG или PQ в обычных плеерах выглядит блёкло. Преобразуем цвет в BT.709. Проверьте, что в вашей сборке есть фильтр zscale: в стандартной сборке Homebrew его нет.
macOS
INPUT="input.mp4"; OUTPUT="output.mp4"; F=8; FPS=60
ffmpeg -i "$INPUT" -vf "zscale=t=linear:npl=100,tonemap=hable:desat=0,zscale=p=bt709:t=bt709:m=bt709:r=tv,format=yuv420p,setpts=${F}*PTS,fps=${FPS}" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -an "$OUTPUT"
ffmpeg -hide_banner -filters | grep zscale
zscale есть только в сборках с --enable-libzimg. Проверьте так: ffmpeg -hide_banner -filters | grep zscale. Чаще всего его нет именно на macOS: стандартная сборка Homebrew идёт без zimg, а вот сборки Gyan для Windows, пакеты Debian и Ubuntu и статические сборки johnvansickle его содержат. Если фильтра нет, вариантов два. На машине с OpenCL можно взять tonemap_opencl (сложнее в настройке, нужен -init_hw_device opencl). Либо ограничиться format=yuv420p вместо всей цепочки: файл откроется везде, но цвета останутся неверными, светы уйдут в белое, а насыщенность просядет. Не молчите об этом в результате.
Windows
$IN="input.mp4"; $OUT="output.mp4"; $F=8; $FPS=60
ffmpeg -i "$IN" -vf "zscale=t=linear:npl=100,tonemap=hable:desat=0,zscale=p=bt709:t=bt709:m=bt709:r=tv,format=yuv420p,setpts=${F}*PTS,fps=${FPS}" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -an "$OUT"
ffmpeg -hide_banner -filters | Select-String zscale
zscale есть только в сборках с --enable-libzimg. Проверьте так: ffmpeg -hide_banner -filters | grep zscale. Чаще всего его нет именно на macOS: стандартная сборка Homebrew идёт без zimg, а вот сборки Gyan для Windows, пакеты Debian и Ubuntu и статические сборки johnvansickle его содержат. Если фильтра нет, вариантов два. На машине с OpenCL можно взять tonemap_opencl (сложнее в настройке, нужен -init_hw_device opencl). Либо ограничиться format=yuv420p вместо всей цепочки: файл откроется везде, но цвета останутся неверными, светы уйдут в белое, а насыщенность просядет. Не молчите об этом в результате.
Linux
INPUT="input.mp4"; OUTPUT="output.mp4"; F=8; FPS=60
ffmpeg -i "$INPUT" -vf "zscale=t=linear:npl=100,tonemap=hable:desat=0,zscale=p=bt709:t=bt709:m=bt709:r=tv,format=yuv420p,setpts=${F}*PTS,fps=${FPS}" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -an "$OUTPUT"
ffmpeg -hide_banner -filters | grep zscale
zscale есть только в сборках с --enable-libzimg. Проверьте так: ffmpeg -hide_banner -filters | grep zscale. Чаще всего его нет именно на macOS: стандартная сборка Homebrew идёт без zimg, а вот сборки Gyan для Windows, пакеты Debian и Ubuntu и статические сборки johnvansickle его содержат. Если фильтра нет, вариантов два. На машине с OpenCL можно взять tonemap_opencl (сложнее в настройке, нужен -init_hw_device opencl). Либо ограничиться format=yuv420p вместо всей цепочки: файл откроется везде, но цвета останутся неверными, светы уйдут в белое, а насыщенность просядет. Не молчите об этом в результате.
Поворот
Если картинка легла на бок, применяем поворот к пикселям и снимаем флаг из метаданных.
macOS
INPUT="input.mp4"; OUTPUT="output.mp4"; F=8; FPS=60
ffmpeg -i "$INPUT" -vf "transpose=1,setpts=${F}*PTS,fps=${FPS}" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -metadata:s:v rotate=0 -an "$OUTPUT"
transpose=1 это поворот на 90 градусов по часовой стрелке, transpose=2 - против часовой, для 180 берите transpose=1,transpose=1 или hflip,vflip. Нужное значение подскажет тег rotate из ffprobe: 90 - transpose=1, 270 - transpose=2. Ширина и высота при этом меняются местами.
Windows
$IN="input.mp4"; $OUT="output.mp4"; $F=8; $FPS=60
ffmpeg -i "$IN" -vf "transpose=1,setpts=${F}*PTS,fps=${FPS}" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -metadata:s:v rotate=0 -an "$OUT"
transpose=1 это поворот на 90 градусов по часовой стрелке, transpose=2 - против часовой, для 180 берите transpose=1,transpose=1 или hflip,vflip. Нужное значение подскажет тег rotate из ffprobe: 90 - transpose=1, 270 - transpose=2. Ширина и высота при этом меняются местами.
Linux
INPUT="input.mp4"; OUTPUT="output.mp4"; F=8; FPS=60
ffmpeg -i "$INPUT" -vf "transpose=1,setpts=${F}*PTS,fps=${FPS}" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -metadata:s:v rotate=0 -an "$OUTPUT"
transpose=1 это поворот на 90 градусов по часовой стрелке, transpose=2 - против часовой, для 180 берите transpose=1,transpose=1 или hflip,vflip. Нужное значение подскажет тег rotate из ffprobe: 90 - transpose=1, 270 - transpose=2. Ширина и высота при этом меняются местами.
Звук
По умолчанию дорожку проще убрать. Если звук нужен, растягиваем его цепочкой atempo, но на восьмикратном замедлении он превращается в гул.
macOS
INPUT="input.mp4"; OUTPUT="output.mp4"; F=8; FPS=60
ffmpeg -i "$INPUT" -filter_complex "[0:v]setpts=${F}*PTS,minterpolate=fps=${FPS}:mi_mode=blend[v];[0:a]atempo=0.5,atempo=0.5,atempo=0.5[a]" -map "[v]" -map "[a]" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -c:a aac -b:a 192k "$OUTPUT"
ffmpeg -i "$INPUT" -filter_complex "[0:v]setpts=16*PTS,minterpolate=fps=30:mi_mode=blend[v];[0:a]atempo=0.5,atempo=0.5,atempo=0.5,atempo=0.5[a]" -map "[v]" -map "[a]" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -c:a aac -b:a 192k "$OUTPUT"
ffmpeg -i "$INPUT" -filter_complex "[0:v]setpts=0.125*PTS[v];[0:a]atempo=2.0,atempo=2.0,atempo=2.0[a]" -map "[v]" -map "[a]" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -c:a aac -b:a 192k "$OUTPUT"
Общий множитель цепочки atempo обязан равняться 1/F, иначе звук уедет от картинки. Проверяется умножением: 0.5 в кубе это 0.125, то есть 1/8. Три команды выше - это x8, x16 и ускорение x8; для других кратностей просто добавляйте или убирайте звенья.
Windows
$IN="input.mp4"; $OUT="output.mp4"; $F=8; $FPS=60
ffmpeg -i "$IN" -filter_complex "[0:v]setpts=${F}*PTS,minterpolate=fps=${FPS}:mi_mode=blend[v];[0:a]atempo=0.5,atempo=0.5,atempo=0.5[a]" -map "[v]" -map "[a]" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -c:a aac -b:a 192k "$OUT"
Общий множитель цепочки atempo обязан равняться 1/F, иначе звук уедет от картинки. Проверяется умножением: 0.5 в кубе это 0.125, то есть 1/8. Три команды выше - это x8, x16 и ускорение x8; для других кратностей просто добавляйте или убирайте звенья.
Linux
INPUT="input.mp4"; OUTPUT="output.mp4"; F=8; FPS=60
ffmpeg -i "$INPUT" -filter_complex "[0:v]setpts=${F}*PTS,minterpolate=fps=${FPS}:mi_mode=blend[v];[0:a]atempo=0.5,atempo=0.5,atempo=0.5[a]" -map "[v]" -map "[a]" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -c:a aac -b:a 192k "$OUTPUT"
ffmpeg -i "$INPUT" -filter_complex "[0:v]setpts=16*PTS,minterpolate=fps=30:mi_mode=blend[v];[0:a]atempo=0.5,atempo=0.5,atempo=0.5,atempo=0.5[a]" -map "[v]" -map "[a]" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -c:a aac -b:a 192k "$OUTPUT"
ffmpeg -i "$INPUT" -filter_complex "[0:v]setpts=0.125*PTS[v];[0:a]atempo=2.0,atempo=2.0,atempo=2.0[a]" -map "[v]" -map "[a]" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -c:a aac -b:a 192k "$OUTPUT"
Общий множитель цепочки atempo обязан равняться 1/F, иначе звук уедет от картинки. Проверяется умножением: 0.5 в кубе это 0.125, то есть 1/8. Три команды выше - это x8, x16 и ускорение x8; для других кратностей просто добавляйте или убирайте звенья.
Прогресс и время
Долгие задачи удобно запускать с выводом прогресса в файл, чтобы видеть, сколько осталось.
macOS
INPUT="input.mp4"; OUTPUT="output.mp4"; F=8; FPS=60
ffmpeg -progress pipe:1 -nostats -i "$INPUT" -vf "setpts=${F}*PTS,fps=${FPS}" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -an "$OUTPUT"
ffmpeg -progress progress.txt -nostats -i "$INPUT" -vf "setpts=${F}*PTS,fps=${FPS}" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -an "$OUTPUT"
Пример: исходник 12 секунд, F=8, FPS=60 даёт ceil(12 * 8 * 60) = 5760 кадров на выходе. Если frame= растёт на 20 в секунду, работы примерно на 5 минут. Вторая команда пишет то же самое в файл progress.txt, что удобно, когда ffmpeg запущен в фоне.
Windows
$IN="input.mp4"; $OUT="output.mp4"; $F=8; $FPS=60
ffmpeg -progress pipe:1 -nostats -i "$IN" -vf "setpts=${F}*PTS,fps=${FPS}" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -an "$OUT"
Пример: исходник 12 секунд, F=8, FPS=60 даёт ceil(12 * 8 * 60) = 5760 кадров на выходе. Если frame= растёт на 20 в секунду, работы примерно на 5 минут. Вторая команда пишет то же самое в файл progress.txt, что удобно, когда ffmpeg запущен в фоне.
Linux
INPUT="input.mp4"; OUTPUT="output.mp4"; F=8; FPS=60
ffmpeg -progress pipe:1 -nostats -i "$INPUT" -vf "setpts=${F}*PTS,fps=${FPS}" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -an "$OUTPUT"
ffmpeg -progress progress.txt -nostats -i "$INPUT" -vf "setpts=${F}*PTS,fps=${FPS}" -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p -movflags +faststart -an "$OUTPUT"
Пример: исходник 12 секунд, F=8, FPS=60 даёт ceil(12 * 8 * 60) = 5760 кадров на выходе. Если frame= растёт на 20 в секунду, работы примерно на 5 минут. Вторая команда пишет то же самое в файл progress.txt, что удобно, когда ffmpeg запущен в фоне.
Какие кодировщики есть в системе
Сначала посмотрите, с чем собран ваш ffmpeg. Строка в списке ничего не гарантирует: кодировщик может быть собран, а железа под него нет. Надёжна только тестовая прогонка одного кадра.
macOS
ffmpeg -hide_banner -encoders | grep -E "videotoolbox|nvenc|qsv|amf|vaapi"
ffmpeg -hide_banner -f lavfi -i testsrc=size=1280x720:rate=30 -frames:v 1 -c:v h264_videotoolbox -f null -
Честный размен: libx264 -crf 18 остаётся значением по умолчанию, потому что при равном битрейте он даёт лучшую картинку. Аппаратный кодировщик - это опция "быстро", и качество при том же битрейте будет ниже, особенно на движении. И главное: в режиме motion узкое место не кодирование, а minterpolate, который считается на CPU. Там аппаратный кодировщик почти ничего не выигрывает, потому что кодировщик всё равно простаивает в ожидании кадров.
Windows
ffmpeg -hide_banner -encoders | Select-String "videotoolbox|nvenc|qsv|amf|vaapi"
ffmpeg -hide_banner -f lavfi -i testsrc=size=1280x720:rate=30 -frames:v 1 -c:v h264_nvenc -f null -
Честный размен: libx264 -crf 18 остаётся значением по умолчанию, потому что при равном битрейте он даёт лучшую картинку. Аппаратный кодировщик - это опция "быстро", и качество при том же битрейте будет ниже, особенно на движении. И главное: в режиме motion узкое место не кодирование, а minterpolate, который считается на CPU. Там аппаратный кодировщик почти ничего не выигрывает, потому что кодировщик всё равно простаивает в ожидании кадров.
Linux
ffmpeg -hide_banner -encoders | grep -E "videotoolbox|nvenc|qsv|amf|vaapi"
ffmpeg -hide_banner -vaapi_device /dev/dri/renderD128 -f lavfi -i testsrc=size=1280x720:rate=30 -frames:v 1 -vf "format=nv12,hwupload" -c:v h264_vaapi -f null -
Честный размен: libx264 -crf 18 остаётся значением по умолчанию, потому что при равном битрейте он даёт лучшую картинку. Аппаратный кодировщик - это опция "быстро", и качество при том же битрейте будет ниже, особенно на движении. И главное: в режиме motion узкое место не кодирование, а minterpolate, который считается на CPU. Там аппаратный кодировщик почти ничего не выигрывает, потому что кодировщик всё равно простаивает в ожидании кадров.
Аппаратное кодирование
Аппаратный кодировщик в разы быстрее, но при равном битрейте картинка хуже, особенно на движении. В режиме «По движению» узкое место всё равно minterpolate на процессоре, так что выигрыш там почти нулевой.
macOS
INPUT="input.mp4"; OUTPUT="output.mp4"; F=8; FPS=60
ffmpeg -i "$INPUT" -vf "setpts=${F}*PTS,fps=${FPS}" -c:v h264_videotoolbox -b:v 12M -pix_fmt yuv420p -movflags +faststart -an "$OUTPUT"
ffmpeg -i "$INPUT" -vf "setpts=${F}*PTS,fps=${FPS}" -c:v hevc_videotoolbox -tag:v hvc1 -b:v 8M -movflags +faststart -an "$OUTPUT"
ffmpeg -i "$INPUT" -vf "setpts=${F}*PTS,fps=${FPS}" -c:v libx265 -crf 20 -preset slow -tag:v hvc1 -pix_fmt yuv420p -movflags +faststart -an "$OUTPUT"
VideoToolbox не понимает -crf, качество задаётся битрейтом через -b:v или -q:v на Apple Silicon. Работает и на Intel, и на M-серии.
Windows
$IN="input.mp4"; $OUT="output.mp4"; $F=8; $FPS=60
ffmpeg -i "$IN" -vf "setpts=${F}*PTS,fps=${FPS}" -c:v h264_nvenc -rc vbr -cq 23 -b:v 0 -pix_fmt yuv420p -movflags +faststart -an "$OUT"
ffmpeg -i "$IN" -vf "setpts=${F}*PTS,fps=${FPS}" -c:v h264_qsv -global_quality 23 -pix_fmt nv12 -movflags +faststart -an "$OUT"
ffmpeg -i "$IN" -vf "setpts=${F}*PTS,fps=${FPS}" -c:v h264_amf -rc cqp -qp_i 22 -qp_p 24 -pix_fmt yuv420p -movflags +faststart -an "$OUT"
У nvenc вместо crf используется -cq при -rc vbr -b:v 0, у qsv это -global_quality, у amf это -rc cqp с -qp_i и -qp_p. Для AMD: ffmpeg -i "$IN" -vf "setpts=${F}*PTS,fps=${FPS}" -c:v h264_amf -rc cqp -qp_i 22 -qp_p 24 -pix_fmt yuv420p -movflags +faststart -an "$OUT"
Linux
INPUT="input.mp4"; OUTPUT="output.mp4"; F=8; FPS=60
ffmpeg -i "$INPUT" -vf "setpts=${F}*PTS,fps=${FPS}" -c:v h264_nvenc -rc vbr -cq 23 -b:v 0 -pix_fmt yuv420p -movflags +faststart -an "$OUTPUT"
ffmpeg -vaapi_device /dev/dri/renderD128 -i "$INPUT" -vf "setpts=${F}*PTS,fps=${FPS},format=nv12,hwupload" -c:v h264_vaapi -b:v 12M -movflags +faststart -an "$OUTPUT"
VA-API требует явного устройства и загрузки кадров в память видеокарты: отсюда -vaapi_device /dev/dri/renderD128 и хвост format=nv12,hwupload в фильтре. Проверьте, что устройство существует: ls /dev/dri/. Для nvenc нужны проприетарные драйверы NVIDIA, открытый nouveau кодировать не умеет.
То же самое без браузера
После установки ffmpeg интернет не нужен вообще: ни для запуска, ни для обработки. Это удобный вариант для закрытых контуров, машин без сети и пакетной обработки, где важно, чтобы данные не покидали конкретный компьютер.
Команды рассчитаны на ffmpeg 6 и новее. В более старых версиях названия некоторых фильтров отличаются.