Відео — це ілюзія. Це просто серія картинок, які змінюються так швидко, що око не помічає підміни. Але якщо ми збережемо ці "картинки" як звичайні BMP чи PNG файли, то 1 година фільму займе терабайти місця.
Чому ж тоді фільм на Netflix займає всього 1-2 ГБ? Відповідь: Математичне шахрайство (або, науковою мовою, компресія з втратами).
Уявіть, що ви пакуєте валізу у відпустку.
Це класична плутанина.
Контейнер (.mp4, .mkv, .mov)
Кодек (H.264, VP9, AAC)
Coder-Decoder. Це алгоритм, який:
Контейнер — це не просто "коробка". Це структурований формат зберігання, який організує різнорідні потоки даних у єдиний файл.
Уявіть, що ви відправляєте посилку другові:
.mp4, .mkv, .mov. Вона визначає, як все упаковано.Важливо: Ви можете покласти той самий подарунок (H.264 відео) в різні коробки (MP4 або MKV) — це працюватиме. Але деякі коробки (WebM) приймають тільки певні подарунки (VP9, AV1).
Що це? Один або кілька відеопотоків. Наприклад:
Приклад: На Netflix один файл може містити кілька версій відео різної якості. Коли ви перемикаєтеся з 720p на 1080p, плеєр просто переключається на інший потік у тому ж контейнері.
Формат даних: Сирі закодовані байти (H.264, VP9, AV1, тощо.)
Що це? Один або кілька аудіопотоків. Наприклад:
Приклад: Фільм на Blu-ray зазвичай має 3-5 аудіодоріжок (різні мови + звукові ефекти).
Формат даних: Сирі закодовані аудіобайти (AAC, Opus, MP3)
Що це? Текстові потоки з таймкодами.
Формати:
<video>)Приклад:
1
00:00:10,500 --> 00:00:13,000
Привіт, це перший субтитр.
2
00:00:15,000 --> 00:00:18,000
А це другий.
Що це? Інформація про файл, а не медіа-контент.
Що зберігається:
title)artist)creation_time)description)Приклад: Коли ви завантажуєте відео на YouTube, платформа читає метадані, щоб автоматично заповнити поля "Назва", "Тривалість", "Роздільна здатність".
Що це? Таймкоди для навігації (як розділи у книзі).
Приклад: На Blu-ray фільмі ви можете "перемотати на епізод 3" — це працює завдяки chapter markers у контейнері.
Структура:
Chapter 1: 00:00:00 - Intro
Chapter 2: 00:05:30 - Main Act
Chapter 3: 00:45:00 - Climax
| Контейнер | Розширення | Підтримка кодеків | Де використовується | Особливості |
|---|---|---|---|---|
| MP4 | .mp4, .m4v | H.264, H.265, AAC | Всюди: YouTube, телефони, браузери | Універсальний. Стандарт де-факто. |
| WebM | .webm | Тільки VP8, VP9, AV1, Opus, Vorbis | Веб (HTML5 <video>), YouTube | Відкритий стандарт Google. Немає патентів. |
| MKV | .mkv | Будь-які (H.264, VP9, AV1, FLAC) | Піратство, архіви, Blu-ray rips | Найгнучкіший. Підтримує все: меню, кілька аудіо. |
| MOV | .mov | H.264, ProRes, AAC | Apple екосистема, професійне відео | Оптимізований для Final Cut Pro та QuickTime. |
| AVI | .avi | Старі кодеки (DivX, Xvid) | Старі фільми | Застарів. Немає підтримки сучасних кодеків. |
| TS | .ts, .m2ts | H.264, H.265, AAC | Broadcast TV, стрімінг (HLS) | Може відновитися після помилок (важливо для Live) |
MP4 побудований з атомів (atoms) — це блоки даних, що вкладаються один в одного, як матрьошки.

