Skip to content

itregernium/obs-s3-streaming

Repository files navigation

obs-s3-streaming

Полный проект для приёма RTMP-потока (OBS) → HLS (nginx) → загрузка сегментов в S3 (Yandex.Cloud). Набор скриптов упрощает запуск, остановку и сбор записи в MP4.

Содержание репозитория

  • Dockerfile, docker-compose.yaml — образ с nginx + RTMP + upload-скриптом
  • nginx.conf — конфигурация nginx с RTMP/HLS
  • upload2s3.py — наблюдатель папки HLS и загрузчик сегментов в S3
  • s3config — env-файл с параметрами доступа к S3 (не храните секреты в git)
  • start.sh — собрать и поднять сервис
  • stop.sh — скачать сегменты, собрать output.mp4, удалить сегменты из S3 (опц.) и остановить стек
  • download_and_concat.sh — вспомогательный скрипт для скачивания + склейки

Требования

  • Docker и Docker Compose
  • yc CLI (опционально) — удобно для управления Yandex Cloud
  • ffmpeg (на хосте) — опционально; если нет, stop.sh использует Docker-образ с ffmpeg

Безопасность

  • Не кладите s3config в репозиторий. Добавьте s3config в .gitignore.
  • Ротируйте access-keys и используйте минимально необходимые роли.

  1. Быстрая схема работы

  1. Запускаете ./start.sh — поднимается nginx (RTMP/HLS) и скрипт upload2s3.py.
  2. В OBS стримите в rtmp://<HOST>:1935/live/<STREAM_KEY>.
  3. nginx пишет сегменты в /tmp/hls; upload2s3.py подхватывает файлы и загружает в S3.
  4. После остановки стрима запускаете ./stop.sh — скачивание сегментов, сбор output.mp4, очистка S3 (по желанию) и docker compose down.

  1. Настройка Yandex.Cloud (создать сервисный аккаунт и ключи)

Через Web Console (GUI)

  • Откройте Yandex.Cloud Console → IAM & Admin → Service accounts → Create service account.
  • Выберите сервисный аккаунт → Keys → Create access key. Сохраните access key id и secret (secret показывается один раз).
  • Object Storage → Create bucket (например obs-test1).
  • IAM → Access bindings → Add binding: Subject = ваш service account, Role = Storage Object Admin (или подходящая роль для работы с объектами).

Через yc CLI (автоматизация)

# получить folder id (если нужно)
yc config get folder-id

# создать сервисный аккаунт
yc iam service-account create --name obs-uploader --description "Uploader for HLS" --folder-id $(yc config get folder-id)

# получить ID созданного аккаунта (пример)
SA_ID=$(yc iam service-account list --folder-id $(yc config get folder-id) --format json | jq -r '.[] | select(.name=="obs-uploader") | .id')

# создать access-key (выведет JSON с ключом и секретом)
yc iam access-key create --service-account-id $SA_ID > key.json
cat key.json

# назначить роль storage.objectAdmin на уровень папки (или проект)
FOLDER_ID=$(yc config get folder-id)
yc resource-manager folder add-access-binding --folder-id $FOLDER_ID --role storage.objectAdmin --subject serviceAccount:$SA_ID

# создать бакет (если ещё нет)
yc storage bucket create --name obs-test1 --default-storage-class standard

Скопируйте accessKeyId и secret в безопасное место и используйте их в s3config.


  1. Файл s3config

Создайте s3config в корне проекта с содержимым:

AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
AWS_ENDPOINT_URL=https://storage.yandexcloud.net
S3_BUCKET=obs-test1
# (опционально) PREFIX=hls/

Пример: S3_BUCKET=obs-test1, AWS_ENDPOINT_URL=https://storage.yandexcloud.net.


  1. Запуск (start)

Собрать и поднять сервис:

./start.sh

Что делает start.sh:

  • проверяет наличие s3config
  • запускает docker compose up --build -d nginx-rtmp

