В этом лонгриде мы разберёмся, как превратить обычную камеру в высокотехнологичный видеоцентр с поддержкой RTSP, motion detection, архивом и просмотром видео в браузере. Тут вам и настройка камеры, и волшебство ffmpeg, и хитрости nginx с RTMP и HLS — короче, полный набор! Ну что, готовы? Поехали!


Как подключить камеру по RTSP протоколу — просто как дважды два

Первое, что нужно знать: ваша камера должна поддерживать RTSP. Это как ключ к тайной двери — без него не войти. Информация о поддержке обычно есть в документации камеры.

Стандартный RTSP адрес выглядит примерно так:

rtsp://<пользователь>:<пароль>@<IP-адрес>:<порт>/<путь_к_потоку>

Например, для Axis это будет что-то вроде:

rtsp://root:password@192.168.0.90:554/mpeg4/media.amp

Теперь представьте, что это ваша цифровая шпионская труба — по ней будет течь видео.


Почему motion detection — это как глаз орла на страже безопасности

Видеонаблюдение без обнаружения движения — это как охранник, который спит на посту. Вот тут на сцену выходит утилита motion — она смотрит на видео и кричит "Эй, кто там шевелится!"

Motion умеет брать RTSP-поток, распознавать движение и записывать в архив — как настоящий бдительный детектив.


RTMP и HLS — два протокола, как «Рэмбо» и «Чак Норрис» стриминга

Чтобы видео показывалось в браузере, нужна магия протоколов. С двумя главными героями знакомьтесь:

  • RTMP — практически мгновенный стрим с минимальной задержкой, но работает только с Flash-плеерами (да-да, Flash — это динозавр, но иногда он ещё полезен).
  • HLS — дружелюбный ко всем устройствам, особенно iOS, но с задержкой — это как смотреть матч с небольшим опозданием.

Чтобы не выбирать, мы используем их оба! nginx с модулем RTMP — это наш «комбайн», который умеет и то, и другое.


Схема системы видеонаблюдения

Ниже классическая схема, которую можно представить как организацию работы полиции на районе:

Элемент Функция
camera Источник видеопотока
ffserver RTSP сервер, принимает поток от камеры
nginx RTMP и HLS сервер, раздаёт поток на клиентов
motion Обнаружение движения и запись в архив
archive Хранение видео файлов
camera ---> ffserver ---> nginx ---> HLS/RTMP (для просмотра)
                   \
                    ---> motion ---> archive

Настройка ffserver — малый, да удалый

ffserver — это старый, но золотой помощник для трансляций. Пример минимального конфигурационного файла:

RTSPPort 554
HTTPPort 8080
HTTPBindAddress 0.0.0.0
RTSPBindAddress 0.0.0.0
MaxClients 2000
MaxBandwidth 50000
CustomLog -
NoDefaults

<Feed cam1.ffm>
</Feed>

<Stream cam1>
Feed cam1.ffm
Format rtp
NoAudio
VideoSize 1280x720
</Stream>

Здесь мы говорим, что принимаем RTSP на порту 554, и выдаём видео через HTTP на 8080. Можно добавить несколько камер — просто копируйте блоки <Feed> и <Stream>.


Настройка motion — как сделать так, чтобы камера не спала

Для motion важны несколько параметров:

  • event_gap 10 — сколько секунд не должно быть движения, чтобы завершить запись
  • output_pictures off — отключаем снимки, чтобы не засорять память
  • ffmpeg_video_codec mp4 — используем mp4 для видео
  • stream_port 0 — отключаем собственный поток
  • webcontrol_port 8080 — включаем веб-управление
  • camera_dir /etc/motion/conf.d — конфиги камер лежат здесь

Пример конфига для одной камеры:

camera_id 1
width 1280
height 720
framerate 5
post_capture 50
netcam_url rtsp://127.0.0.1/cam248
threshold 4000
target_dir /var/www/archive/
movie_filename cam%t/%Y-%m-%d_%H-%M-%S

nginx с модулем RTMP — настройка для видеостриминга

В основной конфигурации /etc/nginx/nginx.conf рядом с секцией http добавляем RTMP-сервер:

