До списку уроків
9 клас · Урок 10 з 16

Монтаж без кнопок: ffmpeg, субтитри, build.sh

виконано0%
Крок 1

Що робимо сьогодні

Модуль I · IT Skills (Cloud Services & Documents) · тема 5, урок 2 з 2 · 120 хвилин

У тебе вже все є. Шість панелей коміксу лежать у ~/local/comic/images/, музична підкладка й ефекти — у ~/local/av/. Сьогодні з цього народжується трейлер на 20–40 секунд.

Але головне не ролик. Ролик змонтувати нескладно. Важче інше. Через тиждень ти заміниш одну панель — і доведеться згадувати, «а що я тоді натискав». Тому сьогодні монтаж — це файл. Він зветься build.sh і збирає ролик сам, від початку до кінця, однією командою.

Друга частина уроку — субтитри. Це окремий текстовий файл із репліками й часом їх показу. Завдяки йому ролик зрозуміє й той, хто його не почує.

Після уроку ти вмієш

Слова WebVTT, ffprobe і LUFS поки нічого не означають. Розберемо їх по черзі, кожне після конкретної дії.

Жорстка умова теми: ffmpeg живе тільки в тебе Увесь монтаж відбувається на твоєму комп'ютері, у теці ~/local/av/. Сервер нічого не рендерить і не перекодовує — він відхиляє .mp4 автоматично, і залити ролик по FTP не вийде. На сервер їдуть чотири текстові файли: build.sh, trailer.vtt, probe.txt, av.meta.json. Сам ролик учитель дивиться очно, за твоїм екраном, з увімкненими субтитрами.
Що вже було у 8 класі й сьогодні не повторюємо Анатомію команди ffmpeg (порядок ключів, -i, -c:v, -y), склейку через concat і титр через drawtext ти вже розбирав. Сьогодні ці команди — будівельний матеріал, а урок про те, як їх скласти в скрипт, як зробити ролик доступним і як про нього звітувати.

Хід уроку

ЕтапХвЩо робимо
Розминка10Слухаємо дві підкладки з уроку 9
Чому скрипт15Відтворюваність, перезбірка, історія змін
Анатомія build.sh20Змінні, перевірки, збірка, звіт
Практика 125Пишеш свій build.sh і збираєш трейлер
Перерва10
Субтитри20WebVTT, доступність, редактор на цій сторінці
Практика 215probe.txt, av.meta.json, вивантаження по FTP
Очна здача5Дивимося ролик і запускаємо build.sh при вчителі
Разом120
Наскрізний приклад уроку Скрізь на сторінці один і той самий ролик: 6 панелей по 5 секунд = 30,00 с, 1280×720, 25 кадрів/с, відео h264, звук aac 192 кбіт/с. Числа у прикладах probe.txt, av.meta.json і на схемах узгоджені між собою — можеш перевіряти.
Тека практики зветься за темою Робота обох уроків теми 5 складається в одну теку ~/www/av/ і в локальну ~/local/av/. Теки lesson-10 немає й не буде — не шукай.
Крок 2

Чому build.sh, а не команди в зошиті

Три причини, і жодна з них не про «так красивіше»

Уяви двох монтажерів. Перший набирає команди ffmpeg у терміналі, дивиться результат, щось міняє, набирає знову. Другий пише ті самі команди у файл build.sh і запускає його. Поки все йде добре, різниці немає. Різниця з'являється в момент першої правки.

1. Відтворюваність

Запусти скрипт сьогодні, через тиждень і на іншому комп'ютері — ролик вийде той самий. Це і зветься відтворюваність. Скрипт відтворюваний, бо в ньому записано рівно ті команди, у рівно тому порядку.

Команди «з пам'яті» — ні. Учора ти поставив -crf 20, сьогодні -crf 23. Ролик уже інший, а чому — ніхто не пригадає.

2. Перезбірка після правки

Ти замінив третю панель. Що далі?

