FFmpeg — швейцарский нож для мультимедиа. Совершенно незаменимая программа, которую использует в повседневной жизни почти каждый, даже не зная об этом. Например, вы сняли видео и заливаете на видеохостинг — оно перекодируется и публикуется уже в другом разрешении/формате/размере. Как вы думаете, какая программа выполнила транскодирование? Вполне возможно, что под капотом на сервере работает FFmpeg.
FFmpeg объединяет более 300 видео/аудио/графических кодеков, декордеров, муксеров, демуксеров и фильтров. Благодаря ему вы можете написать собственный видеоплеер в тысячу строчек кода, не разбираясь с кишочками видеообработки.
Это «движок» почти всех современных инструментов для обработки/сжатия/редактирования видео. Они просто предлагают графический интерфейс с кнопками, а
ffmpeg
делает реальную работу. Другими словами, существует основной движок FFmpeg, а весь остальной софт — это прокладки/GUI/плееры/редакторы, которые дают к нему доступ. Но можно обойтись без посредников и использовать FFmpeg напрямую. Только в консоли. Последняя версия программы лежит здесь (вместе с сопровождающими инструментами FFplay и FFprobe).
Для примера, вот несколько практических задач, с которыми приходится сталкиваться в повседневной рутине. Все они решаются однострочниками за несколько секунд.
▍ Вырезать кусочек видео, сохранить его в GIF
Стандартная ситуация, когда хочется вырезать из фильма или видеотрансляции какой-то жест или эмоцию и отправить в мессенджер как анимацию. Например, в Телеграме анимации можно отправлять в форматах GIF и MP4.
FFmpeg вырезает видеофрагмент и конвертирует его в GIF следующей командой:
ffmpeg -i input.mp4 -r 10 -an -ss '00:11:02.5' -to '00:11:05' output.gif
В команде указан фреймрейт gif (10), время начала и конца видео. Как вариант, можно указать время начала и продолжительность фрагмента.
Примечание. Для генерации простых команд ffmpeg в первое время можно пользоваться «помощником» ffmpeg buddy.
▍ Пережать другим кодеком
Например, мы оцифровали старую VHS-кассету в программе HandBrake (подключили с видеомагнитофона по USB), не применяли никаких фильтров и сохранили MPEG2 разрешением 720×576. С трёхчасовой кассеты получился файл размером 6,4 ГБ.
Понятно, что кассете 30 лет, качество сигнала плохое, тем более это вторая или третья копия, которая была ужасна в момент своего появления. Но выбирать не приходится.
Глядя на исходный MPEG2, возникают вопросы:
- Как сжать это видео (с потерями качества), чтобы быстро закинуть одноклассникам в Телеграм? Качество такое, что снижение разрешения не играет особой роли.
- Как сохранить это видео для длительного хранения? Существуют ли видеокодеки для сжатия без потерь, как в случае с фотографиями?
С первым вопросом всё довольно просто. Указываем в FFmpeg масштабирование 50% по горизонтали и вертикали, кодируем стандартным кодеком:
ffmpeg -i input.mpg -vf 'scale=iw*0.5:ih*0.5' output.mp4
Здесь масштабирование указано относительно оригинала.
Или так:
ffmpeg -i input.mpg -vf 'scale=360:288' output.mp4
Здесь масштабирование указано в пикселях (половина от оригинального 720×576). Результат будет идентичный:
ffmpeg -i input.mpg -vf 'scale=360:288' output.mp4
ffmpeg version 5.0.1-essentials_build-www.gyan.dev Copyright (c) 2000-2022 the FFmpeg developers
built with gcc 11.2.0 (Rev7, Built by MSYS2 project)
configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-lzma --enable-zlib --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-sdl2 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --enable-libaom --enable-libopenjpeg --enable-libvpx --enable-libass --enable-libfreetype --enable-libfribidi --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-d3d11va --enable-dxva2 --enable-libmfx --enable-libgme --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libtheora --enable-libvo-amrwbenc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-librubberband
libavutil 57. 17.100 / 57. 17.100
libavcodec 59. 18.100 / 59. 18.100
libavformat 59. 16.100 / 59. 16.100
libavdevice 59. 4.100 / 59. 4.100
libavfilter 8. 24.100 / 8. 24.100
libswscale 6. 4.100 / 6. 4.100
libswresample 4. 3.100 / 4. 3.100
libpostproc 56. 3.100 / 56. 3.100
Input #0, mpeg, from 'input.mpg':
Duration: 02:26:12.00, start: 0.193178, bitrate: 6296 kb/s
Stream #0:0[0x1e0]: Video: mpeg2video (Main), yuv420p(tv, bt470bg, top first), 720x576 [SAR 16:15 DAR 4:3], 25 fps, 25 tbr, 90k tbn
Side data:
cpb: bitrate max/min/avg: 8500000/0/0 buffer size: 1835008 vbv_delay: N/A
Stream #0:1[0x1c0]: Audio: mp2, 48000 Hz, stereo, s16p, 224 kb/s
File 'output.mp4' already exists. Overwrite? [y/N] n
Not overwriting - exiting
PS D:\> .\ffmpeg -i input.mpg -vf 'scale=360:288' output.mp4
ffmpeg version 5.0.1-essentials_build-www.gyan.dev Copyright (c) 2000-2022 the FFmpeg developers
built with gcc 11.2.0 (Rev7, Built by MSYS2 project)
configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-lzma --enable-zlib --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-sdl2 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --enable-libaom --enable-libopenjpeg --enable-libvpx --enable-libass --enable-libfreetype --enable-libfribidi --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-d3d11va --enable-dxva2 --enable-libmfx --enable-libgme --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libtheora --enable-libvo-amrwbenc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-librubberband
libavutil 57. 17.100 / 57. 17.100
libavcodec 59. 18.100 / 59. 18.100
libavformat 59. 16.100 / 59. 16.100
libavdevice 59. 4.100 / 59. 4.100
libavfilter 8. 24.100 / 8. 24.100
libswscale 6. 4.100 / 6. 4.100
libswresample 4. 3.100 / 4. 3.100
libpostproc 56. 3.100 / 56. 3.100
Input #0, mpeg, from 'input.mpg':
Duration: 02:26:12.00, start: 0.193178, bitrate: 6296 kb/s
Stream #0:0[0x1e0]: Video: mpeg2video (Main), yuv420p(tv, bt470bg, top first), 720x576 [SAR 16:15 DAR 4:3], 25 fps, 25 tbr, 90k tbn
Side data:
cpb: bitrate max/min/avg: 8500000/0/0 buffer size: 1835008 vbv_delay: N/A
Stream #0:1[0x1c0]: Audio: mp2, 48000 Hz, stereo, s16p, 224 kb/s
Stream mapping:
Stream #0:0 -> #0:0 (mpeg2video (native) -> h264 (libx264))
Stream #0:1 -> #0:1 (mp2 (native) -> aac (native))
Press [q] to stop, [?] for help
[libx264 @ 00000202ddab6e80] using SAR=16/15
[libx264 @ 00000202ddab6e80] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
[libx264 @ 00000202ddab6e80] profile High, level 2.1, 4:2:0, 8-bit
[libx264 @ 00000202ddab6e80] 264 - core 164 r3094 bfc87b7 - H.264/MPEG-4 AVC codec - Copyleft 2003-2022 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=6 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to 'output.mp4':
Metadata:
encoder : Lavf59.16.100
Stream #0:0: Video: h264 (avc1 / 0x31637661), yuv420p(tv, bt470bg, top coded first (swapped)), 360x288 [SAR 16:15 DAR 4:3], q=2-31, 25 fps, 12800 tbn
Metadata:
encoder : Lavc59.18.100 libx264
Side data:
cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: N/A
Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 128 kb/s
Metadata:
encoder : Lavc59.18.100 aac
frame=219300 fps=209 q=-1.0 Lsize= 711087kB time=02:26:12.01 bitrate= 664.1kbits/s speed=8.35x
video:566821kB audio:137780kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.920495%
[libx264 @ 00000202ddab6e80] frame I:1143 Avg QP:22.93 size: 10857
[libx264 @ 00000202ddab6e80] frame P:59982 Avg QP:25.64 size: 5013
[libx264 @ 00000202ddab6e80] frame B:158175 Avg QP:29.16 size: 1690
[libx264 @ 00000202ddab6e80] consecutive B-frames: 2.9% 1.9% 2.9% 92.3%
[libx264 @ 00000202ddab6e80] mb I I16..4: 5.2% 71.9% 22.9%
[libx264 @ 00000202ddab6e80] mb P I16..4: 2.2% 13.8% 3.0% P16..4: 40.6% 26.7% 12.7% 0.0% 0.0% skip: 1.1%
[libx264 @ 00000202ddab6e80] mb B I16..4: 0.3% 1.1% 0.2% B16..8: 43.7% 11.8% 2.6% direct:14.1% skip:26.3% L0:38.2% L1:42.7% BI:19.1%
[libx264 @ 00000202ddab6e80] 8x8 transform intra:72.0% inter:73.2%
[libx264 @ 00000202ddab6e80] coded y,uvDC,uvAC intra: 75.8% 92.3% 56.3% inter: 31.9% 62.8% 4.8%
[libx264 @ 00000202ddab6e80] i16 v,h,dc,p: 30% 26% 3% 40%
[libx264 @ 00000202ddab6e80] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 24% 22% 12% 5% 7% 9% 7% 8% 7%
[libx264 @ 00000202ddab6e80] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 23% 26% 11% 5% 8% 9% 7% 7% 5%
[libx264 @ 00000202ddab6e80] i8c dc,h,v,p: 47% 21% 20% 11%
[libx264 @ 00000202ddab6e80] Weighted P-Frames: Y:31.1% UV:22.8%
[libx264 @ 00000202ddab6e80] ref P L0: 48.6% 19.1% 20.9% 9.5% 1.9%
[libx264 @ 00000202ddab6e80] ref B L0: 89.7% 8.4% 1.8%
[libx264 @ 00000202ddab6e80] ref B L1: 96.4% 3.6%
[libx264 @ 00000202ddab6e80] kb/s:529.34
[aac @ 00000202ddab8780] Qavg: 356.888
Потеря качества практически не заметна на экране телефона, а размер файла уменьшился до 694 МБ. Уже влезает в бесплатный лимит телеграма (и даже на CD, если кому-то отправить по почте).
Согласно документации, кодирование в H.265 займёт втрое больше времени, зато файл получится на 25–50% меньше, чем H.264. Но это пока относительно новый формат, который поддерживается не на всех старых устройствах. Даже FFmpeg по умолчанию его пока не использует. У меня не получилось закодировать в H.265 с настройками максимального качества и уменьшением разрешения в одной команде. Наверное, нужно сначала переконвертировать в lossless-формат, потом уменьшить до 50% кадра, а потом кодировать в H.265.
Кстати, перекодирование с уменьшением размера видео можно выполнить бесплатно на серверах Google, если залить оригиналы на YouTube, затем скачать результаты транскодинга программой yt-dlp и удалить исходники. Это удобно, если у вас сотни часов видеоматериала и не хочется нагружать свой ПК.
Эксперименты показывают, что любые кодеки с потерей качества заметно портят картинку, независимо от настроек. Казалось бы, надо найти вариант с перекодированием без потери качества (lossless). Теоретически, такие варианты есть. Ряд видеокодеков поддерживают режим сжатия без потерь, вот некоторые из них:
- H.264 lossless,
- H.265 lossless,
- Motion JPEG 2000 lossless,
- JPEG XS lossless,
- FFV1,
- AV1,
- VP9,
- Apple Animation (QuickTime RLE),
- … и другие.
FFmpeg использует энкодеры x264/x265, а также нативно поддерживает свободный кодек без потерь FFV1, который по параметрам компрессии похож на Motion JPEG 2000 lossless, но за счёт более быстрых алгоритмов может кодировать в реальном времени.
▍ Извлечение аудиодорожки
Например, у нас большая видеозапись, а мы хотим её загрузить в плеер/смартфон для прослушивания, чтобы не записывать гигабайты сопутствующего видео. Нет ничего проще:
ffmpeg -i input.mpg -map 0:1 bbb_audio.mp3
Если не указаны дополнительные параметры, то всё кодируется с настройками по умолчанию для MP3.
ffmpeg -i input.mpg -map 0:1 bbb_audio.mp3
ffmpeg version 5.0.1-essentials_build-www.gyan.dev Copyright (c) 2000-2022 the FFmpeg developers
built with gcc 11.2.0 (Rev7, Built by MSYS2 project)
configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-lzma --enable-zlib --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-sdl2 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --enable-libaom --enable-libopenjpeg --enable-libvpx --enable-libass --enable-libfreetype --enable-libfribidi --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-d3d11va --enable-dxva2 --enable-libmfx --enable-libgme --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libtheora --enable-libvo-amrwbenc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-librubberband
libavutil 57. 17.100 / 57. 17.100
libavcodec 59. 18.100 / 59. 18.100
libavformat 59. 16.100 / 59. 16.100
libavdevice 59. 4.100 / 59. 4.100
libavfilter 8. 24.100 / 8. 24.100
libswscale 6. 4.100 / 6. 4.100
libswresample 4. 3.100 / 4. 3.100
libpostproc 56. 3.100 / 56. 3.100
Input #0, mpeg, from 'input.mpg':
Duration: 02:26:12.00, start: 0.193178, bitrate: 6296 kb/s
Stream #0:0[0x1e0]: Video: mpeg2video (Main), yuv420p(tv, bt470bg, top first), 720x576 [SAR 16:15 DAR 4:3], 25 fps, 25 tbr, 90k tbn
Side data:
cpb: bitrate max/min/avg: 8500000/0/0 buffer size: 1835008 vbv_delay: N/A
Stream #0:1[0x1c0]: Audio: mp2, 48000 Hz, stereo, s16p, 224 kb/s
Stream mapping:
Stream #0:1 -> #0:0 (mp2 (native) -> mp3 (libmp3lame))
Press [q] to stop, [?] for help
Output #0, mp3, to 'bbb_audio.mp3':
Metadata:
TSSE : Lavf59.16.100
Stream #0:0: Audio: mp3, 48000 Hz, stereo, s16p
Metadata:
encoder : Lavc59.18.100 libmp3lame
size= 137063kB time=02:26:12.00 bitrate= 128.0kbits/s speed=31.5x
video:0kB audio:137063kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.000169%
С параметром
-ss
можно вырезать нужный фрагмент аудиодорожки.▍ Любая магия
Даже самый лаконичный и понятный мануал по FFmpeg занимает сотню страниц печатного текста. Про официальную документацию не стоит даже упоминать, там объём скорее в тысячу страниц.
Глядя на фантастические примеры использования FFmpeg, поражаешься мощи этого инструмента. Например, вот пользователь захотел поиграть в игры PS2 на своём ноутбуке. Но поскольку тот недостаточно мощный для эмулятора PCSX2, ему пришла идея транслировать видео с домашнего сервера в другом конце города. То есть он пробросил геймпад на рабочую станцию через USB/IP и начал копать мануал FFmpeg, как транслировать игру на ноутбук. FFmpeg захватывает видео напрямую из буферов KMS, использует аппаратное ускорение GPU для транскодирования со снижением разрешения, захватывает аудио, всё перекодирует с параметрами для передачи по сети (в реальном времени) и передаёт результат в UDP-сокет. На другом конце он настроил плеер mpv для получения и воспроизведения потока.
ffmpeg \
-f pulse \
-i alsa_output.platform-snd_aloop.0.analog-surround-51.monitor \
-f kmsgrab \
-thread_queue_size 64 \ # уменьшает задержку ввода
-i - \
# Capture and downscale frames on the GPU:
-vf 'hwmap=derive_device=vaapi,scale_vaapi=1280:720,hwdownload,format=bgr0' \
-c:v libx264 \
-preset:v superfast \ # максимально быстрое кодирование видео
-tune zerolatency \ # настройка кодека на нулевую задержку
-intra-refresh 1 \ # уменьшает задержку и уменьшает потери пакетов
-f mpegts \ # объединение в поток mpegts, который хорошо подходит для данного случая
-b:v 3M \ # целевая полоса пропускания для итогового видео
udp://$hackerspace:41841
Всего час изучения руководства — и мы с нуля составляем рабочую команду FFmpeg, чтобы играть в PS2 на ноутбуке через стрим с удалённого сервера. Практически Google Stadia своими руками (земля ей пухом).
Или вот пример из мануала:
ffmpeg -y \
-ss 20 -t 60 -i bbb_sunflower_1080p_60fps_normal.mp4 \
-i train.jpg \
-ss 4 -i voice_recording.wav \
-filter_complex "[0:v]hue=h=80:s=1[main] ; [1:v]crop=w=382:h=304:x=289:y=227[train] ; [main][train]overlay=x=200:y=200,vignette=PI/4[video] ; [2:a]volume=1.5,aecho=0.8:0.9:100:0.3[speech] ; [0:a][speech]amix=duration=shortest,asplit[audio1][audio2]" \
-map '[video]' -map '[audio1]' -metadata title="Editor's cut" bbb_edited.mp4 \
-map '[audio2]' bbb_edited_audio_only.wav
Эта команда делает в том числе следующее:
- Открывает файл.
- Вырезает фрагмент (
-ss 20 -t 60
).
- Накладывает изображение
train.jpg
.
- Обрезает наложенное изображение (
crop
).
- Добавляет эффект виньетирования под углом PI/4.
- Накладывает фильтр для коррекции тона (
hue
).
- Накладывает дополнительную звуковую дорожку
voice_recording.wav
.
- Увеличивает громкость.
- Добавляет эхо.
- Экспортирует результат в разные форматы.
- Экспортирует оригинальную звуковую дорожку.
Одна команда в консоли заменяет десять минут редактирования в Premiere Pro!
Оригинал (видео, картинка поезда, звук) и результат (справа):
▍ Редактор LosslessCut как GUI для FFmpeg
Как мы уже говорили, многие программы для обработки видео «под капотом» используют FFmpeg. И похоже, что FFmpeg начинает осваивать веб-технологии. Например, недавно появился ffmpeg.wasm — чистый порт FFmpeg на WebAssembly/JavaScript. Это обработка видео нативно в браузере.
Ещё одна интересная новинка последнего времени — видеоредактор LosslessCut. Он вырезает и склеивает фрагменты видео практически мгновенно и без потери качества, не выполняя перекодирование, как Adobe Premiere Pro. Привычная получасовая операция тут занимает пять секунд, экономя при этом гигабайты дискового пространства.
LosslessCut
Конечно, такая магия работает только при условии, что фрагменты видео/аудио сжаты одинаковым кодеком. В данном случае не требуется повторная обработка и фрагменты достаточно просто склеить.
Такая функциональность лучше всего подходит для следующих задач:
- Быстрый монтаж небольших видеороликов.
- Вырезание/добавление фрагментов. Например, вот что можно сделать:
- вырезать рекламные ролики из записанной телепередачи;
- удалить аудио- или видеодорожку из файла;
- добавить музыку в видео (или заменить существующую звуковую дорожку);
- добавить субтитры (или произвольные надписи) в видеоряд;
- выполнить слияние файлов (с идентичными параметрами кодирования);
- извлечь любые/все дорожки из файла;
- извлечь музыку, видео или субтитры из видео и обрезать их в соответствии с вашими потребностями;
- повернуть видео, для которого установлен флаг неправильной ориентации, например, видео с телефона.
- вырезать рекламные ролики из записанной телепередачи;
- Быстрое перекодирование H264 MKV в MOV или MP4 для воспроизведения на iPhone.
-
Журнал последних команд ffmpeg, чтобы изменять и запускать эти команды из консоли.
- Зацикливание видео/аудио X раз без повторного кодирования.
- Экспорт/импорт вырезанных сегментов в CSV.
Примечание: доступность отдельных функций зависит от формата/кодека.
В общем, очень полезный инструмент. Неудивительно, что под его капотом тоже работает FFmpeg. То есть LosslessCut — просто удобный и эффективный FFmpeg GUI. Разумеется, исходный код тоже открыт. Если есть желание задонатить автору, то программу можно купить через Mac App Store или Microsoft Store. Версия под Linux распространяется через Snap Store и Flathub (а также напрямую с GitHub).
FFmpeg выполняет практически любые операции с мультимедийными файлами, какие только можно представить. Остаётся упомянуть добрым словом гениального программиста Фабриса Беллара, который запустил этот опенсорсный проект в 2000 году и несколько первых лет возглавлял разработку. Человечеству нужен был такой инструмент. Теперь он у нас есть, проблема решена, а Фабрис работает над другими крайне важными задачами.
Telegram-канал с розыгрышами призов, новостями IT и постами о ретроиграх
Комментарии (82)
andreymal
00.00.0000 00:00+4И все всегда забывают указывать правильное цветовое пространство, чтобы плеерам не приходилось его угадывать. Поэтому совет: если лень разбираться с этим, то просто вставляйте эти опции в параметры кодирования видео, в большинстве случаев сойдёт:
-color_primaries:v bt709 -color_trc:v bt709 -colorspace:v bt709
An_private
00.00.0000 00:00А смысл? В 99% при разрешении видео SD и ниже - bt470, всё что выше - b709. Тут, правда, есть подводный камень - если делаешь апскейл SD-HD или даунскейл HD-SD, то лучше прописать преобразование в явном виде. А в остальных случаях особо и не надо.
andreymal
00.00.0000 00:00+6Я как питонист воспитан, что явное лучше неявного, подводных камней будет поменьше)
Плюс в такой формулировке возникает вопрос, что такое SD, а что такое HD. Слегка увеличенное видео 722x578 — это уже HD или ещё SD? Или наоборот, слегка обрезанное видео 1278x718 — это уже SD или ещё HD? А если «кинематографичное» соотношение сторон 1280x536? А если кому-то приспичило сделать неквадратный пиксель 640x536? У всех ли плееров одинаковый алгоритм «угадывания»? А у браузеров? https://habr.com/ru/company/vdsina/blog/560224/
Я не хочу задаваться подобными вопросами, поэтому для удобства сделал себе в консоли переменную
$BT709
, которую теперь пихаю почти в любую команду ffmpeg: цветовое пространство в моих файлах указано, а если у кого-то видео отобразится некорректно, то это уже не мои проблемы)An_private
00.00.0000 00:00+1Обычно считается по ширине - всё, что до 720 - SD, 721 и более - HD.
Проблема в том, что для этого надо учитывать входное цветовое пространство. То есть можно, конечно, по умолчанию ставить видеофильтр приведения к 709, но это, скорее костыль.
An_private
00.00.0000 00:00+1Посмотрел статью, на которую дана ссылка, и стал понимать. Дело в том, что я в основном имею дело с профессиональными программами работы с видео. И у них алгоритм именно такой - если цветовое пространство прописано в файле - работать в нём. Не прописано - смотрим по разрешению файла.
Если же данный алгоритм не гарантирован - то, конечно, лучше прописывать цветовое пространство в явном виде.
Немного напоминает ранние компьютерные видеоплейера, программисты которых в принципе не понимали - что такое чересстрочная развертка и как пиксель может быть неквадратным
Balling
00.00.0000 00:00+1ITU-R BT.470 же закончился, когда Москва отключила аналоговый ТВ, и то там был SECAM, а значит https://en.wikipedia.org/wiki/YDbDr
Вы вообще не понимаете, что несете.
Primaries между SD и HD разные (причем в SD может быть два типа, а вообще могут быть любые) -- это надо тоже проконтролировать отдельно от матрицы.
13werwolf13
00.00.0000 00:00Ряд видеокодеков поддерживают режим сжатия без потерь
помню игрался с тем как хранить видео, HuffYUV отжирает просто непомерно места и довольно паршиво сжимается силами ФС, зато практически моментально обрабатывается серверами youtube (после многочасового ожидания выгрузки на эти самые сервера конечно).
Eol78
00.00.0000 00:00Я не так давно открыл для себя безпотерьный кодек utvideo. Сжатие гораздо лучше, чем HuffYUV, а скорость приблизительно такая же. ffmpeg в него умеет. А лучше всех из известных жмёт ffv1, правда он медленный, и как мне кажется, однопоточный
Balling
00.00.0000 00:00Математический lossless поддерживается в ffmpeg для AV1 (и даже AVIF), VP9, AVC, HEVC. Слышали про такие? Причем hevc и avc lossless даже с nvenc на Nvidia Turing.
А еще есть MJPEG 2000 lossless. И даже JPEG lossless и JPEG-LS и даже JPEG XL.
Conung_ViC
00.00.0000 00:00+23Одна команда в консоли заменяет десять минут редактирования в Premiere Pro!
Ага. и 2 суток курения мануалов, чтоб эту команду составить...
Кстати, еще прекрасный мультимедиа комбайн/фреймворк - это GStreamer. Тоже позволяет творить мультимедиа магию в консоли, и может быть встроен в ваши приложения.LakesChueka
00.00.0000 00:00+1Gstreamer ещё, кстати, используется в nvidia deepstream SDK. Т.е. при работе с jetson альтернатив, к сожалению, мало.
emerald_isle
00.00.0000 00:00Если не указаны дополнительные параметры, то всё кодируется с настройками по умолчанию для MP3.
Не очень понял. А как вытащить аудиодорожку без перекодирования? Возможно ли это в принципе? Она же как-то уже закодирована, правильно? Во-первых, это по идее должно быть быстрее, а во-вторых, хочется без потери качества (а все эти кодирования туда-сюда по-любому могут что-то там портить).
andreymal
00.00.0000 00:00Да,
-c:a copy
— только вот в mpg-файлах будет скорее всего не mp3, а что-то другое, а значит или придётся заранее узнавать кодек и выбирать правильный контейнер для него, или всё-таки перекодироватьMetotron0
00.00.0000 00:00ffmpeg -i позволяет тут же на месте узнать кодек
ElvenSailor
00.00.0000 00:00с хорошей вероятностью там будет AAC, и контейнер .m4a
а вообще, сам же ffmpeg расскажет, что там и чем пожато.
Balling
00.00.0000 00:00И скорее всего m4a контейнер неправильный и это скорее всего mp4. Для m4a надо отдельно команду.
saboteur_kiev
00.00.0000 00:00+7Я обнаружил, что chatGPT заменяет все подобные статьи и документацию по ffmpeg. Примерно понимая что ffmpeg может, просто спрашиваешь у чатгпт как это сделать, получаешь готовую команду, и делаешь.
Kaputmaher
00.00.0000 00:00+1Еще для быстрого редактирования без перекодирования удобен Avidemux, только нужно удалять контент между ключевыми кадрами
Dr_Faksov
00.00.0000 00:00С перекодированием - тоже. С деинтерлейсингом, субтиррами, поворотами и прочими наворотами. Там возможностей - море.
Javian
00.00.0000 00:00мы оцифровали старую VHS-кассету в программе HandBrake
Это как? HandBrake для перекодирования видеофайлов, а не для видеозахвата.
An_private
00.00.0000 00:00+3У меня не получилось закодировать в H.265 с настройками максимального качества и уменьшением разрешения в одной команде
Эээээ. Что???
А вообще - статья мне напомнила классический рисунок "как нарисовать сову".
NNMTM
00.00.0000 00:00+1Няшненько и ванильненько, самое главное не упоминать про интерлейс, правильные пропорции кадра и frame accuracy, что-бы не спугнуть маленьких "я-ж погромистов".
beremour
00.00.0000 00:00+4Одна команда в консоли заменяет десять минут редактирования в Premiere Pro!
Эээ :) только всё наоборот: десять минут редактирования в Premiere Pro заменяет день курения мануалов для формирования "одной команды"
Voenniy
00.00.0000 00:00+1p0isk
00.00.0000 00:00+2И h265 через hls тоже:
ffmpeg -fflags nobuffer
-rtsp_transport tcp -stimeout 1000000
-i "rstp://ip/stream.265"
-vsync 0 -copyts -vcodec copy
-movflags frag_keyframe+empty_moov
-c:a aac -method POST -f hls
"https://a.upload.youtube.com/http_upload_hls?cid=YOUR_KEY©=0&file=index.m3u8"
Germanjon
00.00.0000 00:00Фразы вида "Программа - швейцарский нож в такой-то области..." уже изрядно надоели, как будто нельзя найти другую аналогию или мем.
Balling
00.00.0000 00:00Это самая главная библиотека в мире после GMP/GCC/Clang. А это компилятор.
Germanjon
00.00.0000 00:00Не спорю, но фраза "швейцарский нож" на Хабре и в статьях к опенсорсным программам уже приелась. Возможно только мне.
fshp
00.00.0000 00:00glibc: "Ну да, ну да. Пошла я нахер".
Balling
00.00.0000 00:00Ну да, есть же Microsoft libm (или в код windows нужно смотреть) https://github.com/amd/win-libm/blob/master/pow.asm#L108
libc++ в llvm есть тоже.
Musl, uClibc.
https://en.wikipedia.org/wiki/Bionic_(software)
А вот у GMP там только GNU MPRF и ARB. И то спорно.
fshp
00.00.0000 00:00Пересекаемся в разных постах))
glibc не имеет отношения непосредственно к c++. А Musl и uClibc не на столько популярны.
Balling
00.00.0000 00:00Альтернативы есть. У ffmpeg нет, даже близко. Gstreamer уступает в 10 раз, да и не имеет hdr zscale например. Что там ещё? Avisynth+? Смешно.
Да и в любом случае GMP бесконечная арифметика самая важная библиотека, без неё gcc это тыква.
yakimchuk-ry
00.00.0000 00:00+4Закину кирпич, пока не знаю в чей огород.
Когда работал с ffmpeg, была задача видео разных форматов приводить к одному формату, прожигать субтитры, изменять размер видео, склеивать видео из разных форматов, и так далее.
Вобщем, швейцарский нож да, инструмент огонь, но пытаясь собрать в одно целое видео разных форматов это как та картинка про CSS из грифинов. Постоянные артефакты, ограничения, дропы кадров, искажения, и прочее, и прочее, целое море всевозможных косяков с кодированием вылезло. Может быть готовить не умею.
Я к тому, что круто оно круто, но как и любой инструмент который пытается собрать воедино всё и сразу, это не просто взять и использовать, это всё-равно море работы по исследованию совместимостей, отладке, и прочему.
Но ffmpeg огонь в любом случае. Титаническая работа сделана.
An_private
00.00.0000 00:00Вот что он не любит - это собирать несколько клипов в один. Совершенно не его задача.
А вот чего мне у него действительно не хватает - некоего внутреннего скриптового языка, чтобы можно было внутри него формировать командную строку в зависимости от формата входного файла. Поэтому у меня большинство задач решается либо через bat'ник - запустил ffmpeg, получил параметры входного файла, распарсил выход, сформировал командную строку, запустил ffmpeg на обработку. Либо через самописные программы, делающие примерно то же самое, но когда нужно что-то более наворочанное.
Ну и, конечно, его библиотеки просто великолепны.
qw1
00.00.0000 00:00+2Вот что он не любит — это собирать несколько клипов в один. Совершенно не его задача.
Я собирал. Нужно сконвертировать файлы в формат TransportStream (ts), т.е. поток без глобального заголовка, где заголовок есть у каждого фрейма, затем файлы бинарно склеить (copy /b), затем обратно из ts в mp4. Всё это можно делать без перекодирования (-c:a copy -c:v copy).An_private
00.00.0000 00:00Да не, можно, конечно. Но далеко не всякий формат поддерживает ts. А уже тем более это не работает в случае " пытаясь собрать в одно целое видео разных форматов", как в исходном комментарии.
Тут уже либо надо конвертить сперва в промежуточный формат и потом уже собирать всё это в кучу. Либо пытаться как-то извратиться через фрейм-сервера. Но этим лично я не занимался, поэтому не могу ничего конкретного сказать.
qw1
00.00.0000 00:00В исходном комментарии
задача видео разных форматов приводить к одному формату
То есть, вместо-c:v copy
надо-c:v libx264
если кодек отличается.Тут уже либо надо конвертить сперва в промежуточный формат и потом уже собирать всё это в кучу
Вы смешиваете в одну кучу контейнер и кодек. «Промежуточный формат» как контейнер — ничего страшного, это быстрое копирование потока. «Промежуточный формат» как кодек — не нужен, т.к. конвертить надо не в промежуточный, а сразу в окончательный h.264.
Но в целом, замечание справедливое. Если надо смонтировать совсем разные клипы последовательно в один файл, в командной строке это целый квест, когда в GUI-редакторах это банальное мышекликание.Ulibka
00.00.0000 00:00Дайте пожалуйста пример команд чтобы склеить два ролика разных форматов (для человека который ffmpeg никогда не пользовался ) :)
qw1
00.00.0000 00:00+1ffmpeg -i clip1.avi clip1.ts ffmpeg -i clip2.avi clip2.ts copy /b clip1.ts + clip2.ts clip_result.ts ffmpeg -i clip_result.ts -c:v copy -c:a copy clip_result.mp4
в первых двух командах не указываю-c:v copy -c:a copy
на случай, если аудио/видео в разных кодекахBalling
00.00.0000 00:00Ваша 3 команда это плохая идея. Объединять так нельзя. Есть спец. фильтры в ffmpeg
Metotron0
00.00.0000 00:00+1А я сперва жму в одинаковые форматы с одинаковым размером кадра, а потом делаю mkvmerge -o file.mkv file1 + file2 + fileN
fshp
00.00.0000 00:00Отдельный скриптовый язык не нужен, когда есть биндинги для питона.
andreymal
00.00.0000 00:00+3А они есть? Всё, что я вижу в своём гугле, это просто обёртки над командной строкой, толку от которых почти нет
fshp
00.00.0000 00:00https://github.com/kkroening/ffmpeg-python
Толк от них в том, что бы не парсить вывод ffmpeg в первую очередь. А например удобно получить разрешение видео через api, список стримов и т.п.
Скажем вам нужно все что больше fullhd уменьшить вполовину, а все что меньше уменьшить на 80%. На cmd или баше это будет боль.
andreymal
00.00.0000 00:00+2Это не биндинги, а распарсить
ffprobe -print_format json
тривиально и без таких библиотек, поэтому я их не используюЕщё есть проблема, что это подразумевает два отдельных запуска (сперва ffprobe, потом ffmpeg), а между запусками свойства стримов имеют шанс внезапно поменяться — это было для меня проблемой, когда я пытался работать с RTSP-потоками IP-камер
fshp
00.00.0000 00:00Ну если нужны именно биндинги к либам, то https://pyav.org
Тут конечно личные предпочтения. Но если мне нужно написать пару циклов с несколькими условиями, то я ни при каких обстоятельствах не выберу баш.
Balling
00.00.0000 00:00Так и есть. Это считается библиотека, а значит очень все хитро. Т.е. предполагается, что ты сам пишешь код, а не пользуешься ffmpeg/ffprobe и уж тем более ffplay.
>Постоянные артефакты, ограничения, дропы кадров, искажения, и прочее, и прочее, целое море всевозможных косяков с кодированием вылезло. Может быть готовить не умею.
Обычно с ffplay/mpv нет проблем. VLC это баг на баге.
Borjomy
00.00.0000 00:00-5Графическая оболочка для работы с графическим же контентом, предпросмотром, и визуальным выбором режимов, когда будет?
В IrfanView же сделали. Один человек, между прочим, работал.
Moskus
00.00.0000 00:00+1IrfanView - никакая не "оболочка", а полноценная программа с GUI. (Наличие у нее интерфейса командной строки не делает ее консольной программой.)
ElvenSailor
00.00.0000 00:00Мужики, а можно дать примеры команд для hardware-accelerated encoding ? С масштабированием , к примеру, с 3840x2160 до fullhd , желательно тоже аппаратным ?
qw1
00.00.0000 00:00+2В официальной документации есть страница trac.ffmpeg.org/wiki/HWAccelIntro
При запуске без параметров видно, с какими опциями скомпилен ваш ffmpeg.exe (например, --enable-nvenc).
В ком. строку добавляется
-c:v h264_nvenc
или
-c:v h264_cuvid
для NVidia
или для AMD
Windows: -c:v h264_amf / hevc_amf
Linux: h264_vaapi / hevc_vaapiBalling
00.00.0000 00:00cuvid может быть как декодер (до -i), так и енкодер. А вот nvenc все сложнее. Это только енкодер. Для декодера используется программный h264, но можно добавить ускорение (-hwaccel cuda, имеено cuda, не nvdec, или другие). h264 при этом все равно активно используется.
AmiGO1
00.00.0000 00:00+1Кто вдруг не знает, хочу посоветовать конвертер с аппаратным ускорение HEVC(h265) кодека на картах nvidia - nvenc. После попыток обработки большого количества домашнего видео 2.7k в 265 кодек с помощью ffmpeg случайно пришёл к нему. Скорость обработки кратно быстрее длительности ролика( условно, ролик в 1 минуту обрабатывается за 20-25 секунд ) на карте 1060. Если говорит о более низких разрешениях-там вообще полёт. С телефона не удобно, позже дополню ссылкой.
Metotron0
00.00.0000 00:00https://developer.nvidia.com/video-encode-and-decode-gpu-support-matrix-new
Вот тут указано, кто во что умеет сжимать. 1030 ни во что не умеет, если что. Потому что GT, а нужно GTX. Я разок так прокололся на покупке.
SneakyJoe
00.00.0000 00:00Мне вот было интересно возможно ли как-то спарить ffmpeg и smooth video project чтобы конвертировать 30 фпс стримы в 60 фпс через командную строку. Я в своё время игрался, не нашёл. Мб кто знает?
Balling
00.00.0000 00:00Это бесполезно. Без LG C9 и новее аппаратной упловнялки артефактов будет слишком много.
SneakyJoe
00.00.0000 00:00Напоминает ответы на форумах когда попытка разобраться зачем человеку что-то надо заменяет простой ответ в стиле "вот, сделай так, но разочаруешься"
Я транскодил стримы которые я смотрел с 30 фпс и мне было норм, артефактов было не так уж и много - тем более сильно зависит от стилистики контента. Хотелось бы и на отдачу это как-то запихнуть.
alexkuzko
00.00.0000 00:00Давненько не было тут такого...
Подскажите кто что использует чтобы звук корректно растянуть из 23.976 в 25 кадров? Использовал раньше atempo, но на некоторых исходниках он заметно портит звук. Недавно попробовал rubberband, с ним пришлось долго параметры подбирать чтобы убрать одну проблему, правда в целом звук становится выше и несколько хуже...
Есть ли что-то проф.уровня именно в ffmpeg?
qw1
00.00.0000 00:00Даже не подозревал, что есть такая проблема.
Ведь звуковая дорожка идёт со своими параметрами (AAC, 192Kbps, 44.1KHz, 16-bit, stereo, например) и формально никак не связана с частотой кадров видео.
Balling
00.00.0000 00:00+1Для начала поймите 23.976 это на самом деле 24/1.001 и да это играет огромное значение.
Вот есть такое. https://toolstud.io/video/framerate.php?inputfps=23.976&compare=network&duration=60&duration_unit=seconds&outputfps=25
alexkuzko
00.00.0000 00:00Это вы хорошо заметили... вот только я про это очень хорошо в курсе.
И если я меняю частоту видео, то я использую setpts + atempo, причем мои значения отличаются от тех, что по вашей ссылке (проверял что чуть лучше результат именно из-за того что нет ошибки округления т.к. 23.976 != 24/1001).
Как они хотят:ffmpeg -i [input] -r 25 -filter:v "setpts=0.959*PTS" -y [output]
Как я пишу:ffmpeg -i [input] -r 25 -filter:v"setpts=0.959040959*PTS" -y [output]
Почему?24000/1001 = 23.976023976/25 = 0.959040959 и 25/23.976023976 = 1.042708333
Аналогично и по звуку
Предлагается:ffmpeg -i [input] -filter:a "atempo=1.0427" -vn [output]
Я же делаю иначе:ffmpeg -i [input] -filter:a "atempo=1.042708333" -vn [output]
Но сути это не меняет, звук-то портится. Поэтому и ищу вариант получше.Пробовал (после тестов на слух) вариант с rubberband, искажения стали другими:
rubberband=tempo=1.042708333:pitch=1.042708333:pitchq=quality:smoothing=on:channels=apart:phase=independent:detector=percussive:transients=crisp
Вариант с тупым -r 25 не катит, т.к. видео заметно дергается...
Т.е. я не совсем не в теме, хотя это не мой профиль. И если у вас есть иные советы - напишите, думаю что не только мне будет полезно. Спасибо!
NasretdinovRR
00.00.0000 00:00Считаю также важным отразить в примерах, что в зависимости от задачи стоит применять различные пресеты. Видеофайл, сжатый в H.264 с пресетом slower, будет примерно в 10 раз легче при таком же качестве, чем сжатый с пресетом ultrafast, но при этом процесс сжатия может быть до 10 раз медленнее. Также для новичков будет полезно знать, что пресеты veryslow и placebo в большинстве случаев не рекомендуются: экономия битрейта (в сравнении со slower) от них незначительная, обработка крайне медленная, могут быть проблемы при воспроизведении в некоторых плеерах.
akhmat-kat
Очень удобная штука! Используем в своем проекте для обработки более полутора тысяч видео.