From f04ce1a9b658494e2dea2a408afc2016246bdf69 Mon Sep 17 00:00:00 2001 From: postscriptum Date: Mon, 20 Oct 2025 09:58:22 +0300 Subject: [PATCH] add `m3u8-stream-proxy-with-ffmpeg-in-icecast.gmi` --- public/uk/index.gmi | 1 + ...u8-stream-proxy-with-ffmpeg-in-icecast.gmi | 116 ++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 public/uk/m3u8-stream-proxy-with-ffmpeg-in-icecast.gmi diff --git a/public/uk/index.gmi b/public/uk/index.gmi index ad022a7..82606a4 100644 --- a/public/uk/index.gmi +++ b/public/uk/index.gmi @@ -9,6 +9,7 @@ ### Нотатки +=> m3u8-stream-proxy-with-ffmpeg-in-icecast.gmi 2025-10-20 Проксування потоку m3u8 засобами ffmpeg в Icecast => i2p-capsule-in-gemini-space-with-agate.gmi 2025-10-09 Публікація капсули Gemini в I2P на прикладі сервера Agate => squid-out-proxy.gmi 2025-10-08 Налаштування вихідного проксі на базі squid => reticulum-meshchat-with-connection-over-yggdrasil.gmi 2025-10-07 Reticulum / MeshChat з підключенням через Yggdrasil diff --git a/public/uk/m3u8-stream-proxy-with-ffmpeg-in-icecast.gmi b/public/uk/m3u8-stream-proxy-with-ffmpeg-in-icecast.gmi new file mode 100644 index 0000000..50ec15e --- /dev/null +++ b/public/uk/m3u8-stream-proxy-with-ffmpeg-in-icecast.gmi @@ -0,0 +1,116 @@ +# Проксування потоку m3u8 засобами ffmpeg в Icecast + +В мене немає досвіду з адміністрування стрімінгових сервісів, раніше на базі Icecast робив тільки локальну ротацію музичної колекції: +=> setup-icecast-ezstream-web-radio-on-linux.gmi Веб-радіо в Linux: встановлення сервера Icecast та базове налаштування ротації з Ezstream + +Зацікавив проєкт довкола-айтішних стрімів eQtv: +=> https://tv.equalitie.org/uk/live/ + +Цей матеріал - невеличка нотатка про налаштування проксі на прикладі сервісу eQtv українською мовою для локальних мереж: + +=> http://[202:68d0:f0d5:b88d:1d1a:555e:2f6b:3148]:8000/eQtv.mp3 Yggdrasil +=> http://[505:6847:c778:61a1:5c6d:e802:d291:8191]:8000/eQtv.mp3 Mycelium +=> http://mrkssh4b2qkrf5hl4yxrwbtuowbmjugozaa7emaybnokw5jtcydq.b32.i2p/eQtv.mp3 I2P + +## Джерела + +Витягнути потік виявилось задачею не тривіальною, я її постійно відкладав але згодом таки знайшов в дебагах (ctrl+shift+i) наступні доріжки: + +* https://eqtv.live:8083/eqtvua/eqtvua480/chunks_dvr.m3u8 - схоже, що відповідає за відео +* https://eqtv.live:8083/eqtvua/eqtvua_hd_ukr/chunks_dvr.m3u8 - відповідає за аудіо-ряд (їх 3) + +## ffmpeg + +Вже звичний мені ezstream не вміє проксувати потоки з URL, тому віднайшов спосіб з ffmpeg: + +``` bash +ffmpeg -i "https://eqtv.live:8083/eqtvua/eqtvua_hd_ukr/chunks_dvr.m3u8?nimblesessionid=xxx" -c:a copy icecast://user:password@127.0.0.1:8000/eQtv.aac +``` + +У прикладі вище - потік передається в Icecast "як є" у форматі AAC, але такий формат мені не зовсім підходить, бо я хочу окрім оверлейних мереж Yggdrasil і Mycelium ще й стрімити в I2P з його "вузьким" каналом. Хоч конвертація вимагає додаткових ресурсів CPU, все ж вирішив її застосувати, звівши до поширеного формату MP3 з бітрейтом 32 kb/s: + +``` bash +ffmpeg -i "https://eqtv.live:8083/eqtvua/eqtvua_hd_ukr/chunks_dvr.m3u8?nimblesessionid=xxx" -b:a 32k icecast://user:password@127.0.0.1:8000/eQtv.mp3 +``` + +Як видно на прикладах вище, я додав до URL джерела аргумент `?nimblesessionid=xxx` - він потрібен для того, щоб ffmpeg не плодив нові сесії в процесі читання. Тут я ще не знаю, як довго протримається поточна сесія, але якщо будуть проблеми - напишу скрипт, що витягає актуальний її номер та доповню цей матеріал. + +## Icecast + +Декілька слів про налаштування сервера Icecast. Раніше, для локальних колекцій, мета-інформація про стрім в мене обслуговувалась сервером ezstream. Тут його немає, тому я додав такий набір до конфігурації точки монтування Icecast: + +``` /etc/icecast2/icecast.xml + + /eQtv.mp3 + user + password + eQtv українською мовою (аудіо, 32 kb/s) + eQtv — це проект eQualitie, неприбуткової організації, що розробляє технології для підвищення цифрової стійкості, особливо для спільнот, яким загрожують цензура, стеження, зміна клімату та мережева ізоляція. + https://tv.equalitie.org/uk/live + +``` +* відповідно, `user:password` мають відповідати тим, що вказані в команді `ffmpeg` + +## Systemd + +Команду `ffmpeg` я виконую від системного сервісу, створивши відповідного користувача: + +``` /etc/systemd/system/eqtv-mp3.service +#/etc/systemd/system/eqtv-mp3.service +[Unit] +After=network.target + +[Service] +Type=simple + +User=eqtv +Group=eqtv + +# Затримка потрібна у моєму випадку через залежність від Icecast +# ExecStartPre=/bin/sleep 5s +ExecStart=/usr/bin/ffmpeg -i ... + +# Журнали я вимкнув, але можна продебажити наступним чином +StandardOutput=null +# file:///home/eqtv/eqtv-mp3-debug.log +StandardError=null +# file:///home/eqtv/eqtv-mp3-error.log + +[Install] +WantedBy=multi-user.target +``` +* в `ExecStart` треба вказати відповідний набір атрибутів `ffmpeg` + +## Nginx + +Як видно з прикладу, мій сервер Icecast крутиться на інтерфейсі `127.0.0.1` для локальних потреб (щоб не ганяти трафік через оверлей). Окрім локалхосту, в мене відбувається ретрансляція на різні мережі IPv6, тому для зручності я проксую клієнтський трафік через Nginx: + +``` /etc/nginx/sites-available/default +#/etc/nginx/sites-available/default +server { + listen [202:68d0:f0d5:b88d:1d1a:555e:2f6b:3148]:8000; + listen [505:6847:c778:61a1:5c6d:e802:d291:8191]:8000; + listen xx.xx.xx.xx:8000; + + access_log /var/log/nginx/icecast.access.log; + + location / { + proxy_pass http://127.0.0.1:8000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_redirect off; + } +} +``` +* на прикладі `listen` - проксі на Yggdrasil та Mycelium і одна на локальну мережу IPv4 +* `proxy_pass` - може бути відмінний локальний порт від вказаного у прикладах + +## Посилання + +=> https://devzone.org.ua/post/proksuvannia-m3u8-zasobamy-icecast Веб-версія цього матеріалу з коментарями на DevZone + +### Читайте також + +=> yggdrasil-is-network-with-distributed-routing.gmi Yggdrasil - мережа з децентралізованою маршрутизацією \ No newline at end of file