Просмотр логов:

docker compose logs -f nginx-rtmp

  1. Настройки OBS

  • Service: Custom...
  • Server: rtmp://<HOST>:1935/live (если OBS на той же машине — localhost)
  • Stream Key: любое имя (например mystream) — по ключу nginx создаёт HLS-плейлист mystream.m3u8
  • Output → Encoder: x264 (или аппаратный)
  • Rate control: CBR
  • Bitrate: 2500–4000 kbps для 720p, 4500–6000 kbps для 1080p
  • Keyframe interval: 2 (сек)

После старта стрима проверьте плейлист:

http://<HOST>:8080/hls/<STREAM_KEY>.m3u8

  1. Остановка и сбор (stop)

Запустить сбор записи и остановку:

./stop.sh

Что делает stop.sh:

  • скачивает сегменты из S3 в ./segments/ (через amazon/aws-cli контейнер и ./s3config)
  • формирует concat.txt в натуральном порядке
  • склеивает output.mp4 (локально через ffmpeg если установлен, иначе через Docker image)
  • по умолчанию удаляет объекты в S3 в указанном префиксе (чтобы не накапливать сегменты)
  • вызывает docker compose down

Пропустить удаление сегментов из бакета:

SKIP_S3_CLEANUP=1 ./stop.sh

Дополнительные опции (ручной режим)

  • Посмотреть список объектов:
docker run --rm -v "$PWD":/work -w /work --env-file ./s3config \
  --entrypoint sh amazon/aws-cli:latest -c 'aws --endpoint-url "$AWS_ENDPOINT_URL" s3 ls "s3://$S3_BUCKET/${PREFIX:-hls/}"'
  • Скачать сегменты вручную:
docker run --rm -v "$PWD":/work -w /work --env-file ./s3config \
  --entrypoint sh amazon/aws-cli:latest -c 'aws --endpoint-url "$AWS_ENDPOINT_URL" s3 cp --recursive "s3://$S3_BUCKET/${PREFIX:-hls/}" ./segments/'

  1. Troubleshooting

  • InvalidBucketName — проверьте имя бакета и наличие бакета в том же регионе/endpoint.
  • AccessDenied — проверьте, что сервисный аккаунт имеет роль storage.objectAdmin на нужном ресурсе.
  • 403 при http://<HOST>:8080/hls/ — это нормально (директория без index). Открывайте конкретный *.m3u8.
  • Ошибки FileNotFoundError при upload — скрипт теперь игнорирует временные .bak файлы и ждёт стабилизации размера файла перед upload.

  1. Security & best practices

  • Не коммитьте s3config.
  • Храните секреты в менеджере секретов (Yandex Lockbox, Vault и т.д.) для production.
  • Выдавайте минимально необходимые права и ротируйте ключи.

  1. Возможные улучшения

  • Собрать Docker image с awscli+ffmpeg для полноценной контейнерной сборки stop без ffmpeg на хосте.
  • Добавить флаги к stop.sh (--no-clean, --output <file>, --keep-remote).
  • Добавить healthcheck и systemd unit для запуска в продакшн.

Если хотите — реализую любой из пунктов.

obs-s3-streaming

Небольшой проект: nginx-rtmp пишет HLS в /tmp/hls, процесс upload2s3.py загружает сегменты в S3 (например Yandex Cloud Object Storage). В репо есть вспомогательные скрипты для запуска и остановки.

Содержание

  • Dockerfile, docker-compose.yaml — образ с nginx + модулем rtmp и скриптом загрузки
  • nginx.conf — конфиг nginx (RTMP + HLS + HTTP)
  • upload2s3.py — наблюдатель, загружает файлы в S3 (использует env)
  • s3config — env-файл с параметрами S3 (не храните секреты в git)
  • download_and_concat.sh — локальный скрипт для скачивания сегментов и склейки
  • start.sh, stop.sh — helper-скрипты (start/stop/collect)

