Модуль I · Тема 5 «Мультимедіа: відео» · урок 2 з 2 · 120 хвилин
Мета. Зібрати ролик приблизно на 10 секунд — без відеоредактора. Вирізати кілька фрагментів із джерела. Склеїти їх. Накласти титр. Усе це — самими командами. І записати монтаж так, щоб його можна було повторити з нуля.
Слова concat, drawtext і «монтажний
лист» поки нічого не означають — розберемо їх по черзі.
| Етап | Хв | Що робимо |
|---|---|---|
| Розминка | 5 | Дивимось готовий 10-секундний ролик і розбираємо його на операції |
| Обрізання і склейка | 15 | -ss, -t, список файлів і -f concat |
| Практика 1 — обов'язкова | 30 | Три фрагменти → merged.mp4, перевірка тривалості |
| Перерва | 10 | — |
| Практика 2 | 25 | Титр drawtext — обов'язково; fade — рівень «+» |
| Практика 3 | 15 | cmd.txt, probe.txt, report.csv, монтажний лист |
| Очна здача медіа | 15 | Учитель дивиться final.mp4 на твоєму екрані |
| Підсумок і ДЗ | 5 | Куди й з якими параметрами експортувати |
| Разом | 120 |
ffmpeg сьогодні не запускається на сервері жодного разу. Усі
команди ти набираєш у терміналі власного комп'ютера (PowerShell або
Terminal), у теці media/lesson-05/. По FTP їдуть рівно чотири легкі
файли: cmd.txt, probe.txt, report.csv і
index.html із монтажним листом. Готовий ролик учитель дивиться
очно, на твоєму екрані — FTP-приймальня .mp4 просто відхилить.drawtext, третя — рядок libx264.
Якщо хоч одна нічого не знайшла, підніми руку.media/lesson-05/ і ~/www/lesson-05/.
Так задумано: нумерація йде за темами, а «Відео» — тема п'ята. Не шукай
lesson-10, її немає.ffmpegОдне правило пояснює 90% помилок: опція діє на той файл, який іде після неї
Команда ffmpeg схожа на довгий рядок без ладу. Насправді порядок
у ній жорсткий, і читають її зліва направо, як речення. Частин п'ять, і кожна
відповідає на своє питання.
Глобальні опції стоять на самому початку. Вони діють на весь запуск,
а не на якийсь один файл. Таких у нас дві: -hide_banner прибирає
зайвий службовий текст, -y дозволяє мовчки перезаписати результат.
Про них є врізка одразу під схемою.
Опції входу кажуть, як читати файл, що стоїть після них. Саме
тут місце для -ss, коли ролик має починатися не з нульової
секунди.
Далі -i і вхідний файл. Це єдиний ключ, який показує
пальцем: ось той файл, який я читаю.
Фільтри й кодеки — це вже про те, що зробити з картинкою. Накласти титр, згасити кінець. І вибрати, чим стискати відео і звук на виході.
Вихідний файл завжди останній, і ключа перед ним немає взагалі.
Що лишилося в кінці рядка — те ffmpeg і запише.
-i і після нього, робить
різні речі. Це не примха: ffmpeg уміє читати кілька входів
одразу й писати кілька виходів, тому кожна опція має «прилипати» до
конкретного файлу.-hide_banner прибирає десяток рядків про версію й конфігурацію
збірки — щоб у виводі було видно саме твої помилки. -y дозволяє
одразу перезаписати вихідний файл. Без нього ffmpeg спитає «файл існує,
перезаписати?» і зупиниться, поки ти не введеш y.Ти написав ffmpeg -i source.mp4 -ss 30 -t 5 part.mp4. Команда
відпрацювала правильно, але думала 40 секунд — хоча вирізала всього 5.
Чому так довго?
-ss, -t, -toТри ключі, якими з довгого джерела дістають потрібні секунди
| Ключ | Що означає | Приклад |
|---|---|---|
-ss | позиція, з якої починати (seek start) | -ss 12 або -ss 00:00:12.5 |
-t | тривалість у секундах — скільки взяти | -t 3 — три секунди |
-to | позиція кінця, а не тривалість | -ss 12 -to 15 — теж три секунди |
-t і -to разом не вживають. Якщо вкажеш обидва,
ffmpeg послухається -t. Обери щось одне і тримайся
його в усіх трьох фрагментах. Інакше через п'ять хвилин сам не згадаєш:
15 — це секунда кінця чи довжина шматка?
-ss ставлять до -iВідео не можна «розгорнути» на потрібній секунді, як книжку. Кадри залежать один від одного. Більшість кадрів зберігає лише різницю з попереднім — це P- і B-кадри з уроку 9. Щоб показати кадр на 30-й секунді, програма шукає найближчий попередній ключовий кадр і розкодовує все від нього.
-ss 30 -i source.mp4 — опція входу: ffmpeg
стрибає по індексу файлу одразу до потрібного місця. Миттєво.-i source.mp4 -ss 30 — опція виходу: файл читається
і декодується з нульової секунди, а перші 30 секунд просто викидаються.
Результат той самий, час — у десятки разів більший.Обрізати можна двома способами. Різниця між ними — як між «вирвати сторінки» і «переписати від руки».
-c copy — без перекодування | перекодування | |
|---|---|---|
| Що робить | переписує вже стиснені дані в новий файл | розтискає кожен кадр і стискає наново |
| Швидкість | частка секунди | секунди й хвилини, кулер шумить |
| Якість | жодних втрат — байти ті самі | трохи гірша: стиснення з втратами повторюється |
| Точність різу | тільки по ключових кадрах — початок «поїде» на 0—2 с | рівно там, де просив |
| Коли брати | вирізати рекламу з середини, склеїти однакові шматки | коли потрібен точний різ або треба зрівняти параметри |
Сьогодні ми ріжемо з перекодуванням. Не заради точності. Заради того, щоб усі три фрагменти вийшли з однаковими параметрами. Це й є умова, за якої спрацює склейка.
| Частина | Навіщо вона тут |
|---|---|
-ss 3 -t 4 | беремо 4 секунди починаючи з третьої |
-s 1280x720 -r 30 | жорстко фіксуємо розмір кадру і fps — щоб у трьох фрагментів вони збіглися |
-c:v libx264 -crf 20 | кодувальник H.264; -crf — якість, менше число = краще й важче |
-preset veryfast | швидкість кодування; на уроці важливіше не чекати |
-c:a aac -b:a 128k -ar 48000 -ac 2 | звук теж однаковий у всіх: кодек, бітрейт, частота, два канали |
Ти вирізав фрагмент командою з -c copy. Просив початок рівно
на 12,0 с — а ролик починається з 10,5 с. Файл не пошкоджений, команда без
помилок. Що сталося?
concatДва різні інструменти з однаковою назвою — і половина проблем саме через це
У ffmpeg є демюксер concat і фільтр
concat. Обидва з'єднують шматки один за одним. Але працюють вони
на різних рівнях і вимагають різного. Плутанина між ними дає більшість скарг
«у мене concat не працює».
демюксер -f concat | фільтр concat= | |
|---|---|---|
| Як задаються шматки | текстовий список файлів list.txt | усі файли через окремі -i |
| Рівень роботи | потік байтів: дані навіть не розтискаються | кадри: усе декодується й кодується наново |
| Перекодування | не потрібне — -c copy | завжди |
| Швидкість на трьох шматках | частка секунди | секунди, з навантаженням на процесор |
| Вимоги до шматків | однакові кодеки, роздільна здатність, fps, параметри звуку | однакова роздільна здатність і формат пікселів; кодеки можуть бути різні |
| Коли брати | шматки вирізані з одного джерела однією командою | джерела різні: телефон + камера + запис екрана |
Нам підходить демюксер. Усі три фрагменти ми щойно вирізали з одного джерела. Шаблон команди був той самий, тож і параметри в них однакові.
Демюксер читає звичайний текстовий файл. Кожен рядок — слово file,
пробіл і ім'я в одинарних лапках. Порядок рядків = порядок у ролику.
Створити його можна будь-яким редактором. У терміналі — так:
ascii, а не utf8
Windows PowerShell 5.1 з ключем -Encoding utf8 ставить на початок
файлу службову позначку BOM (три невидимі байти). ffmpeg читає
перший рядок разом із нею й не впізнає в ньому директиву file.
Імена файлів у нас латиницею, тому ascii достатньо — і жодних
невидимих байтів. Це той самий підводний камінь, що й з probe.txt
на уроці 9, тільки навпаки.| Частина | Що робить |
|---|---|
-f concat | каже: наступний вхід — не відео, а список файлів. Без цього ключа ffmpeg спробує програти сам list.txt |
-safe 0 | дозволяє імена з шляхами й символами, які демюксер вважає «небезпечними». Без нього шляхи з дискової літери або з / відхиляються |
-i list.txt | сам список |
-c copy | нічого не перекодовувати — просто перекласти готові дані в один файл |
З -c copy ffmpeg не дивиться на картинку. Він бере
стиснені порції даних і кладе їх у новий контейнер одну за одною. Час дописує
на ходу. У заголовку доріжки написано «1280×720, 30 кадрів, H.264». Написано
один раз на весь файл. Якщо в другому шматку насправді 640×360,
переписати заголовок посеред доріжки нікуди.
-c copy часто не падає на різних параметрах. Він
спокійно збирає файл, а плеєр після стику показує застиглу картинку зі звуком
або сиплеться квадратами. У виводі при цьому видно рядок про
Non-monotonic DTS — і його дуже легко проґавити.Ти склеїв два кліпи. У другому фрагменті голос відстає від губ. Перший фрагмент грає нормально. У чому річ?
concat відпрацював без жодної помилки, файл створено. Але
після стику картинка застигає, хоча звук іде далі. Що сталося і що робити?
Не переходь до титру, поки не побачив правильну тривалість. Стик має бути видно на око: змінюється сцена.
Цільова тривалість — 10 секунд ±0,5. Число 10,048 у прикладі вище ілюстративне. У тебе буде своє, і рівним воно майже напевно не буде. Це нормально: тривалість кратна кадрам, а не круглим секундам.
drawtextОбов'язкова частина роботи. Твоє ім'я на перших секундах ролика
drawtext — це відеофільтр. Він отримує кадр, малює на
ньому текст і віддає далі. Фільтр працює з розтиснутою картинкою, тому
-c copy тут неможливий: відео доведеться перекодувати.
Звук чіпати не треба — його якраз копіюємо.
| Параметр фільтра | Що задає |
|---|---|
fontfile | повний шлях до файлу шрифту. Не назва шрифту, а саме файл .ttf |
text | що написати |
fontsize | висота літер у пікселях кадру. Для 720p 36—48 — читабельно |
fontcolor | колір: назва (white) або 0xRRGGBB |
borderw, bordercolor | обведення. Без нього білий титр зникає на світлому кадрі |
x, y | координати. Тут вирази: w, h — розмір кадру, text_w, th — розмір напису |
enable | коли титр видно. between(t,0,3) — з 0-ї по 3-тю секунду |
Вираз x=(w-text_w)/2 ставить напис по центру. Ширину літер
рахує сам ffmpeg, тому довжина тексту не має значення.
y=h-th-40 притискає титр до низу кадру. Відступ — 40 пікселів.
ffmpeg — не текстовий редактор. Списку шрифтів системи він не
бачить. Малює літери він лише через бібліотеку FreeType. А їй треба дати
конкретний файл із контурами літер. Тому fontfile — це шлях, а не
назва. «Arial» для ffmpeg порожній звук, а
C:/Windows/Fonts/arial.ttf — файл, який лежить на диску.
: розділяє параметри. Тому диск пишеться як
C\:/Windows/Fonts/arial.ttf — зі зворотною скісною перед двокрапкою.
І скісні — прямі: зворотні \ фільтр читає як екранування.
Це пункт, на якому щороку застрягає пів класу.arial.ttf, Arial.ttf і DejaVuSans.ttf її
мають. Якщо взяти шрифт без кирилиці, титр вийде порожнім або з квадратиками —
і це не помилка команди, команда відпрацює успішно.| Система | Робочий шлях до шрифту |
|---|---|
| Windows | C\:/Windows/Fonts/arial.ttf |
| macOS | /System/Library/Fonts/Supplemental/Arial.ttf |
| Linux | /usr/share/fonts/truetype/dejavu/DejaVuSans.ttf |
На Windows ти написав у фільтрі fontfile=C:/Windows/Fonts/arial.ttf
і отримав скаргу на розбір фільтра. Що саме треба виправити?
З готового ролика витягуємо одну картинку — її вчитель дивиться поруч із відео. Беремо кадр із першої секунди, де вже видно титр.
-frames:v 1 означає «записати рівно один відеокадр і зупинитися».
У старих прикладах з інтернету цей ключ пишуть як -vframes 1.
Це його давня назва, вона працює й досі.
fadeрівень «+»Необов'язково. Береться тільки тоді, коли склейка й титр уже готові
report.csv і монтажний лист, ніж кинути незібраний fade.Фільтр fade плавно виводить картинку з чорного і зводить у чорне.
Він теж працює з кадрами. Тому ставиться в той самий -vf, через кому,
після drawtext. Фільтри виконуються ланцюжком зліва направо.
| Параметр | Що задає |
|---|---|
t=in / t=out | поява з чорного чи згасання в чорне |
st= | секунда, на якій ефект починається |
d= | скільки секунд він триває |
Для 10-секундного ролика: поява з 0-ї секунди тривалістю 1 с. Згасання — з 9-ї, теж на секунду. Секунду початку згасання рахують від кінця: тривалість мінус довжина ефекту.
drawtext потім fade — титр згасає разом із картинкою.
Навпаки — fade потім drawtext — титр залишиться яскравим
на чорному тлі, бо його домалюють уже після згасання. Обидва варіанти робочі,
але виглядають вони по-різному, і на здачі варто знати, який ти обрав.Ролик триває 10 с. Ти написав fade=t=out:st=10:d=1 — і жодного
згасання не побачив, хоча помилки теж не було. Чому?
Збери ролик мишею — сторінка напише команду. Її й копіюєш у термінал
Тут монтаж із голови перетворюється на команди. Перетягни фрагменти в потрібному порядку. Постав час обрізки й текст титру. Команди внизу перезбираються одразу.
Тягни за ⠿ або тисни стрілки — це змінює порядок рядків
у list.txt, а не самі фрагменти. Час обрізки — секунди джерела.
#, у буфер не потрапляють —
копіюється те, що можна одразу вставити в термінал. Ці самі рядки ти дублюєш
у cmd.txt: він поїде на сервер і саме за ним учитель питатиме,
який ключ за що відповідав.Ти поміняв фрагменти місцями в конструкторі. Які команди через це доведеться перезапустити?
ffmpeg і що з ними робитиТри тексти, які сьогодні побачить майже кожен. Помилка — це не поразка, а адреса
ffmpeg друкує багато. Головне правило:
дивись перший рядок зі словом помилки, а не останній. Далі часто
йде відлуння тієї самої проблеми на іншому рівні.
Unknown encoder 'libx264'Причина. Твою збірку ffmpeg зібрали без бібліотеки x264.
Такі «полегшені» збірки трапляються в системних репозиторіях і старих
портативних архівах. Сам ffmpeg є, а кодувальника H.264 у ньому
немає. Файл читати він уміє, створювати — ні.
Що робити. Спершу перевір, що саме є в твоїй збірці:
Якщо рядка немає — потрібна повна збірка. У класі вона лежить у мережевій
теці. Щоб не стояти, є запасний варіант: кодувальник -c:v mpeg4.
Він є в будь-якій збірці. Якість гірша, файл важчий — зате урок рухається
далі. У монтажному листі це чесно записуємо.
No such filter: 'drawtext'Причина. Цю збірку зібрали без бібліотеки шрифтів
(--enable-libfreetype). Малювати літери в ній немає чим, тому
й фільтра з такою назвою всередині просто немає. Перевіряється це двома
командами:
Що робити. Узяти повну збірку: ключем цей фільтр не ввімкнути.
У Windows бери збірку з gyan.dev або
BtbN. У macOS — brew install ffmpeg. У Linux — пакет
ffmpeg зі звичайного репозиторію.
Сусідня помилка з тим самим фільтром виглядає інакше — і означає інше:
Тут фільтр на місці, а от файлу шрифту за вказаним шляхом немає. Найчастіше
тому, що написали назву шрифту замість шляху. Або забули екранувати
двокрапку диска: правильно 'C\:/Windows/Fonts/arial.ttf'.
concatПричина. Фільтр concat вимагає однакового розміру кадру
в усіх входів. Тут перший вхід 1280×720, а другий 640×360. З'єднати їх
у одну доріжку неможливо.
У тому ж рядку помилки стоїть SAR 1:1. Зазвичай піксель
квадратний, але буває й витягнутий — тоді картинку розтягують уже при показі.
Форма самого пікселя й зветься SAR. Одиниця до одиниці означає «квадратний»,
і в обох наших фрагментах вона однакова.
Що робити. Не лагодь склейку — зрівняй джерела. Перевирізай обидва
фрагменти з однаковими -s і -r, як у нашому шаблоні.
Якщо джерела справді різні (телефон і камера), зведи їх до спільного розміру
фільтром scale перед склейкою.
Це вже не про параметри, а про безпеку. Демюксер за замовчуванням не пускає
абсолютні шляхи. Лікується це ключем -safe 0. Або тим, що ти
працюєш у тій самій теці й пишеш у списку прості імена.
| Що пише | Що це насправді | Дія |
|---|---|---|
Unknown encoder 'libx264' | у збірці немає H.264-кодувальника | повна збірка або тимчасово -c:v mpeg4 |
No such filter: 'drawtext' | збірка без libfreetype | повна збірка |
Could not load font ... cannot open resource | неправильний шлях до .ttf | повний шлях, двокрапка як \: |
Input link in1:v0 parameters ... do not match | у фрагментів різні розміри кадру | перевирізати з однаковими -s і -r |
Unsafe file name | абсолютний шлях у list.txt | додати -safe 0 |
Non-monotonic DTS in output stream | склеїли різне з -c copy; помилки немає, але картинка застигне | зрівняти параметри й склеїти наново |
list.txt: Invalid data found when processing input | забули -f concat — ffmpeg намагається програти сам список | додати -f concat перед -i |
File 'final.mp4' already exists. Overwrite? | це не помилка, а питання; команда чекає на відповідь | додати -y |
Тексти помилок наведені так, як їх друкують збірки ffmpeg 6—7. У давніших версіях формулювання коротші. Шістнадцяткові адреси в дужках щоразу свої — на них не зважай.
-vf може дійти спотвореною. Надійний обхід: покласти текст
у файл title.txt (кодування UTF-8) і замінити text='…'
на textfile='title.txt'. Фільтр прочитає файл сам, повз консоль.Команда з drawtext відпрацювала без помилок. Жодного червоного
рядка у виводі. Але в ролику титру немає взагалі. Що перевіряти першим?
Ролик лишається в тебе. На VPS їде тільки текст про нього
| Файл | Що всередині | Куди |
|---|---|---|
cmd.txt | усі команди ffmpeg, які ти справді виконав, по рядку на команду | сервер |
probe.txt | текстовий вивід ffprobe по final.mp4 | сервер |
report.csv | таблиця про чотири файли: розмір кадру, fps, кодек, вага | сервер |
index.html | сторінка з монтажним листом | сервер |
final.mp4, merged.mp4, part1–3.mp4 | саме відео | лишається локально |
poster.jpg | кадр із титром | лишається локально — учитель дивиться його на твоєму екрані |
probe.txt — паспорт готового ролика> probe.txt записує файл
у UTF-16. Чекер читає його як UTF-8, не знаходить жодного рядка
[STREAM] і дає червоний пункт — хоча ти все зробив правильно.У report.csv чотири рядки, а зроблено поки два. Це
v720p30.mp4 з уроку 9 і сьогоднішній final.mp4.
Бракує зменшеної копії й варіанта в іншому контейнері — це два запуски.
VP9 кодує помітно повільніше за H.264, тому беремо вже зменшений файл, а не
джерело. -b:v 0 тут обов'язковий. Без нього -crf у VP9
працює інакше: бітрейт лишається обмеженим зверху.
report.csv — чотири рядки данихПерший рядок — заголовок, далі по рядку на файл. Числа беруться з
ffprobe, а не з голови. Чекер перерахує їх сам і звірить.
Числа в прикладі ілюстративні, але не випадкові: вони сходяться
з формулою. v720p30 — 45 с при 2113 кбіт/с (це той самий файл,
що ти зробив на уроці 9), final — 10,05 с при 2400 кбіт/с.
У тебе будуть свої, і вони теж мають сходитися.
Вагу у байтах бере команда нижче. Списувати з провідника Windows не варто: він показує МіБ і округлює.
Чекер дивиться, чи не суперечать числа одне одному. Для кожного рядка має
сходитися вага ≈ бітрейт × тривалість ÷ 8 (±20%). v360p15
має важити менше за v720p30. А рядок final —
збігатися з width, height і duration
у probe.txt. Це і є доказ, що ролик справді зібрано.
Монтажний лист — це опис свого монтажу словами: звідки взято кожен шматок і що з ним зробили. За таким описом ролик збирають заново навіть тоді, коли чернетки вже стерли.
Пиши його на своїй сторінці index.html, у блоці з іменем
edit-log. Потрібно від 200 символів власного тексту
і щонайменше дві різні позначки часу джерела. Позначки й доводять, що фрагменти
взяті з різних місць.
fade і яка вийшла тривалість. Три-чотири
речення своїми словами — не список команд, команди вже є в
cmd.txt.final.mp4 (3 МБ) і poster.jpg (180 КБ) готові.
Ліміт на зображення — 500 КБ, тобто постер під нього формально проходить.
Що з цих двох поїде по FTP?
Кроки 1—11 — у твоєму терміналі, кроки 12—14 — на сервері. Галочки зберігаються, сторінку можна закрити.
source.mp4, part1–3.mp4, merged.mp4,
final.mp4, v720p30.mp4, v360p15.mp4,
v.webm і poster.jpg лишаються в локальній теці
media/lesson-05/. FTP-приймальня відхиляє відео автоматично, на
рівні сервера. Ролик учитель дивиться очно, на твоєму екрані.cmd.txt і
report.csv → монтажний лист → і тільки потім fade.
Згасання — рівень «+», без нього урок зараховується.Чекер бачить лише чотири легкі файли — і звіряє їх один з одним. Спроби не обмежені.
Демонстраційний режим: результат згенеровано для показу. На сервері
ця кнопка викликає POST /api/check, який запускає
check 05 від імені учня.
final.mp4 грає у твоєму плеєрі: тривалість близько 10 секунд;poster.jpg;cmd.txt рядок, яким зроблено титр, і кажеш,
у якому терміналі ця команда виконувалась;Це те, що бачить учитель, коли виставляє оцінку.
| Складник | Вага | Результат |
|---|
-ss до
-i — швидкий стрибок по джерелу; -ss після
-i — те саме, але через декодування всього початку.concat нічого не вирівнює. Він тільки складає шматки
встик. Однаковими їх маєш зробити ти — вирізавши з одного джерела одним
шаблоном команди.cmd.txt лишається: за ним роботу можна повторити з нуля.Дописати в монтажний лист один абзац. Тема — під яку платформу ти експортував би цей ролик. Назви роздільну здатність, fps і співвідношення сторін. Поясни, чому саме такі. Числа бери з таблиці якостей із ДЗ уроку 9 і з калькулятора ваги на тій самій сторінці.
Усі ключі, синтаксис фільтрів і формулювання помилок — з офіційної
документації та коду ffmpeg. Перевіряти дозволено й корисно.
ffmpeg — ключі -ss,
-t, -to, -i, -c copy,
-y, -frames:v, правило «опція діє на наступний файл»,
правило «-t має пріоритет над -to».
ffmpeg.org/ffmpeg.htmlconcat — формат list.txt,
директива file, ключ -safe, вимога однакових
параметрів потоків.
ffmpeg.org/ffmpeg-formats.html#concatconcat — вимога однакової роздільної здатності
й співвідношення пікселя для всіх сегментів.
ffmpeg.org/ffmpeg-filters.html#concatdrawtext — параметри fontfile,
textfile, fontsize, fontcolor,
borderw, x, y, enable,
змінні w, h, text_w, th.
ffmpeg.org/ffmpeg-filters.html#drawtext\:.
ffmpeg.org/ffmpeg-filters.htmlfade — t=in|out, st, d.
ffmpeg.org/ffmpeg-filters.html#fade-ss до -i
швидший і чому з -c copy різ прив'язаний до ключових кадрів.
trac.ffmpeg.org/wiki/Seekingffprobe — -show_entries,
-of default=noprint_wrappers=1, поля duration,
size, bit_rate.
ffmpeg.org/ffprobe.html-crf і
-preset.
trac.ffmpeg.org/wiki/Encode/H.264drawtext не збирається.
freetype.orgabout_Redirection — чому >
у Windows PowerShell 5.1 пише UTF-16 і навіщо Out-File -Encoding utf8.
learn.microsoft.com/powershell — about_RedirectionSet-Content -Encoding — які кодування
доступні й де з'являється BOM.
learn.microsoft.com/powershell — Set-ContentПовний список із поясненнями, що саме звідки взято, — у файлі
urok-10-джерела.md поруч із цією сторінкою.