КрокКоманди в зошиті./build.sh
Знайти, що робивгортаєш історію термінала й зошитвідкриваєш файл
Повторити7–9 команд руками, кожна — шанс помилитисяодна команда
Скільки часудесять хвилин і більшестільки, скільки триває збірка
Ризикролик вийшов «схожий, але інший»ролик той самий, крім заміненої панелі
Руками: кожна правка — це весь шлях наново правка панелі згадати ключі набратисім команд одруківкав одній із них іншийролик Скриптом: правка й одна команда правка панелі або рядка скрипта ./build.sh той самий ролик, крім того, що правив цикл замикається: правити можна скільки завгодно разів
Верхній шлях щоразу починається спочатку і щоразу дає трохи інший результат. Нижній — замкнений цикл: єдине, що змінюється між збірками, — те, що ти свідомо змінив.

3. Історія змін

Скрипт — це текст. Текст можна порівняти з учорашнім, показати вчителю, надіслати однокласнику. «Я підняв бітрейт музики зі 128 до 192» — це один змінений рядок, який видно. Те саме, зроблене мишкою у відеоредакторі, не видно ніде: ні тобі, ні перевірці.

А ще текст можна покласти у сховище, яке саме пам'ятає всі попередні версії файлу. Таке сховище в нас є — воно зветься Gitea, і ти сядеш за нього у 8-й темі. Сьогодні воно не потрібне: досить того, що твій монтаж узагалі став текстом.

Побічний ефект, який виявиться найважливішим Скрипт — це ще й документація. Через півроку ти не пам'ятатимеш, який фільтр масштабував панелі. Але build.sh пам'ятатиме, і в ньому будуть твої власні коментарі — рядки, що починаються з #.
Питання

Ти вже зібрав трейлер, а потім помітив, що третя панель — не та, і замінив файл p3.png на новий. Що робиш?

Крок 3

З чого складається build.sh

П'ять блоків у сталому порядку. Порядок не декоративний

1 · Шапка 2 · Змінні 3 · Перевірка входу 4 · Збірка 5 · Звіт #!/usr/bin/env bash · set -euo pipefail · коментар про те, що це за скрипт і що він робить SRC, AUD, OUT, W, H, FPS, DUR — усі шляхи й числа зібрані в одному місці; далі в скрипті — тільки посилання на них чи є ffmpeg; чи всі панелі на місці; чи є музика. Якщо чогось бракує — зрозуміла помилка і вихід ДО того, як щось зіпсовано панелі → кліпи → concat → звук і титр → trailer.mp4. Це те, що ти вже вмієш з 8 класу, тільки записане у файл ffprobe → probe.txt і av.meta.json без цього блоку скрипт мовчки продовжить після першої ж помилки одна правка шляху замість семи без нього ролик збереться з п'яти панелей замість шести — і ніхто не помітить тут живуть команди, які ти вже знаєш числа у звіті не вигадані
Блоки 1 і 3 — це те, чого немає в командах «з пам'яті», і саме вони відрізняють скрипт від списку команд. Блок 5 робить звіт похідним від результату, а не від твоєї пам'яті.

Блок 1: шапка

av/build.sh — початок
#!/usr/bin/env bash # Збірка трейлера до коміксу. Автор: Іван Петренко, 9-Б. # Запуск: bash build.sh (Windows: у Git Bash, не в PowerShell) set -euo pipefail

Перший рядок — «шебанг»: він каже системі, чим виконувати файл. Форма #!/usr/bin/env bash надійніша за #!/bin/bash, бо шукає bash у PATH, а не за жорстко прописаною адресою.

Другий важливий рядокset -euo pipefail. Це три запобіжники в одному:

КлючЩо робитьЩо ловить у монтажі
-eзупиняє скрипт на першій команді, що завершилась помилкою ffmpeg не зміг прочитати панель — далі йти немає сенсу
-uпомилка при звертанні до незаданої змінної одруківка $OTU замість $OUT: інакше файл поїде «в нікуди»
-o pipefailконвеєр вважається невдалим, якщо впала будь-яка ланка, а не лише остання ffprobe … | tail: tail відпрацює «успішно» навіть на порожньому вході
Питання

