media.jsonТи згенеруєш трек і відеофрагмент — і жоден із цих файлів не потрапить на сервер. На сервер поїде те, що дає їм цінність через рік: опис, транскрипт і маніфест походження.
Згенерувати щось сьогодні вміє будь-хто: три слова в поле — і за хвилину готовий трек. Складне починається пізніше. Через рік хтось питає: це зробив ти? А сам файл мовчить. У ньому немає ні автора, ні інструменту, ні згадки про людей у кадрі.
Відповідає маніфест походження — текстовий файл поруч із роботою. У нього ти записуєш усе під час роботи. Сьогоднішній урок про те, як написати його так, щоб він щось доводив.
І друга, дуже приземлена частина: вага. Медіа важить у сотні разів більше за текст. Саме тому воно взагалі не їде на спільний сервер. Ти порахуєш це сам, а не повіриш на слово.
Слова маніфест походження, бітрейт, C2PA і BOM поки нічого не означають. Дійдемо до кожного — після прикладу.
| Файл | Що в ньому |
|---|---|
~/www/media/index.html |
сторінка-опис: назви, тривалості, підписи, транскрипт — без жодного вбудованого медіафайлу |
~/www/media/media.json |
маніфест походження: для кожного твору file, tool, model, prompt, license, consent, duration_sec, size_mb |
~/www/media/transcript.md |
текст пісні й покадровий опис відео |
~/media-local/ |
лишається в тебе на комп'ютері: сам .mp3, сам .mp4, чернетки, невдалі дублі |
~/www/media/. Не шукай lesson-07:
тема четверта, уроків у ній два, тека одна — наступного уроку ти доповниш
цю саму.| Етап | Хв | Що робиш |
|---|---|---|
| Межа «локально / сервер» | 10 | розбираєш, що куди їде і чому |
| Вага медіа | 15 | рахуєш у калькуляторі, звіряєш із ffprobe |
| Промпт як специфікація | 20 | генеруєш трек 30—90 с і відео 10—30 с |
| Маніфест походження | 20 | поля, ланцюг, конструктор media.json |
| Ліцензії вихідних матеріалів | 15 | дерево рішень і атрибуція |
| C2PA і транскрипт | 20 | чому метадані зникають і що лишається текстом |
| Здача й автоперевірка | 20 | FTP, чеклист до зеленого, показ учителю очно |
Правило модуля не «не завантажуй великі файли». Воно жорсткіше: медіафайлів на сервері немає взагалі, і сервер стежить за цим сам
Уся генерація, стиснення, монтаж і перегляд відбуваються у тебе на
комп'ютері, у теці ~/media-local/. VPS нічого не рендерить,
не перекодовує і не роздає відео. Він публікує текст: розмітку, JSON
і Markdown.
Учитель дивиться й слухає твої роботи очно, з твого екрана.
Там же він звіряє справжню тривалість і розмір із тим, що ти написав
у media.json. Тому прикрашати числа в маніфесті безглуздо:
поруч буде відкритий ffprobe.
ffprobe і ls -lh у кроці 4..mp4 .mov .avi .mkv .webm .mp3 .wav .flac і будь-який
файл понад 2 МБ. Відмова приходить ще на FTP: файл не з'явиться в кабінеті,
а клієнт покаже помилку. Якщо він усе-таки туди потрапив, роботу не приймуть —
навіть коли сторінка бездоганна. Перевірка «на сервері немає медіафайлів»
блокуюча, у списку критеріїв вона зветься no_media.
Прибереш файл — заллєш ще раз, спроби не обмежені.Однокласник каже: «Я стиснув відео до 1.8 МБ. Це менше за ліміт,
отже заллю його в ~/www/media/ — хай учитель дивиться
просто з сайту». Що йому відповісти?
Одна формула, яка пояснює все правило модуля: вага = бітрейт × тривалість ÷ 8
Бітрейт — це скільки біт даних припадає на секунду. Помножили на секунди, поділили на 8 (бо в байті 8 біт) — отримали байти. Усе. Ні кодек, ні «якість» не роблять тут магії: вони лише вирішують, який бітрейт потрібен, щоб картинка не розсипалася.
Візьмімо бітрейти, які YouTube рекомендує для завантаження. Для 1080p при 30 кадрах — 8 Мбіт/с. Для 720p — 5 Мбіт/с. Для 4K при 30 кадрах — від 35 до 45 Мбіт/с. Підставмо хвилину.
| Що це | Бітрейт | 1 хвилина | 20 секунд |
|---|---|---|---|
| Відео 4K, 30 к/с | 40 Мбіт/с | 300 МБ | 100 МБ |
| Відео 1080p, 30 к/с | 8 Мбіт/с | 60 МБ | 20 МБ |
| Відео 720p, 30 к/с | 5 Мбіт/с | 37.5 МБ | 12.5 МБ |
| Аудіо WAV 44.1 кГц / 16 біт / стерео | 1411 кбіт/с | 10.6 МБ | 3.5 МБ |
| Аудіо MP3 192 кбіт/с | 192 кбіт/с | 1.44 МБ | 0.48 МБ |
| Уся текстова частина твоєї сторінки | — | 0.03 МБ | — |
Останній рядок і є суть. Три текстові файли роботи разом важать близько 30 КБ. Хвилина відео 1080p — 60 000 КБ. Різниця у дві тисячі разів. Побачити її на одній картинці майже неможливо. Саме тому нижче вона намальована чесно, без «умовного масштабу».
Звідси беруться квоти. Квота учня на цьому сервері — 250 МБ. У текстових файлах це тисячі сторінок і десятки уроків. У відео 1080p це 4 хвилини 10 секунд, і місце скінчилося — разом із усіма наступними уроками модуля.
Ти зняв 25-секундний ролик у 4K. Треба вкластися в 20 МБ: саме таку
межу на розмір файлу ставить перевірка limits.
Що дасть найбільший ефект першим кроком?
Покрути повзунки й подивись, де саме зникає квота. Усі числа рахуються тут, у браузері, за формулою з кроку 3
= 19.1 МіБ у Провіднику Windows
Ціни в останніх двох рядках узяті з прайсу Amazon S3. Зберігання — $0.023 за ГБ на місяць, віддача в інтернет — $0.09 за ГБ у першому діапазоні. Наш VPS живе не в S3, тож це порядок величини, а не рахунок школи.
Але порядок показовий. За медіа платять не один раз при завантаженні. Платять щомісяця за зберігання і щоразу за кожен перегляд.
І головне: справжня причина правила модуля — не долари. Це одна спільна машина на три класи. Твої 20 МБ помножені на 60+ акаунтів і на 16 уроків — це вже гігабайти, які ніхто не дивиться після здачі.
ffprobe … > probe.txt у Windows PowerShell 5.1
запише файл у UTF-16, і будь-який чекер зламається. Пиши
ffprobe … | Out-File -Encoding utf8 probe.txt.
По-друге, && у PowerShell 5.1 не працює взагалі: замість
mkdir media-local && cd media-local пиши
mkdir media-local; if ($?) { cd media-local }.У класі 24 учні. Кожен здає 20-секундне відео 1080p. Учитель пропонує «просто складати їх на сервер, місця ж вистачить». Порахуй у калькуляторі й скажи, що станеться з квотою 250 МБ.
У 8 класі ти розбирав, як модель перетворює шум на зображення. Сьогодні промпт цікавить нас з іншого боку: як запис, за яким роботу можна повторити й перевірити
Різниця в одному слові. Промпт «зроби пісню про школу» дає результат — але нічого не доводить. За ним не відтворити ні настрою, ні аранжування, ні навіть мови вокалу. Промпт із параметрами — це технічне завдання: за ним і ти сам, і будь-хто інший отримає щось дуже схоже.
| Блок | Що вказуєш | Приклад |
|---|---|---|
| Жанр | стиль, епоха, сцена | synth-pop, вплив 80-х |
| Настрій | емоція, енергія | світлий, трохи ностальгійний |
| Інструменти | що звучить, що веде | аналоговий синт, електробас, живі барабани |
| Темп і тональність | BPM, мажор/мінор | 112 BPM, мінор |
| Вокал | є/немає, стать, мова, манера | жіночий вокал українською, без надриву |
| Структура і довжина | куплет—приспів, скільки секунд | інтро 8 с, куплет, приспів, аутро; разом 60 с |
| Блок | Що вказуєш | Приклад |
|---|---|---|
| Сцена | місце, час доби, погода | шкільний коридор, ранок, сонце у вікнах |
| Суб'єкт | хто або що в кадрі | паперовий літачок |
| Дія | що відбувається за 10—30 с | повільно летить повз шафки й зникає за поворотом |
| Камера | план, рух, оптика | середній план, плавний трекінг збоку |
| Світло і колір | джерело, палітра | тепле контрове світло, теплі відтінки |
| Стиль | референс не на людину, а на техніку | документальне відео, зернистість плівки |
| Формат | тривалість, співвідношення сторін | 15 с, 16:9 |
consent.2026-09-02 14:10 | Suno v4.5 | спроба 1 synth-pop 80-х, світлий ностальгійний настрій, аналоговий синт, електробас, живі барабани, 112 BPM, мінор, жіночий вокал українською, структура: інтро 8 с / куплет / приспів / аутро, разом близько 60 с. Без: реп-вставок, англійського вокалу, гітарного дисторшну. → дубль 1: занадто швидко, вокал перекриває бас 2026-09-02 14:19 | Suno v4.5 | спроба 2 (той самий промпт, 104 BPM) → дубль 3 — беремо. Далі обрізка й нормалізація гучності локально.
Через рік учитель просить: «Зроби ще один трек у тому самому настрої,
що й торішній». У тебе збережено файл track.mp3
і рядок у маніфесті "prompt": "пісня про школу".
Що саме ти вже не відтвориш?
Походження (provenance) — це відповідь на питання «звідки взявся цей файл і чиї сліди на ньому». Не одне поле, а ланцюг
Уяви картину в музеї. Поруч висить табличка: хто автор, у якому році написав, у кого картина зберігалася до музею. Саме така табличка й зветься походженням — англійською provenance.
У файлу такої таблички немає. clip.mp4 — це 20 мегабайтів
і більше нічого. Ні автора, ні інструменту, ні згоди людей у кадрі.
Табличку доводиться писати поруч, окремим файлом.
| Поле | Що відповідає | Чому без нього погано |
|---|---|---|
tool + model |
чим і якою версією зроблено | «AI» — це не інструмент; без версії результат не повторити |
prompt |
що саме ти попросив, дослівно | переказ промпта своїми словами не відтворює нічого |
created |
дата генерації | моделі оновлюють мовчки; без дати незрозуміло, яка це була версія |
human / ai |
що зробила людина, що модель | це і є відповідь на «а ти взагалі щось робив?» |
sources[] |
вихідні матеріали та їхні ліцензії | чужий семпл без ліцензії робить незаконною всю роботу |
license |
на яких умовах твій результат можна брати | без цього ніхто не знає, чи можна тебе цитувати |
consent |
згода людей, чий голос або обличчя звучить | порожнє поле = порушення, навіть якщо все інше бездоганне |
duration_sec, size_mb |
фактичні тривалість і розмір | перевіряються ffprobe за пів хвилини — брехня видно одразу |
Тому що після роботи його нема з чого писати. Через два дні ти вже не пам'ятаєш точного формулювання промпта. Не пам'ятаєш, що дубль був сьомий. Не пам'ятаєш, звідки взявся фоновий шум із чужого відео.
Лишається один варіант — вигадати правдоподібне. А вигаданий маніфест гірший за відсутній: він виглядає як доказ, але доказом не є.
Через рік тебе питають, чи цей ролик робив саме ти. Файл
clip.mp4 у тебе є. Що з твого проєкту це доведе?
media.jsonВерхній рівень — масив. Один елемент масиву — один твір. Усередині елемента є прості поля, а є вкладені
jq. Блокуючий критерій
provenance дивиться рівно три поля в кожному записі:
tool, model і prompt довший
за 10 символів. Решта полів робить маніфест корисним для людини.[
{
"file": "track.mp3",
"type": "audio",
"title": "Коридор о сьомій",
"tool": "Suno",
"model": "v4.5",
"prompt": "synth-pop 80-х, світлий ностальгійний настрій, аналоговий синт, електробас, живі барабани, 104 BPM, мінор, жіночий вокал українською, інтро 8 с / куплет / приспів / аутро, разом близько 60 с",
"seed": "a91f0c",
"created": "2026-09-02",
"duration_sec": 62,
"size_mb": 1.5,
"human": "написав промпт і три ітерації, обрав дубль 3, обрізав хвіст і вирівняв гучність у Audacity",
"ai": "згенерувала мелодію, аранжування й вокал за промптом",
"sources": [],
"license": "CC BY 4.0",
"consent": "n/a — реальних людей у записі немає"
},
{
"file": "clip.mp4",
"type": "video",
"title": "Літачок",
"tool": "Runway",
"model": "Gen-3 Alpha",
"prompt": "шкільний коридор уранці, сонце у вікнах, паперовий літачок повільно летить повз шафки й зникає за поворотом, середній план, плавний трекінг збоку, тепле контрове світло, зернистість плівки, 15 с, 16:9",
"seed": "",
"created": "2026-09-02",
"duration_sec": 15,
"size_mb": 12.4,
"human": "написав промпт, відібрав дубль 2 з п'яти, обрізав перші 3 с і стиснув ffmpeg до 12.4 МБ",
"ai": "згенерувала всі 5 дублів відео",
"sources": [
{
"title": "School Hallway Ambience — назва як на сторінці джерела",
"author": "нік автора на Freesound",
"url": "https://freesound.org/people/<автор>/sounds/<id>/",
"license": "CC BY 4.0"
}
],
"license": "CC BY-SA 4.0",
"consent": "n/a — облич у кадрі немає"
}
]
Це приклад-зразок: назви, дати, seed і посилання в ньому
ілюстративні. Числа duration_sec і size_mb у
твоєму файлі беруться з ffprobe, а не з цього прикладу.
media.json у PowerShell командою
… | Out-File -Encoding utf8, Windows PowerShell 5.1 допише
на початок файлу невидиму мітку BOM. Файл виглядатиме нормально в редакторі,
але jq і json.load впадуть, і критерій
manifest_valid буде червоним без жодного пояснення.
Правильно так:
[IO.File]::WriteAllText($path, $text, (New-Object Text.UTF8Encoding $false)).
Або просто збережи файл редактором коду у форматі «UTF-8 без BOM».Твій media.json відкривається в редакторі бездоганно,
але чекер каже «маніфест не парситься». Ти впевнений, що JSON валідний.
Що перевіряєш першим?
Заповнюй поля свого справжнього твору. Сторінка перевіряє
повноту, показує, наскільки походження простежуване, і збирає
валідний media.json
[]
Збережи цей текст у файл media.json у кодуванні
UTF-8 без BOM і залий у ~/www/media/. Чекеру потрібні
щонайменше два записи: аудіо і відео.
Учень заповнив усі обов'язкові поля, але написав
"human": "зробив пісню" і "ai": "допомогла".
Автоперевірка це пропустить. Чому маніфест усе одно поганий?
Одне правило, яке заощадить тобі багато нервів: відсутність позначки про ліцензію — це не дозвіл
За замовчуванням будь-який твір захищений авторським правом із моменту створення. Ніякої реєстрації для цього не потрібно. Тому «я не знайшов напису, що не можна» означає рівно протилежне: не можна, поки не сказано, що можна.
| Позначка | Що дозволяє | Що зобов'язує | Годиться для уроку |
|---|---|---|---|
| Власний матеріал | усе | нічого | так, найкращий варіант |
CC0 1.0 | усе, зокрема переробку | нічого; згадати автора — ввічливість | так |
CC BY 4.0 | усе, зокрема переробку | вказати автора, джерело й ліцензію | так |
CC BY-SA 4.0 | усе, зокрема переробку | атрибуція + твій результат теж SA | так, якщо готовий віддати свій твір під SA |
CC BY-NC 4.0 | некомерційне використання | атрибуція; ніякої комерції | так — шкільна робота некомерційна |
CC BY-ND | лише поширення без змін | переробка заборонена | ні — будь-яка генерація на його основі це похідний твір |
| немає позначки | нічого | — | ні |
| трек із YouTube / TikTok, кадр із фільму | нічого | — | ні, навіть «на 5 секунд» |
У маніфесті — структуровано, у полі sources[]. На сторінці —
людським рядком під твором. Ці два записи описують одне й те саме,
і обидва потрібні: перший читає програма, другий — людина.
<p class="credit">Фоновий шум коридору — <a href="https://freesound.org/people/…/sounds/…/">«School Hallway Ambience»</a>, автор <a href="https://freesound.org/people/…/">нік автора</a>, ліцензія <a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a>. Змінено: обрізано до 8 с і приглушено на 12 дБ.</p>
license, а не вгадуй.Ти знайшов ідеальний фоновий звук на сайті, де під ним написано «free download». Ліцензії не вказано ніде. Що робиш?
Індустрія намагається вирішити ту саму задачу технічно — вшити маніфест у сам файл і підписати його криптографічно
Твій media.json лежить поруч із файлом. Розлучити їх
легко: хтось перешле саме відео, а текстовий опис лишиться на сторінці.
Тому камери, редактори й генератори домовилися записувати ту саму історію
всередину файлу — щоб вона їздила разом із ним.
Домовленість оформили як відкритий стандарт. Він зветься C2PA: Coalition for Content Provenance and Authenticity, «коаліція за походження й достовірність вмісту». А позначку, яку в стрічці чи в редакторі бачить звичайний користувач, назвали Content Credentials — «посвідчення вмісту».
Логіка та сама, що в твоєму media.json, тільки веде запис
не людина, а програма. Розберемо по кроках.
Спершу. Кожна окрема дія над файлом — зйомка, генерація, обрізка, корекція кольору — лягає в короткий запис: що зробили, коли, чим. Такий запис зветься твердженням, англійською assertion.
Потім. Усі твердження про цей файл складають в одну пачку. Пачка зветься claim, тобто «заява»: програма ніби заявляє «ось усе, що я знаю про походження цього файлу».
Наостанок. Пачку запечатують цифровим підписом. Печатку ставить той, хто робив дію: камера, редактор, генератор. Працює це як сургуч на конверті. Прочитати вміст може будь-хто, а от змінити хоч один символ і залишити печатку цілою — ні.
Запечатана пачка й зветься маніфестом. Вона лежить у службовій частині файлу, поруч із самим відео чи звуком.
Це вже не експеримент: Content Credentials вбудовують OpenAI, Google, Adobe і Microsoft, а платформи вчаться їх показувати. Але є проблема, через яку твій текстовий маніфест не стає зайвим.
Тобі надсилають відео без жодних Content Credentials і кажуть: «Позначки немає — отже, це не AI, це справжнє». У чому помилка?
На твоєму сервері медіа немає взагалі. Отже, транскрипт — це не додаток до роботи, а сама робота
Текстова альтернатива робить одразу чотири різні речі, і кожної з них достатньо, щоб її писати:
| Навіщо | Хто це відчуває |
|---|---|
| Доступність | людина, яка не чує; людина зі скрінрідером; будь-хто в шумному автобусі без навушників |
| Пошук | усередині відео не шукає ніхто: ні пошуковик, ні grep, ні ти сам через півроку |
| Перевірка | учитель звіряє, чи транскрипт відповідає тому, що справді звучить і показано |
| Ця конкретна умова | на сервері немає файлу — без транскрипта на сторінці порожнє місце |
Для аудіо — повний текст із позначками структури. Для відео — покадровий опис із мітками часу: що в кадрі, що чути, що з'являється як текст. Мітка часу потрібна, щоб опис можна було звірити з файлом.
# Транскрипти ## track.mp3 — «Коридор о сьомій» · 62 с **[0:00—0:08] Інтро.** Інструментальне, синтезатор і бас, без вокалу. **[0:08—0:26] Куплет 1.** Ще темно за вікном, а світло вже горить, і в коридорі чути, як прокинувся наш світ. **[0:26—0:44] Приспів.** … ## clip.mp4 — «Літачок» · 15 с, без звуку | Час | Що в кадрі | Звук | |---|---|---| | 0:00—0:04 | порожній шкільний коридор уранці, сонячні плями на підлозі | тиша | | 0:04—0:10 | паперовий літачок влітає в кадр ліворуч, летить повз ряд шафок | тиша | | 0:10—0:15 | літачок зникає за поворотом, камера сповільнюється | тиша | **Артефакти генерації, які видно:** на 0:07 напис на шафці нечитабельний, на 0:12 тінь літачка не збігається з напрямком світла.
Учень написав у transcript.md: «Відео про літачок у коридорі,
15 секунд, дуже атмосферне». Формально транскрипт є.
Чому перевірка поки його не пропустить і чого тут бракує?
Кроки 1—11 робиш у себе на комп'ютері. На сервер їде тільки крок 12. Галочки зберігаються
.mp3, .mp4, сирі дублі, чернетки, скріншоти —
усе живе в тебе на комп'ютері в ~/media-local/ і
показується вчителю очно. На сервер ідуть рівно три файли:
index.html, media.json, transcript.md.
У ~/www/media/ не має бути жодного файлу з іншим розширенням,
ніж .html .json .md .css .js.Чекер не слухає твій трек. Він парсить media.json,
звіряє межі тривалості й розміру і перелічує розширення в теці.
Спроби не обмежені
Демонстраційний режим: результат згенеровано для показу. На сервері
ця кнопка викликає POST /api/check, який запускає
/opt/lessons/07/check.sh від імені учня.
ffprobe і ls -lh та звірити
фактичні тривалість і розмір із тим, що написано в media.json;prompts.txt або історію чату з генератором
і звіряє з полем prompt у маніфесті;Це те, що бачить учитель, коли виставляє оцінку.
| Складник | Вага | Результат |
|---|
.mp4 у ~/www/media/ — файл не доїде,
а якщо доїде, це блокуючий провал no_media;"prompt": "зроби пісню" — формально поле є, походження немає;"model": "AI" — це не версія моделі, критерій provenance червоний;ffprobe показує 24 с там, де написано 15;media.json збережено з BOM — jq падає, і причина невидима;Дописати в transcript.md покадровий опис свого відео.
Щонайменше один рядок на кожні 3 секунди. У рядку — що в кадрі, що чути
і які помилки генерації видно.
Мета проста. Людина, яка не побачить файлу ніколи, має зрозуміти роботу повністю.
Другим абзацом додай у media.json поле "verify" —
для кожного запису. Уяви: через рік файл спливає десь без твого імені.
Одним реченням напиши, чим саме ти доведеш авторство.
Усі розрахунки на цій сторінці робить твій браузер за формулою з кроку 3 — їх можна перевірити калькулятором
consent.
zakon.rada.gov.uaffprobe — ключі -show_entries
і -of, якими знімаються тривалість, розмір і бітрейт.
ffmpeg.org/ffprobe.htmljq — фільтри all, length
і код повернення -e, якими працює чекер.
jqlang.github.io/jq/manualOut-File -Encoding utf8
у Windows PowerShell 5.1 додає мітку BOM.
learn.microsoft.comПовний список із поясненнями, що звідки взято, —
у файлі urok-07-джерела.md поруч із цією сторінкою.