Требования

  • Docker & Docker Compose
  • (опционально) ffmpeg на хосте — если нет, stop.sh попытается использовать Docker image с ffmpeg
  • s3config в корне репо с переменными (пример ниже)

Конфигурация (s3config) Создайте (или отредактируйте) файл s3config в корне репо со следующими переменными:

AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
AWS_ENDPOINT_URL=https://storage.yandexcloud.net
S3_BUCKET=obs
# (опционально) PREFIX=hls/

ВАЖНО: secret показывается только один раз при создании access key. Если вы потеряли secret — создайте новый ключ и удалите старый.

Запуск (быстро)

  1. Убедитесь, что s3config заполнен и находится в корне проекта.
  2. Запустите сервисы:
./start.sh

OBS: настройки для OBS

  • Service: Custom
  • Server: rtmp://:1935/live
  • Stream Key: любое имя (например mystream) — это имя плейлиста mystream.m3u8
  • Output: x264 (или HW), CBR, Keyframe interval = 2, bitrate в зависимости от разрешения

Остановка и сбор записей После завершения стрима выполните:

 AWS_ACCESS_KEY_ID=... AWS_REGION=... AWS_DEFAULT_REGION=... AWS_SECRET_ACCESS_KEY=... AWS_ENDPOINT_URL=https://storage.yandexcloud.net S3_BUCKET=... ./stop.sh