Учень запустив свій скрипт. Панелі p3.png в теці не було. Але скрипт доробив до кінця і видав trailer.mp4 з п'ятьма панелями замість шести. У терміналі — жодного червоного рядка. Що з цим скриптом не так?

Блок 2: змінні замість повторення шляхів

av/build.sh — змінні
# --- що звідки береться і куди кладеться --- SRC="$HOME/local/comic/images" # панелі з теми 4 AUD="$HOME/local/av" # музика і SFX з уроку 9 OUT="$HOME/local/av/trailer.mp4" # результат, на сервер не їде WEB="$HOME/local/av/upload" # звідси файли підуть по FTP # --- параметри картинки --- W=1280; H=720; FPS=25 DUR=5 # секунд на одну панель PANELS="p1.png p2.png p3.png p4.png p5.png p6.png"

Правило просте: якщо рядок повторюється двічі — це змінна. Шлях до теки панелей зустрічається у скрипті сім разів. Перейменуєш теку — правитимеш один рядок, а не сім, і не забудеш жодного.

Зверни увагу на $HOME замість /home/ivan. Скрипт із $HOME запуститься і в однокласника, і в шкільному кабінеті, і в тебе вдома. Скрипт із твоїм логіном — тільки в тебе.

І на лапки: "$SRC/$f", а не $SRC/$f. Уяви теку з назвою «Мої панелі» — вона цілком реальна. У шляху до неї є пробіл. Без лапок bash розріже такий шлях на два аргументи. І ffmpeg поскаржиться на файл, якого немає.

Питання

У скрипті сім разів написано ~/local/comic/images. Учень перейменував теку на panels, і скрипт перестав працювати. Найнадійніше рішення?

Блок 3: перевірка наявності вхідних файлів

Це найкоротший і найкорисніший блок скрипта. Він відповідає на питання «чи є все, що мені потрібно» до того, як почалася збірка.

av/build.sh — перевірка
# --- 1. чи є інструмент --- command -v ffmpeg >/dev/null || { echo "немає ffmpeg"; exit 1; } command -v ffprobe >/dev/null || { echo "немає ffprobe"; exit 1; } # --- 2. чи є всі панелі --- for f in $PANELS; do [ -f "$SRC/$f" ] || { echo "немає панелі: $SRC/$f"; exit 1; } done # --- 3. чи є музика --- [ -f "$AUD/music.wav" ] || { echo "немає музики: $AUD/music.wav"; exit 1; } echo "вхід на місці"

Конструкція A || { B; exit 1; } читається як «зроби A; якщо не вдалося — скажи B і вийди».

[ -f "шлях" ] перевіряє два факти одразу. Файл існує. І це саме файл, а не тека.

command -v ffmpeg шукає програму в PATH і друкує знайдений шлях. Сам шлях нам не потрібен — потрібне тільки «знайшов чи ні». Тому вивід відправляють у /dev/null.

Чому повідомлення має бути людським Порівняй два варіанти. exit 1 — і чорний екран без пояснень. Або немає панелі: /home/ivan/local/comic/images/p3.png — і ти за секунду бачиш, що переплутав p3.png і p3.PNG (у Linux це два різні файли). Скрипт пишеться для людини, яка втомилася і поспішає, — тобто для тебе за десять хвилин до дзвінка.
Windows: запускати в Git Bash build.sh — це bash-скрипт. У PowerShell він не запуститься: PowerShell 5.1 не розуміє ні set -euo pipefail, ні &&. Відкривай Git Bash (він уже стоїть у класі), переходь у теку і запускай bash build.sh. Автоперевірка на сервері теж проганяє скрипт через bash -n.
Крок 4

Блок збірки — і збирач, який напише його за тебе

Команди ті самі, що у 8 класі. Нове — те, що вони живуть у файлі

