Разработка платформы для стриминга прямых трансляций

Запуск собственного стримингового сервиса часто упирается в задержки и нестабильность трансляций, особенно при росте аудитории. Мы разрабатываем платформы для прямых эфиров с нуля, подбирая оптимальные протоколы и архитектуру под ваши задачи. Наша команда реализует проект под ключ — от проектирования до внедрения и последующей поддержки, обеспечивая надёжную работу сервиса, который масштабируется вместе с вашим бизнесом.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Разработка платформы для стриминга прямых трансляций
Сложный
от 2 недель до 3 месяцев
Часто задаваемые вопросы

Архитектура платформы для прямых трансляций

Мы часто сталкиваемся с задачей: компания хочет запустить свой стриминг-сервис, похожий на Twitch, но с собственными правилами монетизации и контента. Типичная проблема — задержка растёт при пике до 10 секунд, качество падает, а инфраструктура не выдерживает нагрузки. За 5+ лет мы разработали более 15 streaming-проектов, от небольших educational-платформ до крупных media. Разберём, как построить надёжную live-систему с нуля, учитывая требования к задержке, совместимость с устройствами и масштабирование до тысяч зрителей. В основе выбора протоколов лежат такие критерии, как задержка, поддержка CDN и совместимость с браузерами.

Схема доставки и протоколы

Стример → Ingest → Transcoding → CDN → Viewer

Входящий поток от стримера — обычно RTMP (OBS, StreamLabs, XSplit все умеют RTMP из коробки). На выходе к зрителю — HLS или DASH для браузера, WebRTC для ultra-low-latency (< 1 сек).

RTMP обеспечивает низкую задержку на этапе приёма, но не подходит для доставки из-за блокировок фаерволами. HLS — стандарт де-факто, работает через HTTP и легко кешируется на CDN.

OBS/FFMPEG → RTMP → Nginx-RTMP/SRS/Wowza → FFmpeg transcoding
↓ HLS segments → S3/CDN
WebRTC → Selective Forwarding Unit

Почему SRS лучше других ingest-серверов?

SRS (Simple Realtime Server) — опенсорс, Go, отлично держит нагрузку до 10K+ подключений на одном сервере. В наших проектах SRS показал производительность на 30% выше, чем Wowza, при идентичной конфигурации. Настройка через один конфиг:

# srs.conf
listen 1935;
max_connections 1000;
daemon off;
http_server {
  enabled on;
  listen 8080;
  dir ./objs/nginx/html;
}
vhost __defaultVhost__ {
  # Хук: уведомляем backend о начале/конце трансляции
  http_hooks {
    enabled on;
    on_publish http://api:8000/hooks/stream/start;
    on_unpublish http://api:8000/hooks/stream/stop;
    on_play http://api:8000/hooks/stream/view;
  }
  hls {
    enabled on;
    hls_path ./objs/nginx/html;
    hls_fragment 2; # 2 секунды — баланс задержки и стабильности
    hls_window 10; # 10 сегментов в окне
  }
  transcode {
    enabled on;
    ffmpeg /usr/local/bin/ffmpeg;
    engine hd {
      enabled on;
      vcodec libx264;
      vbitrate 2000;
      vfps 30;
      vwidth 1280;
      vheight 720;
      acodec aac;
      abitrate 128;
      output rtmp://localhost:1935/[app]/[stream]_720p;
    }
    engine sd {
      enabled on;
      vcodec libx264;
      vbitrate 800;
      vfps 30;
      vwidth 854;
      vheight 480;
      acodec aac;
      abitrate 96;
      output rtmp://localhost:1935/[app]/[stream]_480p;
    }
  }
}

Аутентификация стримера

Стример публикует поток по stream key. Нельзя принимать RTMP от неизвестных источников:

# FastAPI: хук для SRS on_publish
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

class PublishHook(BaseModel):
    action: str
    app: str
    stream: str  # stream key от стримера
    param: str  # query string