Что делает stop.sh:

  • скачивает все .ts сегменты из S3 (s3://$S3_BUCKET/${PREFIX:-hls/}) в ./segments/ (использует amazon/aws-cli контейнер и ./s3config для env)
  • собирает concat.txt в правильном порядке (natural sort)
  • склеивает output.mp4 (локально через ffmpeg если установлен, иначе через Docker image)
  • останавливает docker compose (docker compose down)

Дополнение: очистка бакета

  • По умолчанию stop.sh после успешной сборки видео удаляет все объекты в указанном префиксе (s3://$S3_BUCKET/${PREFIX:-hls/}), чтобы не накапливать сегменты в бакете.
  • Если вы хотите оставить сегменты в бакете, установите переменную окружения SKIP_S3_CLEANUP=1 перед запуском stop.sh.

Пример (без удаления удалённых объектов):

SKIP_S3_CLEANUP=1 ./stop.sh

Команды вручную

  • Просмотреть содержимое бакета:
docker run --rm -v "$PWD":/work -w /work --env-file ./s3config \
  --entrypoint sh amazon/aws-cli:latest -c 'aws --endpoint-url "$AWS_ENDPOINT_URL" s3 ls "s3://$S3_BUCKET/hls/"'
  • Скачать сегменты (в папку segments):
docker run --rm -v "$PWD":/work -w /work --env-file ./s3config \
  --entrypoint sh amazon/aws-cli:latest -c 'aws --endpoint-url "$AWS_ENDPOINT_URL" s3 cp --recursive "s3://$S3_BUCKET/hls/" ./segments/'

Ошибки и отладка

  • Если upload2s3.py сообщает AccessDenied — назначьте сервисному аккаунту роль storage.objectAdmin в Yandex Cloud для проекта/папки или соответствующую роль на ресурс бакета.
  • nginx может отдавать 403 на корень /hls/ — это нормально (нет index). Открывайте конкретный плейлист: http://<HOST>:8080/hls/<STREAM_KEY>.m3u8.

Безопасность

  • Не храните s3config в git. Добавьте s3config в .gitignore.
  • Для продакшна используйте секретный менеджер вместо плоского env-файла.

Если нужно, могу добавить: единый Docker image с aws+ffmpeg и пример systemd unit или инструкцию для CI.

obs-s3-streaming

Коротко: nginx-rtmp пишет HLS в /tmp/hls, upload2s3.py загружает сегменты в S3 (Yandex Cloud), скрипты помогают запускать и останавливать сервис и собирать запись.s3.py загружает сегменты в S3 (Yandex Cloud), скрипты помогают запускать и останавливать сервис и собирать запись.

Файлы конфигурации

  • s3config — env-файл с ключами и настройками S3 (уже в репо). Пример:
    AWS_ACCESS_KEY_ID=...
    AWS_SECRET_ACCESS_KEY=...
    AWS_ENDPOINT_URL=https://storage.yandexcloud.net
    S3_BUCKET=obs
    # (необязательно) PREFIX=hls/
    ```  ```
    ВАЖНО: не коммитьте секреты в git; добавьте `s3config` в .gitignore в продакшн.
    
    

Запускуск

  1. Собрать и поднять сервис:сервис:

    ./start.sh

    Скрипт делает docker compose up --build -d nginx-rtmp.Скрипт делает docker compose up --build -d nginx-rtmp.

  2. Настройки OBS:

    • Service: Custom - Service: Custom
    • Server: rtmp://:1935/live- Server: rtmp://:1935/live
    • Stream Key: любое имя (например mystream)я (например mystream)
    • Output: CBR, keyframe interval 2, bitrate по разрешению (см. примеры в проекте)- Output: CBR, keyframe interval 2, bitrate по разрешению (см. примеры в проекте)

Остановка и сборка видео

  • Остановить сервис и скачать сегменты + собрать video:- Остановить сервис и скачать сегменты + собрать video:
    ./stop.sh  ./stop.sh
    Что делает: Что делает:
    • вызывает aws-cli в контейнере для копирования s3://$S3_BUCKET/$PREFIX./segments/ вызывает aws-cli в контейнере для копирования s3://$S3_BUCKET/$PREFIX./segments/
    • генерирует concat.txt в правильном порядкеxt` в правильном порядке
    • если ffmpeg есть на хосте — использует его; иначе выполняет ffmpeg в Docker (образ jrottenberg/ffmpeg) если ffmpeg есть на хосте — использует его; иначе выполняет ffmpeg в Docker (образ jrottenberg/ffmpeg)
    • сохраняет итог в output.mp4 - сохраняет итог в output.mp4
    • затем выполняет docker compose down``docker compose down

Примеры ручного выполнения (если нужно только скачать):

# посмотреть список# посмотреть список
docker run --rm -v "$PWD":/work -w /work --env-file ./s3config \
  --entrypoint sh amazon/aws-cli:latest -c 'aws --endpoint-url "$AWS_ENDPOINT_URL" s3 ls "s3://$S3_BUCKET/hls/"'  --entrypoint sh amazon/aws-cli:latest -c 'aws --endpoint-url "$AWS_ENDPOINT_URL" s3 ls "s3://$S3_BUCKET/hls/"'

# скачать сегменты# скачать сегменты
docker run --rm -v "$PWD":/work -w /work --env-file ./s3config \
  --entrypoint sh amazon/aws-cli:latest -c 'aws --endpoint-url "$AWS_ENDPOINT_URL" s3 cp --recursive "s3://$S3_BUCKET/hls/" ./segments/'  --entrypoint sh amazon/aws-cli:latest -c 'aws --endpoint-url "$AWS_ENDPOINT_URL" s3 cp --recursive "s3://$S3_BUCKET/hls/" ./segments/'

Требования

  • Docker + docker compose
  • (опционально) ffmpeg на хосте — если нет, stop.sh использует ffmpeg в контейнере

Права и безопасность

  • Дайте сервис-аккаунту в Yandex Cloud роль storage.objectAdmin для работы с объектами в бакете.- Дайте сервис-аккаунту в Yandex Cloud роль storage.objectAdmin для работы с объектами в бакете.
  • Секреты храните в менеджере секретов в продакшн.

Если нужно — могу добавить Docker image с aws+ffmpeg для полного offline запуска скрипта.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published