Збірка йде у три ходи. Спочатку кожна панель стає окремим кліпом однакового формату. Це потрібно через concat: він склеює лише однакові кліпи. Різна роздільність, різна частота кадрів чи різне співвідношення пікселя — і склейки не буде. Потім кліпи склеюються за списком. І вже до склейки додаються титр і музика.

ХідЩо робитьКлючове місце
4.1панель → кліп на DUR секунд -loop 1 -t "$DUR" перетворює нерухому картинку на відео
4.2складає list.txt рядки виду file '/повний/шлях/clip1.mp4'
4.3склейка + титр + музика → trailer.mp4 -f concat -safe 0, -shortest, -map

Фільтр scale=…:force_original_aspect_ratio=decrease разом із pad вписує будь-яку панель у кадр 16:9. Панель при цьому не спотворюється: вертикальна картинка отримає поля по боках, а не розтягнеться.

setsar=1 вирівнює співвідношення пікселя. Без нього concat лається навіть на кліпи однакового розміру.

У третьому рядку таблиці лишилися ще два ключі. Обидва потрібні саме тому, що ми склеюємо файли за списком.

-safe 0 дозволяє читати з list.txt повні шляхи виду /home/…/clip1.mp4. Без цього ключа ffmpeg із міркувань безпеки бере тільки короткі імена з поточної теки — і зупиняється з помилкою.

-map прямо каже, що з якого файлу брати. У нас два входи: склеєне відео й музика. -map 0:v означає «картинку бери з першого», -map 1:a — «звук бери з другого». Без цих ключів ffmpeg вибирає сам і часто бере не те.

Windows: шлях до шрифту у drawtext У фільтрі drawtext двокрапка — службовий символ, і C:/Windows/Fonts/arialbd.ttf ламає розбір параметрів. У Git Bash пишуть fontfile=C\:/Windows/Fonts/arialbd.ttf — з екранованою двокрапкою. У Linux шлях звичайний: /usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf.
Збирач build.sh

Задай параметри свого трейлера — і сторінка складе повний скрипт із перевірками, коментарями і блоком звіту.

Далі його треба прочитати рядок за рядком і підправити під себе. Чужий скрипт, якого ти не розумієш, на очній здачі не захистиш.

Нижні три перемикачі додають у скрипт по кілька рядків кожен. Ось що вони роблять.

Згасання музики в кінці. Останні дві секунди підкладка плавно стихає, а не обривається на півноті.

Виміряти гучність (LUFS). Скрипт додасть команду, яка порахує, наскільки твій ролик гучний загалом. Міряють це не в тих поділках, що на регуляторі гучності, а в LUFS. Це число враховує, як гучність чує вухо за весь ролик, а не в одну мить. Правило просте: чим ближче до −14 LUFS, тим спокійніше твій трейлер стоятиме поруч із чужими відео й не оглушить глядача.

Кадр-постер poster.jpg. Скрипт вирізає з ролика один кадр і зберігає його окремою картинкою. Це та обкладинка, яку плеєр показує, поки відео ще не запустили. Без неї на місці ролика стоїть чорний прямокутник.

av/build.sh
Що робить останній блок Він знімає числа з готового ролика ffprobe-ом і сам підставляє їх у av.meta.json. Через це розбіжність між звітом і роликом стає неможливою: не тому, що ти уважний, а тому, що числа туди вписує не людина.
Питання

Панелі дають 30 секунд відео, а музична підкладка триває 1 хвилину 20 секунд. Учень прибрав зі скрипта ключ -shortest. Яким вийде ролик?

Крок 5

Субтитри — це доступність, а не прикраса

Хто насправді читає субтитри і чому їх не можна «домалювати потім»

Найпоширеніша помилка в думці про субтитри звучить так: «у мене ролик українською, всі почують, субтитри не потрібні». Порахуймо, кому вони потрібні насправді.