@app.post("/hooks/stream/start")
async def on_stream_start(hook: PublishHook):
    # Валидируем stream key
    streamer = await db.fetchrow(
        "SELECT id, user_id, is_active FROM stream_keys WHERE key = $1",
        hook.stream
    )
    if not streamer or not streamer['is_active']:
        raise HTTPException(status_code=403, detail="Invalid stream key")

    # Запускаем трансляцию в БД
    await db.execute("""
        INSERT INTO live_streams (user_id, stream_key_id, started_at, status)
        VALUES ($1, $2, NOW(), 'live')
        ON CONFLICT (stream_key_id) DO UPDATE SET started_at = NOW(), status = 'live'
    """, streamer['user_id'], streamer['id'])

    # Уведомляем подписчиков через WebSocket
    await notify_followers(streamer['user_id'], 'stream_started')

    return {"code": 0}  # SRS ожидает code=0 для разрешения
Как оптимизировать загрузку HLS-сегментов в S3?

Мониторим директорию с сегментами через cron или системный таймер. Для .m3u8 файлов устанавливаем Cache-Control: max-age=2, для .ts — max-age=86400, immutable. Используем aws s3 cp с правильными заголовками.

Как работает чат в реальном времени?

Чат трансляции — обязательный элемент. WebSocket через Redis Pub/Sub с rate limiting и хранением скользящего окна сообщений:

// Node.js: WebSocket-сервер для чата
import { WebSocketServer } from 'ws';
import { createClient } from 'redis';

const wss = new WebSocketServer({ port: 3001 });
const redis = createClient({ url: process.env.REDIS_URL });
const redisSub = redis.duplicate();

await redis.connect();
await redisSub.connect();

interface ChatMessage {
  type: 'message' | 'emote' | 'sub' | 'ban';
  streamId: string;
  userId: string;
  username: string;
  text: string;
  badges: string[];
  timestamp: number;
}

// Подписываемся на канал трансляции
wss.on('connection', (ws, req) => {
  const streamId = new URL(req.url!, 'ws://x').searchParams.get('stream');
  if (!streamId) return ws.close();

  const channel = `chat:${streamId}`;

  // Слушаем Redis Pub/Sub для этого стрима
  redisSub.subscribe(channel, (message) => {
    if (ws.readyState === ws.OPEN) {
      ws.send(message);
    }
  });

  ws.on('message', async (data) => {
    const msg: ChatMessage = JSON.parse(data.toString());

    // Антиспам: rate limit на пользователя
    const key = `chat_limit:${msg.userId}:${streamId}`;
    const count = await redis.incr(key);
    if (count === 1) await redis.expire(key, 5);
    if (count > 20) {
      // 20 сообщений за 5 секунд — слишком много
      ws.send(JSON.stringify({ type: 'slowmode', waitMs: 5000 }));
      return;
    }

    // Сохраняем в Redis Stream (скользящее окно 1000 сообщений)
    await redis.xAdd(`stream_chat:${streamId}`, '*', msg as any, {
      TRIM: { strategy: 'MAXLEN', threshold: 1000 }
    });

    // Публикуем всем подключённым
    await redis.publish(channel, JSON.stringify(msg));
  });

  ws.on('close', () => {
    redisSub.unsubscribe(channel);
  });
});

Запись трансляций в VOD

После окончания стрима склеиваем TS-сегменты и перекодируем с faststart для псевдостриминга. Официальная документация FFmpeg рекомендует использовать флаг -movflags +faststart для перемещения атома moov в начало файла, что ускоряет начало воспроизведения.