rtmp {
  server {
    listen 1935;
    chunk_size 256;
    wait_key on;
    sync 10ms;
    interleave on;
    buflen 1s;

    application stream {
      live on;
      hls on;
      hls_fragment_naming system;
      hls_fragment 1s;
      hls_playlist_length 3s;
      hls_path /srv/http/hls;
      hls_nested on;

      allow publish 127.0.0.0/8;
      deny publish all;

      exec_static ffmpeg -r 5 -fflags nobuffer -probesize 32 -loglevel quiet -re -rtsp_transport tcp -i rtsp://192.168.20.100/channel=1_stream=0 -override_ffserver -c copy http://127.0.0.1:8080/cam1.ffm;
      exec_static ffmpeg -r 5 -fflags nobuffer -probesize 32 -loglevel quiet -re -rtsp_transport tcp -i rtsp://192.168.20.101/channel=1_stream=0 -override_ffserver -c copy http://127.0.0.1:8080/cam2.ffm;

      exec_static ffmpeg -r 5 -fflags nobuffer -probesize 500000 -loglevel quiet -re -rtsp_transport tcp -i rtsp://127.0.0.1/cam1 -c copy -f flv rtmp://127.0.0.1:1935/stream/cam1;
      exec_static ffmpeg -r 5 -fflags nobuffer -probesize 500000 -loglevel quiet -re -rtsp_transport tcp -i rtsp://127.0.0.1/cam2 -c copy -f flv rtmp://127.0.0.1:1935/stream/cam2;
    }
  }
}

Здесь происходит магия: ffmpeg берёт RTSP-поток с камеры, передаёт на ffserver, потом nginx рассылает через RTMP и HLS.


Как устроена страница просмотра онлайн

Чтобы не запускать тысячу приложений, видео показывается прямо в браузере с помощью HTML5-плеера Video.js.

Основные фишки:

  • Поддержка RTMP и HLS
  • Список камер в боковой панели
  • Автоматический запуск выбранного видео

Фрагмент JavaScript для динамического подгружения камер:

var base_url_rtmp = "rtmp://192.168.20.1/stream/";
var base_url_hls = "hls/";
var playlist = document.getElementById("playlist");
var player = videojs("player", { sourceOrder: true, techOrder: ["flash", "html5"] });

var getCameras = function() {
  getJSON(base_url_hls, function(err, data) {
    if(!err) {
      data.forEach(function(cam) {
        var link = document.createElement("a");
        link.textContent = cam.name;
        link.href = '#' + cam.name;
        link.dataset.camera = cam.name;
        link.onclick = function() {
          playCamera(this.dataset.camera);
          return false;
        };
        playlist.appendChild(link);
        playlist.appendChild(document.createElement("br"));
      });
    }
  });
};

var playCamera = function(camera) {
  player.src([
    { src: base_url_rtmp + camera, type: "rtmp/mp4" },
    { src: base_url_hls + camera + "/index.m3u8", type: "application/x-mpegURL" }
  ]);
  if(player.paused()) player.play();
};

getCameras();

Архив видео — как машина времени для вашего видеонаблюдения

Архив — это когда видео складывается в аккуратные папочки с датами и временем, чтобы потом можно было пересмотреть любое событие.

Настройка архива похожа на онлайн-просмотр, только пути другие, и добавляется логика для отображения файлов внутри папок камер.


Подсказки и советы для стабильной работы

  • Используйте -rtsp_transport tcp в ffmpeg для устойчивой передачи, особенно если камера и сервер в одной локалке.
  • Параметр probesize лучше увеличить (например, до 500000), если возникают сбои при подключении к потоку.
  • Опция nobuffer минимизирует задержки, но требует стабильного канала.
  • Для ffmpeg используйте -c copy, чтобы не перекодировать видео и снижать нагрузку на процессор.
  • Для высокой нагрузки выставьте MaxClients и MaxBandwidth в ffserver под ваши требования.

Итоговая таблица параметров для ffmpeg в системе

Параметр Значение Зачем нужен
-r 5 5 кадров в секунду Уменьшение нагрузки и размера видео
-fflags nobuffer Отключить буферизацию Снизить задержку
-probesize 500000 Размер буфера для анализа потока Увеличить стабильность соединения
-loglevel quiet Минимум логов Чистый вывод
-re Считывать вход как в реальном времени Избежать переполнения буфера
-rtsp_transport tcp Использовать TCP вместо UDP Надёжная передача
-c copy Копировать кодек без перекодирования Снизить нагрузку CPU

Заключение

Собрать систему видеонаблюдения с RTSP камерой, motion detection, и просмотром через nginx и ffmpeg — задача, в которой сочетаются чутьё инженера, волшебство командной строки и капля терпения. Но результат того стоит — живое видео с камер, архив с обнаружением движения и удобный просмотр в браузере.

Не нужно бояться команд exec_static, конфигов nginx и ffserver — это как выучить рецепт любимого блюда. Приготовите один раз — и сможете накормить целую армию своих видеокамер!


Погружайтесь в настройки, экспериментируйте и пусть ваш видеосервер работает как часы швейцарского мастера!