ХтоСитуаціяБез субтитрів
Глухі та слабочуючідивляться будь-де ролик для них не існує — це не «гірше», це нуль
Будь-хто в шуміметро, коридор школи, вулиця чути музику, не чути слів
Будь-хто без звукустрічка соцмережі, урок, ніч удома дивиться перші 3 секунди й гортає далі
Хто вчить мовуіноземець, молодший школяр на слух втрачає половину слів
Пошук і роботіндексація, автопереклад текст ролика невидимий: у відео нема чого шукати

Є міжнародний набір правил доступності — WCAG 2.1. У ньому субтитри до записаного відео стоять у критерії 1.2.2 Captions (Prerecorded). Це рівень A — найнижчий поріг. Сторінку без нього взагалі не вважають доступною. Отже, субтитри — не «бажано», а «мінімум».

І практичний бік: субтитри неможливо чесно «домалювати потім», якщо репліки не сплановані. Тому їх пишуть на тому самому таймлайні, на якому розкладені панелі.

Трейлер, 30,00 с · 1280×720 · 25 кадрів/с відео p1p2 p3p4 p5p6 титр drawtext, 0–3 с — вписаний у картинку назавжди музика afade=t=out:st=28:d=2 субтитри 12 34 5 окремий файл trailer.vtt — його можна виправити, не чіпаючи відео 0 с5 1015 2025 30 репліки не зобов'язані збігатися з межами панелей — вони йдуть за змістом
Титр і субтитри — різні речі. Титр drawtext впечений у пікселі: щоб його виправити, ролик треба перезбирати. Субтитри лежать поруч у текстовому файлі: помилку в них виправляють за десять секунд, а глядач може їх вимкнути.
Питання

Однокласник каже: «Субтитри не потрібні — у нас у класі всі чують, а на екрані вони тільки заважають». Що відповісти по суті?

Крок 6

Як влаштований файл .vtt

Заголовок, порожній рядок, репліки. Усе — звичайний текст у UTF-8

av/trailer.vtt
WEBVTT 1 00:00:01.000 --> 00:00:04.200 Місто спало вже третю добу. 2 00:00:05.000 --> 00:00:08.500 — Хто вимкнув сонце? — Ніхто. Воно саме. 3 00:00:10.000 --> 00:00:13.000 Ліфт зупинився між поверхами.
WEBVTT обов'язковий перший рядок файлу без нього браузер не читає файл узагалі 2 ідентифікатор репліки — не обов'язковий, але з ним легше говорити «помилка в репліці 2» 00:00:05.000 --> 00:00:08.500 рівно один пробіл з кожного боку стрілки поява · год:хв:сек.мілісекунди зникнення · крапка, а не кома (кома — це SRT) — Хто вимкнув сонце? — Ніхто. Воно саме. максимум 2 рядки, до ~40 символів кожен перенос рядка робиш ти, а не браузер порожній рядок — кінець репліки. Забудеш — наступна репліка приклеїться до цієї як текст
Порожній рядок у WebVTT — не оформлення, а синтаксис: саме він відділяє одну репліку від наступної. Найчастіша помилка новачка — злиплі репліки через забутий порожній рядок.

VTT чи SRT

SRT старший і поширеніший у відеоплеєрах на комп'ютері. Для вебу придатний лише WebVTT: HTML-елемент <track> за специфікацією читає тільки його.

ОзнакаWebVTT (.vtt)SubRip (.srt)
Перший рядокWEBVTT обов'язковийнемає заголовка
Дробова частина секундкрапка: 00:00:03.500кома: 00:00:03,500
Кодуваннялише UTF-8, за стандартомяке завгодно — звідси «кракозябри»
Номер реплікине обов'язковийобов'язковий
У браузері через <track>працюєне працює
Позиція, вирівнювання, стиліє (line, align, ::cue)немає
MIME-типtext/vttне стандартизований

Як підключити до відео

~/local/av/preview.html — локальний перегляд
<video controls width="720"> <source src="trailer.mp4" type="video/mp4"> <track kind="subtitles" src="trailer.vtt" srclang="uk" label="Українські" default> </video>

