Стриминг через Docker: M3U8 в RTMP с визуализацией волны

Ниже – схема, как через Docker и FFmpeg перегнать HLS (M3U8) в RTMP, например на сервер трансляции Telegram. Параметром eqon/eqoff включается или отключается визуализация волны (showwaves), чтобы на «чисто аудио» потоке было хоть какое-то видео для RTMP.

Что нужно

  1. Docker – изоляция и простой запуск без локальной сборки FFmpeg.
  2. FFmpeg – чтение M3U8, фильтры, кодирование, отдача в FLV/RTMP (в образе уже есть).
  3. Источник в формате HLS: URL .m3u8.
  4. RTMP endpoint: URL сервера и ключ потока (ingest Telegram или свой nginx-rtmp / mediaMTX и т.п.).

Установка Docker

На Debian/Ubuntu, если Docker ещё не стоит:

sudo apt update
sudo apt install docker.io

На серверах чаще ставят официальный Docker Engine; для домашней лаборатории пакета docker.io обычно достаточно. Пользователя можно добавить в группу docker, чтобы не писать sudo каждый раз.

Скрипт stream.sh

Скрипт принимает M3U8, RTMP URL, ключ и флаг визуализации. При eqon из аудио строится видеоряд showwaves 1280×720; при eqoff в map уходит только аудио (для многих RTMP-приёмников без видео это может быть проблемой – смотрите требования платформы).

#!/bin/bash

# Проверка аргументов
if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] || [ -z "$4" ]; then
  echo "Usage: $0 <M3U8_URL> <RTMP_URL> <RTMP_KEY> <eqon/eqoff>"
  exit 1
fi

M3U8_URL=$1
RTMP_URL=$2
RTMP_KEY=$3
EQ_STATUS=$4
FULL_RTMP_URL="$RTMP_URL/$RTMP_KEY"

if [ "$EQ_STATUS" == "eqon" ]; then
    EQ_FILTER="[0:a]showwaves=s=1280x720:mode=line:colors=blue,format=yuv420p[v]"
    MAP_FILTER="-map '[v]' -map 0:a"
else
    EQ_FILTER=""
    MAP_FILTER="-map 0:a"
fi

ffmpeg -re -i "$M3U8_URL" \
    -filter_complex "$EQ_FILTER" \
    $MAP_FILTER \
    -c:v libx264 -preset veryfast -tune zerolatency -c:a aac -ar 44100 -b:a 128k \
    -f flv "$FULL_RTMP_URL"

Сохраните как stream.sh, сделайте исполняемым: chmod +x stream.sh.

Параметры FFmpeg

  • -re – читать вход примерно в реальном времени (для live-источника, не для «прогнать файл как можно быстрее»).
  • -i "$M3U8_URL" – вход: плейлист HLS.
  • -filter_complex + showwaves – картинка из аудио: размер s=1280x720, режим mode=line, цвет colors=blue, пиксельный формат yuv420p для совместимости с x264/RTMP.
  • -map '[v]' -map 0:a – при eqon: сгенерированное видео и исходное аудио; при eqoff – только аудио.
  • -c:v libx264 -preset veryfast -tune zerolatency – быстрое кодирование с низкой задержкой.
  • -c:a aac -ar 44100 -b:a 128k – AAC, 44.1 кГц, 128 кбит/с.
  • -f flv "$FULL_RTMP_URL" – контейнер FLV на RTMP (URL + ключ).

Важно: при пустом EQ_FILTER строка -filter_complex "" в части сборок FFmpeg ведёт себя капризно. Если eqoff падает, либо не передавайте -filter_complex совсем (разветвить команду в if/else), либо всегда держите простой null/anull-фильтр. В проде лучше две явные ветки ffmpeg.

Dockerfile

FROM jrottenberg/ffmpeg:4.4-ubuntu

COPY stream.sh /usr/local/bin/stream.sh
RUN chmod +x /usr/local/bin/stream.sh

ENTRYPOINT ["/usr/local/bin/stream.sh"]

Базовый образ уже содержит FFmpeg. Скрипт – единственная точка входа: аргументы контейнера уходят в stream.sh.

Сборка и запуск

docker build -t m3u8-to-rtmp-eq .
docker run m3u8-to-rtmp-eq <M3U8_URL> <RTMP_URL> <RTMP_KEY> eqon

Аргументы:

  • <M3U8_URL> – URL плейлиста HLS;
  • <RTMP_URL> – база RTMP без ключа (например rtmps://.../s);
  • <RTMP_KEY> – ключ/stream key;
  • eqon или eqoff – визуализация волны вкл/выкл.

Автозапуск и перезапуск

Чтобы контейнер поднимался после ребута и после падения FFmpeg:

docker run --restart unless-stopped m3u8-to-rtmp-eq \
  <M3U8_URL> <RTMP_URL> <RTMP_KEY> eqon

Для логов удобно добавить --name m3u8-rtmp и смотреть docker logs -f m3u8-rtmp. Ключ RTMP не светите в публичных репозиториях и CI.

Готовый образ и пример

Код и образ выложены автором схемы: репозиторий на GitHub и образ на Docker Hub (ссылки в блоке источников). Пример живой отдачи – канал Telegram с online-потоком; для своего кейса подставьте свой M3U8 и ключ ingest.

Итог

Схема простая: контейнер с FFmpeg читает M3U8, при необходимости рисует showwaves, кодирует x264+AAC и шлёт FLV на RTMP. Удобно для радио/аудио-источников, которым нужен «видео» слой, и для перегона HLS на платформы с RTMP-ingest. Дальше – мониторинг логов, лимиты CPU на veryfast/zerolatency и запас по сети.

Источники и ссылки


Комментарии загружаются…