Основні атоми:
ftyp (File Type)
Перший атом. Вказує тип файлу та сумісність.
Приклад:
isom — базовий ISO MP4mp42 — MP4 версія 2M4V — iTunes-сумісний відеоmoov (Movie Metadata)
Найважливіший атом. Містить всю інформацію про структуру:
Без moov ви не можете перемотувати відео! Плеєр читає moov, щоб зрозуміти, де знаходиться кадр на 1:30.
Проблема Web: Якщо moov знаходиться в кінці файлу (після mdat), браузер має завантажити весь файл, щоб почати відтворення.
Рішення: FFmpeg параметр -movflags faststart переміщує moov на початок.
mdat (Media Data)
Сирі закодовані дані: H.264 відеопакети, AAC аудіопакети.
Це найбільший атом (99% розміру файлу).
Плеєр читає moov, знаходить потрібний offset у mdat, і декодує тільки ті байти, що потрібні.
ffmpeg -i input.mp4 -c copy -movflags faststart output_web.mp4
Давайте подивимося, що всередині справжнього MP4 файлу.
# macOS
brew install ffmpeg mediainfo
# Linux
sudo apt install ffmpeg mediainfo
# Детальна інформація про потоки
ffprobe -v quiet -print_format json -show_format -show_streams video.mp4
# Читабельний вигляд
mediainfo video.mp4
Приклад виводу:
General
Format : MPEG-4
File size : 15.2 MiB
Duration : 2 min 10 s
Overall bit rate : 980 kb/s
Video
Format : AVC (H.264)
Codec ID : avc1
Resolution : 1920x1080
Frame rate : 30.000 FPS
Bit rate : 850 kb/s
Audio
Format : AAC LC
Channels : 2 channels (Stereo)
Sampling rate : 48.0 kHz
Bit rate : 128 kb/s
# Показати всі метадані
ffprobe -v quiet -show_entries format_tags -of json video.mp4
Результат:
{
"format": {
"tags": {
"major_brand": "isom",
"minor_version": "512",
"title": "My Awesome Video",
"artist": "Creator Name",
"creation_time": "2024-01-15T10:30:00.000000Z"
}
}
}
moov на початку файлу? → ffprobe -v trace video.mp4 2>&1 | grep moovContent-Type: video/mp4| Кодек | Розробник | Особливості | Де використовується |
|---|---|---|---|
| H.264 (AVC) | MPEG LA | Стандарт де-факто. Працює скрізь. Ефективний, але старий. | Всюди (YouTube, Twitch 1080p, файли на телефоні). |
| H.265 (HEVC) | MPEG LA | На 50% ефективніший за H.264, але платний ліцензійно. | Apple, Netflix 4K, Blu-ray. |
| VP9 | Безкоштовний аналог H.265. | YouTube (за замовчуванням для 1440p+). | |
| AV1 | AOMedia | Майбутнє. Ще краще стиснення, безкоштовний. Дуже важкий для кодування. | Netflix, YouTube (поступово). |
Перед тим як стискати відео, його спочатку треба правильно "упакувати" у кольоровий простір. І тут є хитрий трюк.

Ваш монітор працює з RGB (Red, Green, Blue). Кожен піксель зберігає 3 числа:
Для 1920×1080 кадру це 1920 × 1080 × 3 = 6,220,800 байтів (~6 МБ) на один кадр.
Але є проблема: людське око не рівноцінно сприймає колір та яскравість.
Ми набагато краще бачимо деталі світла й тіні, ніж відтінки кольору.
YUV розділяє ці канали:
Y (Luma)
U та V (Chroma)
Уявіть старі газетні фото:
Ось де починається магія. Якщо око не бачить деталей у кольорі, навіщо зберігати повну роздільну здатність для U та V?

| Формат | Опис | Байтів на піксель | Використання |
|---|---|---|---|
| 4:4:4 | Повна якість. Y, U, V для кожного пікселя. | 3 байти | Професійне відео. |
| 4:2:2 | U/V половина роздільності по горизонталі. | 2 байти | Broadcast, виробництво. |
| 4:2:0 | U/V половина і по горизонталі, і по вертикалі. | 1.5 байти | YouTube, Netflix, Blu-ray. |
Розрахунок для 1080p (4:2:0):
Y: 1920 × 1080 = 2,073,600 байтів
U: 960 × 540 = 518,400 байтів (1/4 від Y)
V: 960 × 540 = 518,400 байтів (1/4 від Y)
────────────────────────────────────
Всього: 3,110,400 байтів (~3 МБ)
Економія: 50% порівняно з RGB, без втрати якості для ока.
Тепер найцікавіша частина: як кодеки зменшують розмір у сотні разів?
Секрет простий: вони знаходять повтори і викидають їх.
Уявіть, що ви фотографуєте свою кімнату кожну секунду протягом 10 секунд.
Повтори ВСЕРЕДИНІ кадру
Просторова надлишковість (Spatial Redundancy)
У кожному кадрі є багато однакових пікселів поряд: синє небо, біла стіна, чорний стіл.
Аналогія: Якщо ви малюєте небо, не треба малювати кожну синю крапку окремо. Можна написати: "З цього місця до того — все синє".
Повтори МІЖ кадрами
Часова надлишковість (Temporal Redundancy)
Між кадрами №1 та №2 змінилося лише 5% картинки (ви поворухнули рукою, решта — ідентична).
Аналогія: Якщо ви пишете щоденник, не потрібно щодня писати "Я живу в Києві, мені 25 років". Достатньо написати один раз, а далі тільки "Сьогодні зробив X".
Уявіть Zoom-дзвінок:
Результат: Замість зберігати 300 повних картинок, кодек зберігає:

Кодеки групують кадри у GOP (Группа Картинок). Це як розділи книги.
Кожна група починається з I-фрейму (повної картинки), а далі йдуть P та B-фрейми (різниці).

Що це? Повноцінна картинка, як JPEG-фото.
Розмір: Найбільший (~500 KB для 1080p).
Коли використовується?
Аналогія: Це як перший кадр комікса — ви бачите всю сцену з нуля.
Важливо: Ви не можете почати дивитися відео з середини P-фрейму. Браузер/плеєр завжди шукає найближчий I-фрейм назад.
Що це? Зберігає тільки зміни від попереднього кадру (I або P).
Розмір: 20-50% від I-фрейму (~100-250 KB).
Як працює?
Приклад:
I-фрейм (00:00): Обличчя дивиться прямо
P-фрейм (00:03): "Обличчя повернулось на 5° вліво, решта без змін"
P-фрейм (00:06): "Губи відкрилися на 2 мм, решта без змін"
Аналогія: Це як другий кадр комікса: "Той самий герой, але тепер він усміхається". Не треба малювати всю фігуру знову, тільки посмішку.
Що це? Використовує інформацію і з попереднього, і з наступного кадру.
Розмір: Найменший! 5-15% від I-фрейму (~25-75 KB).
Як це можливо? Уявіть, ваша рука рухається з лівої частини екрану до правої:
Кодек бачить, що в кадрі №11 рука — це "50% між кадром №10 та №12", і зберігає саме цю інформацію замість повної картинки.

Компроміс: B-фрейми дають найкраще стиснення, але:
Чому Live-стрімери не люблять B-фрейми?
Затримка критична. Якщо ви стрімите гру, і кодек чекає "наступного кадру" для оптимізації, це додає 30-100 мс затримки. Для конкурентних ігор це неприйнятно.
Ось як виглядає типова група з 12 кадрів:
Підсумок GOP:
Тепер, коли ми розуміємо що робить стиснення (I/P/B-фрейми, YUV), давайте подивимося як це робить найпопулярніший кодек у світі.
H.264 (він же MPEG-4 AVC) — це стандарт, який з'явився у 2003 році і досі панує скрізь:
Чому він став стандартом?
H.264 не обробляє відео "попіксельно". Замість цього він ділить кадр на макроблоки розміром 16×16 пікселів.
Макроблок (16×16)
Аналогія: Мозаїка
Для 1920×1080:
Найважливіша частина H.264 — оцінка руху (Motion Estimation).