Атрибут default вмикає доріжку одразу — саме так учитель дивитиметься твій ролик на очній здачі. Ця сторінка живе локально, поруч із trailer.mp4: на сервер відео не поїде, а от trailer.vtt поїде.

Пастка з file:// Якщо відкрити preview.html подвійним кліком, деякі браузери не покажуть субтитри: доріжку <track> вони вважають «стороннім ресурсом». Лікується локальним сервером в одну команду — python -m http.server 8000 у тій самій теці, далі http://localhost:8000/preview.html.
Питання

Учень зробив субтитри у програмі, яка зберігає .srt, і підключив їх: <track src="trailer.srt" srclang="uk" default>. У браузері субтитрів немає, помилок теж. Що відбувається?

Правила, за якими субтитр можна прочитати

Це не смак, а виміряні речі. Ось галузеві орієнтири (Netflix, BBC — посилання в «Джерелах»):

ПравилоЗначенняЧому саме так
Рядків у репліціне більше 2 третій рядок закриває кадр і відриває око від картинки
Символів у рядку~40 (Netflix 42, BBC 37) довший рядок око «сканує» замість читати
Швидкість читання≤ 17 симв./с (дорослі), 13 (діти) верхня межа, за якою глядач не встигає
Мінімальний показ5/6 с ≈ 0,83 с коротший блимає й дратує навіть на одному слові
Максимальний показ7 с довше глядач починає перечитувати той самий рядок

Із швидкості читання виводиться проста формула мінімальної тривалості репліки: час ≥ кількість символів ÷ 17, але не менше 0,83 с. Репліка на 51 символ вимагає щонайменше 3 секунди на екрані.

Питання

У репліці три рядки по 55 символів, показ — 1,2 секунди. Скільки правил порушено?

Питання

Репліка 2 закінчується о 00:00:09.000, а репліка 3 починається о 00:00:08.000. Що побачить глядач?

Питання

Учитель каже: «Субтитри з'являються приблизно на секунду раніше за репліку». Де саме в файлі шукати помилку?

Крок 7

Редактор субтитрів

Розстав репліки на таймлайні, а сторінка перевірить їх за правилами й видасть готовий trailer.vtt

Правила з попереднього кроку легко переказати і легко порушити. Тут вони перетворені на перевірки.

Щойно репліка стає нечитабельною, її блок на доріжці червоніє. А внизу з'являється пояснення, що саме не так.