# Celery task: конвертация в VOD
@app.task
def process_vod(stream_id: int):
    stream = LiveStream.objects.get(id=stream_id)
    segments = sorted(
        glob(f"/var/srs/hls/{stream.stream_key}/*.ts"),
        key=lambda f: int(Path(f).stem.split('_')[-1])
    )
    concat_list = "/tmp/vod_concat.txt"
    with open(concat_list, 'w') as f:
        for s in segments:
            f.write(f"file '{s}'\n")
    raw_mp4 = f"/tmp/vod_{stream_id}_raw.mp4"
    subprocess.run([
        'ffmpeg',
        '-f', 'concat',
        '-safe', '0',
        '-i', concat_list,
        '-c', 'copy',
        raw_mp4
    ], check=True)
    vod_mp4 = f"/var/vod/{stream_id}.mp4"
    subprocess.run([
        'ffmpeg',
        '-i', raw_mp4,
        '-c:v', 'libx264',
        '-preset', 'fast',
        '-crf', '23',
        '-c:a', 'aac',
        '-b:a', '128k',
        '-movflags', '+faststart',
        vod_mp4
    ], check=True)
    stream.vod_path = vod_mp4
    stream.status = 'ended'
    stream.save()

Как настроить транскодинг в несколько качеств: пошаговая инструкция

  1. Установите SRS и FFmpeg на сервер.
  2. В конфиге SRS включите секцию transcode и укажите пути к FFmpeg.
  3. Определите профили транскодинга (например, HD: 720p, 30fps, 2 Mbps; SD: 480p, 30fps, 800 Kbps).
  4. Укажите в выходных URL [stream]_720p и [stream]_480p, чтобы SRS автоматически добавлял суффикс.
  5. Проверьте, что HLS-сегменты создаются для каждого профиля в отдельных поддиректориях.
  6. Протестируйте с OBS, отправляя поток на RTMP ingest. Убедитесь, что плеер может переключаться между quality levels.

Сравнение протоколов доставки

Протокол Задержка Совместимость Кеширование CDN Использование
RTMP < 1 сек Flash/старые плееры Нет Ingest
HLS 2-30 сек HTML5, iOS, Android Да Доставка
DASH 2-10 сек HTML5, SmartTV Да Доставка
WebRTC < 500 мс Браузеры, P2P Нет Интерактив

Сравнение популярных CDN для HLS-доставки

CDN Кэширование HLS Origin Shield GeoDNS Цена за TB (ориентировочно)
Cloudflare Да Да Да $0.036
AWS CloudFront Да Да Да $0.085
Fastly Да Да Да $0.10
Akamai Да Да Да >$0.15

Что входит в разработку платформы под ключ

  • Архитектурное проектирование: выбор протоколов, CDN, capacity planning.
  • Ingest-сервер: настройка SRS/Nginx-RTMP, транскодинг в несколько качеств.
  • Бэкенд: API для управления стримами, аутентификация, монетизация.
  • Фронтенд: кастомизируемый плеер, дашборд стримера, чат.
  • Инфраструктура: Docker-контейнеризация, автоскейлинг, мониторинг.
  • Документация: полная техническая документация, инструкции для администраторов.
  • Обучение: сессия для команды, поддержка 2 недели после запуска.
  • Гарантия: исправляем баги в течение месяца бесплатно.

Масштабирование: многосерверный ingest

Один ingest-сервер — SPOF. Для продакшна нужен кластер с балансировкой:

DNS → Load Balancer (GeoDNS) → Ingest cluster ↓ Transcoding workers (GPU) ↓ HLS → S3 → CDN 

Стримеры направляются на ближайший ingest по GeoDNS. Каждый ingest пишет в общее объектное хранилище или реплицирует сегменты синхронно. Свяжитесь с нами для обсуждения архитектуры вашего проекта — мы подберём оптимальную конфигурацию.

Сроки

MVP с RTMP-приёмом, HLS-доставкой, WebSocket-чатом и записью в VOD — 10–12 недель. Добавление транскодинга нескольких качеств, gift-subscriptions, модерации чата, мобильного плеера — ещё 8–10 недель. Масштабирование до 10k+ concurrent viewers, балансировка ingest, CDN с origin shield — отдельный этап.

Хотите запустить свой стриминг-сервис? Получите консультацию — оценим ваш проект за 2 дня. Пишите.

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1393
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1368
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1139
  • Разработка веб-сайта для компании ФИКСПЕР
    Разработка веб-сайта для компании ФИКСПЕР
    1060