Ідея: Більшість блоків у кадрі №50 майже ідентичні блокам у кадрі №49. Можливо, вони просто трохи зсунулися (людина повернула голову).
Замість 256 пікселів (16×16) зберігаємо: вектор руху (2 байти) + залишок (20-50 байтів).
Пам'ятаєте гру "знайди 10 відмінностей" між двома картинками?
Замість того, щоб малювати всю другу картинку заново, ви просто пишете: "Кіт перемістився на 2 см вліво, фон той самий". Ось це і є motion estimation!
Для кожного макроблоку кодек вибирає один із режимів:
Intra-Prediction
Передбачення на основі сусідніх блоків у тому ж кадрі. Використовується для I-фреймів та складних блоків (де motion estimation не спрацював).
Аналогія: Якщо ліворуч від вас синє небо, ймовірно, що і праворуч теж небо.
Inter-Prediction
Передбачення на основі інших кадрів (P/B-фрейми). Використовує motion vectors.
Аналогія: Прогноз погоди — якщо вчора була хмарність, сьогодні, ймовірно, теж буде.
Після prediction кодек отримує residual (залишок) — різницю між передбаченням та реальністю.
DCT (Discrete Cosine Transform) перетворює ці піксельні дані у частоти:
Quantization просто відкидає високі частоти (або сильно їх спрощує).
Після всіх трансформацій кодек отримує набір чисел (motion vectors, residuals, coefficients). Їх треба запакувати ефективно.
H.264 використовує два методи:
Аналогія: Як ZIP-архів для тексту. Замість "AAAAAABBBB" пишемо "7A4B".
H.264 має кілька "рівнів" (profiles), які визначають, які фішки використовувати.
Для кого: Старі мобільні телефони, вебкамери, відеодзвінки.
Обмеження:
Результат: Швидко кодується та декодується, але файли трохи більші.
Для кого: Broadcast телебачення, стрімінг сервіси (старі).
Можливості:
Результат: Баланс між якістю та сумісністю.
Для кого: Blu-ray, Netflix 4K, професійне відео.
Можливості:
Результат: Найкраща якість при тому ж бітрейті. Вимагає потужніше залізо.
Якщо кодек — це спосіб пакування валізи, то бітрейт — це швидкість, з якою ви можете ці валізи переносити.
Бітрейт (Bitrate) — це кількість бітів (даних), які обробляються за одиницю часу. Зазвичай вимірюється в Mbps (мегабітах за секунду) для відео та kbps (кілобітах за секунду) для аудіо.
Уявіть, що відеодані — це потік автомобілів, які мають дістатися з точки А (сервер) в точку Б (ваш екран).
З відео розібралися. А звук?
Тепер ваша черга показати це на практиці.
У цьому демо ви створите нестиснуте відео і порівняєте його з H.264.
Переконайтеся, що у вас встановлений ffmpeg.
brew install ffmpeg
Створимо 5 секунд тестового шуму. Формат rawvideo зберігає кожен піксель без стиснення.
ffmpeg -f lavfi -i testsrc=duration=5:size=1920x1080:rate=30 -vcodec rawvideo raw_video.yuv
Результат: Цей файл буде величезним. (1920 _ 1080 _ 1.5 байт/піксель _ 30 кадрів _ 5 секунд ≈ 466 МБ).
Тепер стиснемо це ж відео в H.264.
ffmpeg -f lavfi -i testsrc=duration=5:size=1920x1080:rate=30 -c:v libx264 compressed_video.mp4
Результат: Файл буде розміром кілька кілобайт (або мегабайт, залежно від складності картинки).
ls -lh raw_video.yuv compressed_video.mp4
Ви побачите різницю в сотні разів. Це і є магія кодеків.
Тепер давайте порівняємо 4 різні кодеки на одному відео і подивимося, хто переможе.
Використаємо Big Buck Bunny — відомий open-source ролик для тестування відео.
# Завантаження 10 секунд у високій якості
wget -O bbb_sample.mp4 "https://download.blender.org/demo/movies/BBB/bbb_sunflower_1080p_30fps_normal.mp4"
# Витягнемо лише 10 секунд для швидкості тестування
ffmpeg -i bbb_sample.mp4 -t 10 -c copy bbb_10s.mp4
Тепер закодуємо це відео 4 способами. Всі команди використовують однаковий target бітрейт 5 Mbps для чесного порівняння.
ffmpeg -i bbb_10s.mp4 -c:v libx264 -b:v 5M -preset medium \
-c:a aac -b:a 128k output_h264.mp4
ffmpeg -i bbb_10s.mp4 -c:v libx265 -b:v 5M -preset medium \
-c:a aac -b:a 128k output_h265.mp4
ffmpeg -i bbb_10s.mp4 -c:v libvpx-vp9 -b:v 5M -cpu-used 2 \
-c:a libopus -b:a 128k output_vp9.webm
ffmpeg -i bbb_10s.mp4 -c:v libaom-av1 -b:v 5M -cpu-used 4 \
-c:a libopus -b:a 128k output_av1.mkv
Ось що ви отримаєте (орієнтовні значення для 10 секунд 1080p@30fps):
| Кодек | Розмір файлу | Час кодування | Підтримка браузерів | Якість (суб'єктивно) |
|---|---|---|---|---|
| H.264 | ~6.5 MB | 4 сек | ✅ 100% (всюди) | Відмінна |
| H.265 | ~4.8 MB | 18 сек | ⚠️ Safari, Edge | Відмінна |
| VP9 | ~5.2 MB | 45 сек | ✅ Chrome, Firefox | Відмінна |
| AV1 | ~3.9 MB | 180 сек (3 хв) | ⚠️ Chrome 90+ | Чудова |