Редактор і симулятор показу
    00:00.00 / 00:30.00
    Це не відео, а симуляція показу: біжить час, під ним з'являється репліка, яка має бути на екрані саме зараз.

    Готовий файл — скопіюй і збережи як trailer.vtt у кодуванні UTF-8:

    av/trailer.vtt
    Що саме перевіряє редактор Дев'ять перевірок. Кожна ловить помилку, яку на очній здачі видно за десять секунд.
    • Порожній текст репліки. Час зайнято, а в кадрі нічого. Глядач вирішує, що субтитри зламані.
    • Кінець раніший або рівний початку. Такий блок плеєр не покаже взагалі: показувати нема коли.
    • Перекриття сусідніх реплік. Дві фрази виїжджають на екран одночасно й затуляють одна одну.
    • Більше двох рядків. Три рядки з'їдають третину кадру. Глядач дивиться вже не ролик, а текст.
    • Рядок довший за 42 символи. На телефоні такий рядок або стискається до нечитабельного, або переноситься сам — і рядків знову стає три.
    • Показ коротший за символи ÷ швидкість (але не менш ніж 0,83 с). Фраза встигає блимнути, а прочитати її не встигає ніхто.
    • Показ довший за 7 с. Репліку вже прочитали разів зо три, і вона починає дратувати.
    • Вихід за тривалість ролика. Субтитр стоїть на секунді, якої в ролику немає. Його не побачить ніхто й ніколи.
    • Надто довга «тиша» між репліками. Велика діра майже завжди означає, що ти забув озвучити шматок ролика.
    Кодування і кінці рядків WebVTT за стандартом читається як UTF-8 — інших варіантів немає. Якщо збережеш файл у Windows-1251, українські літери перетворяться на символи запитання просто в кадрі. У «Блокноті» перевір «Кодування → UTF-8», у VS Code — правий нижній кут вікна.
    Питання

    Репліка «Ліфт зупинився між поверхами.» — це 29 символів. Ти поставив їй показ на рівно 1 секунду, і редактор підсвітив рядок червоним. Скільки часу їй потрібно щонайменше?

    Крок 8

    Звіт: probe.txt і av.meta.json

    Паспорт ролика, який неможливо підробити, не переробивши ролик

    Учитель не побачить твій trailer.mp4 на сервері — його там не буде. Замість відео на сервер їде його паспорт: сирий вивід ffprobe і той самий набір чисел у машиночитному вигляді.

    Джерела 6 панелей · p1…p6.png music.wav (з уроку 9) 3 SFX · sfx.json шрифт для титру build.sh перевірка → збірка → звіт trailer.mp4 · 30,00 с · 1280×720 · 25 fps probe.txt — сирий вивід ffprobe av.meta.json — ті самі числа машиночитно trailer.vtt + сам build.sh ↑ усе це живе тільки на твоєму комп'ютері, у ~/local/ ↓ по FTP на сервер їде тільки текст → ~/www/av/ build.sh trailer.vtt probe.txt av.meta.json trailer.mp4 сервер відхилить автоматично
    Ліворуч — те, що ти зробив на попередніх уроках. Посередині — єдина команда. Праворуч — ролик і три текстові супутники. Червона межа показує, що саме перетинає мережу, а що ні.

    probe.txt — і пастка з порожнім файлом

    ffprobe друкує опис доріжок не в стандартний вивід, а в потік помилок (stderr) — так історично склалося в усьому наборі ffmpeg. Тому звичайне > probe.txt дає порожній файл. Потрібне перенаправлення обох потоків.

    bash · Git Bash · macOS · Linux
    $ ffprobe -hide_banner trailer.mp4 > probe.txt 2>&1 (на екрані нічого — усе пішло у файл)
    PowerShell 5.1 (Windows)
    $ ffprobe -hide_banner trailer.mp4 2>&1 | Out-File -Encoding utf8 probe.txt
    Чому в PowerShell не можна просто > Windows PowerShell 5.1 у перенаправленні > пише файл у UTF-16. Такий probe.txt відкривається в редакторі нормально, але чекер на сервері читає його як UTF-8 і бачить сміття — і ти отримуєш незрозуміле «файл не містить h264», хоча він його містить. Тому в PowerShell завжди | Out-File -Encoding utf8.
    Дзеркальна пастка: -Encoding utf8 додає BOM Той самий ключ, який рятує probe.txt, ламає list.txt для ffmpeg -f concat: три службові байти на початку приклеюються до слова file, і ffmpeg не розуміє перший рядок. Для list.txt у PowerShell потрібне -Encoding ascii. Правило: дивись, хто читатиме файл — чекер на сервері чи інструмент на твоїй машині.
    probe.txt — так виглядає паспорт нашого прикладу
    Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'trailer.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf60.16.100 Duration: 00:00:30.00, start: 0.000000, bitrate: 1043 kb/s Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive), 1280x720 [SAR 1:1 DAR 16:9], 846 kb/s, 25 fps, 25 tbr, 12800 tbn (default) Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 192 kb/s (default)

    Це приклад виводу, а не твої числа: у тебе будуть свої. Але сходитися вони мають так само — 846 + 192 ≈ 1043 кбіт/с разом зі службовими даними контейнера.

    Питання

    Учень виконав ffprobe -hide_banner trailer.mp4 > probe.txt у Git Bash. Ролик відкривається і грає, а probe.txt — нульового розміру. Що сталося?

    Питання

    Учениця працює у PowerShell. probe.txt у «Блокноті» виглядає ідеально, а чекер каже «файл не містить h264». Найімовірніша причина?

    av.meta.json — що з чого зроблено

    probe.txt читає людина, av.meta.json — програма. Це підсумковий звіт про роботу: скільки триває, з чого зібрано, чим зроблено.

    av/av.meta.json
    { "duration": 30.0, "resolution": "1280x720", "fps": 25, "video_codec": "h264", "audio_codec": "aac", "music_source": "strudel", "code_file": "music.strudel", "sfx_count": 3, "panels": 6, "sources": ["p1.png","p2.png","p3.png","p4.png","p5.png","p6.png"], "subtitles": "trailer.vtt", "built_with": "build.sh", "built_at": "2026-09-02T11:40:05+03:00" }
    ПолеЗвідки беретьсяЩо доводить
    durationffprobe … format=duration ролик справді на 20–40 с, а не «приблизно»
    resolution, fpsзмінні W, H, FPS зі скрипта параметри збірки, а не побажання
    video_codec, audio_codecffprobe … stream=codec_name усередині контейнера справді H.264 і AAC
    sourcesзмінна PANELS ролик зібрано з твоїх панелей теми 4, а не з чужих
    music_source, code_fileвписуєш сам музика — твоя, написана кодом на уроці 9

    Ключова ідея: усе, що можна виміряти, вимірює скрипт. Руками ти вписуєш лише те, чого ffprobe знати не може, — звідки взялася музика і скільки в ролику ефектів.

    Питання

    У av.meta.json написано "duration": 35, а в probe.txtDuration: 00:00:30.00. Учень каже: «ну майже». Що буде на перевірці і як цього уникнути назавжди?

    Крок 9

    Практика: від панелей до чотирьох текстових файлів

    Кроки 1—11 — у твоєму терміналі й редакторі, крок 12 — по FTP, крок 13 — для рівня «+». Галочки зберігаються, сторінку можна закрити.

    Межа, яку не можна перейти Усе, що з'являється в ~/local/av/trailer.mp4, проміжні clip1…clip6.mp4, list.txt — лишається в тебе. На сервер піднімаються рівно чотири текстові файли: build.sh, trailer.vtt, probe.txt, av.meta.json. Спроба залити .mp4 нічим не закінчиться: FTP-приймальня його просто не прийме.
    Крок 10

    Автоперевірка

    Чекер не дивиться відео. Він звіряє твої чотири текстові файли один з одним — і вигадані числа не сходяться. Спроби не обмежені.

    Демонстраційний режим: результат згенеровано для показу. На сервері ця кнопка викликає POST /api/check, який запускає check 10 від імені учня.

    Що вчитель дивиться на твоєму екрані

    Найчастіша причина «не зараховано» на цьому уроці Ролик змонтовано мишкою у відеоредакторі, а build.sh дописано «щоб було». Це видно за півхвилини: скрипт або не запускається, або збирає щось інше, ніж те, що на екрані.
    Крок 11

    Шкала виконання

    Це те, що бачить учитель, коли виставляє оцінку.

    СкладникВагаРезультат
    Виконано
    0%
    Рекомендований бал за 12-бальною

    Чотири речення, які варто запам'ятати

    Де найчастіше помиляються

    Домашнє завдання

    Додай у build.sh згасання звуку в кінці (afade=t=out) і перезбери ролик. Онови після перезбірки probe.txt і av.meta.json — обидва мають оновитися самі, бо їх пише скрипт.

    Рівень «+»: знайди в ролику місце, де тиша довша за 8 секунд. Додай туди четверту репліку субтитрів. І поясни одним реченням, чому глядачеві там потрібен текст.

    Джерела

    Звідки взяті команди, формат і числа

    Усі правила на цій сторінці — зі стандартів, документації і галузевих настанов. Перевіряти дозволено й корисно.

    Повний список із поясненнями, що звідки взято, — у файлі urok-10-джерела.md поруч із цією сторінкою.