Перейти к основному содержимому

06-06-02 Интеграция FFMPEG в автоматизированные системы

06-06-02

В предыдущих частях лекции мы рассматривали FFMPEG как мощный инструмент для обработки и трансляции видео, способный работать с сетевыми протоколами, перекодировать потоки и накладывать графику. Однако в реальных видеосистемах FFMPEG редко используется как одноразовая команда, запущенная вручную. Гораздо чаще он становится постоянной частью инфраструктуры — работающим в фоне процессом, управляющим множеством видеопотоков, реагирующим на события и интегрированным в более крупные системы.

В этом разделе мы рассмотрим, как FFMPEG можно интегрировать в автоматизированные среды, чтобы он работал надёжно, масштабируемо и устойчиво к сбоям.


Запуск FFMPEG через службы и скрипты

Для того чтобы FFMPEG работал постоянно, а не только по требованию, его нужно запускать как системную службу или фоновый процесс, который автоматически стартует при загрузке системы и перезапускается при сбоях.

Использование systemd (Linux)

В Linux-системах наиболее надёжный способ — использовать systemd, системный менеджер служб. Он позволяет:

  • Автоматически запускать FFMPEG при загрузке;
  • Перезапускать процесс при падении;
  • Логировать вывод;
  • Контролировать ресурсы (CPU, память, сеть).

Пример файла службы /etc/systemd/system/ffmpeg-camera.service:

[Unit]
Description=FFMPEG stream from IP camera
After=network.target

[Service]
Type=simple
User=video
ExecStart=/usr/bin/ffmpeg -rtsp_transport tcp -i rtsp://192.168.1.100:554/stream1 -c copy -f flv rtmp://cdn.example.com/live/cam1
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

После сохранения файла нужно выполнить:

sudo systemctl daemon-reexec
sudo systemctl enable ffmpeg-camera.service
sudo systemctl start ffmpeg-camera.service

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

journalctl -u ffmpeg-camera.service -f

Пример из практики: на видеонаблюдательной станции 20 камер транслируются через FFMPEG на облачный сервер. Каждая камера — отдельная systemd-служба. При обрыве сети или перезагрузке камеры служба автоматически перезапускает FFMPEG и восстанавливает стрим.

Использование Windows Services

В Windows аналогичную функцию выполняют службы Windows. Для запуска FFMPEG как службы можно использовать утилиты вроде NSSM (Non-Sucking Service Manager) или WinSW.

Пример с NSSM:

  1. Скачать и установить NSSM.
  2. Запустить nssm install FFMPEG_Camera.
  3. Указать:
    • Путь к ffmpeg.exe
    • Аргументы: -i rtsp://... -f flv rtmp://...
    • Рабочую папку
  4. Установить тип перезапуска: «Restart the service» с задержкой 5 секунд.

Теперь служба будет запускаться при старте Windows и перезапускаться при сбоях.

Важно: в Windows также стоит настроить мониторинг потребления ресурсов, особенно при работе с несколькими потоками — FFMPEG может занимать значительную часть CPU.


Управление процессами: перезапуск и циклический опрос

Даже при использовании служб FFMPEG может «зависнуть» или потерять соединение с источником (например, при сетевом сбое). Поэтому важно реализовать логику управления процессами.

Перезапуск при ошибках

systemd и Windows Services уже включают базовую логику перезапуска, но иногда требуется более сложное поведение:

  • Перезапуск только после определённого типа ошибки (например, не при выходе с кодом 0);
  • Задержка перед перезапуском (чтобы не «бомбить» источник);
  • Ограничение числа перезапусков за период (чтобы избежать бесконечного цикла при постоянной ошибке).

Пример настройки в systemd:

Restart=always
RestartSec=10
StartLimitInterval=60
StartLimitBurst=3

Это означает: перезапускать всегда, с задержкой 10 секунд, но не более 3 раз за 60 секунд. Если лимит превышен — служба отключается.

Циклический опрос камер

В системах видеонаблюдения или трансляций может потребоваться динамически подключаться к камерам — например, по расписанию, при срабатывании датчика или при запросе пользователя.

Для этого используется скрипт, который:

  1. Получает список активных камер (из базы, API, конфигурационного файла);
  2. Проверяет, запущен ли FFMPEG для каждой из них;
  3. Запускает или останавливает процесс при необходимости.

Пример на Python:

import subprocess
import psutil

def is_ffmpeg_running(url):
for proc in psutil.process_iter(['pid', 'cmdline']):
if proc.info['cmdline'] and 'ffmpeg' in proc.info['cmdline']:
if url in ' '.join(proc.info['cmdline']):
return True
return False

def start_stream(rtsp_url, rtmp_output):
if not is_ffmpeg_running(rtsp_url):
cmd = [
'ffmpeg', '-rtsp_transport', 'tcp', '-i', rtsp_url,
'-c', 'copy', '-f', 'flv', rtmp_output
]
subprocess.Popen(cmd)

Такой скрипт можно запускать по расписанию (через cron) или в виде веб-сервиса, принимающего команды.

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


Использование wrapper’ов и библиотек для динамического управления

Ручной вызов ffmpeg через командную строку удобен для тестирования, но в автоматизированных системах лучше использовать программные обёртки, которые позволяют:

  • Динамически формировать команды;
  • Контролировать выполнение;
  • Обрабатывать ошибки;
  • Интегрировать с веб-интерфейсами и API.

Python и subprocess

Самый простой способ — использовать модуль subprocess в Python:

import subprocess

cmd = [
'ffmpeg',
'-i', 'rtsp://camera1/stream',
'-vf', 'drawtext=text=Camera1:x=10:y=10',
'-c:v', 'libx264',
'-f', 'flv',
'rtmp://server/live/stream1'
]

process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = process.communicate()

Это даёт полный контроль над запуском и выводом.

Для более сложных сценариев можно использовать библиотеки вроде ffmpeg-python, которая позволяет строить команды в виде цепочек методов:

import ffmpeg

(
ffmpeg
.input('rtsp://camera1/stream')
.drawtext(text='Camera 1', x=10, y=10)
.output('rtmp://server/live/stream1', vcodec='libx264', format='flv')
.run()
)

Node.js и REST-обёртки

В веб-приложениях часто используют Node.js. Здесь можно запускать FFMPEG через child_process или использовать готовые npm-пакеты, например fluent-ffmpeg.

Более продвинутый подход — создать REST API, который принимает параметры стрима и запускает FFMPEG.

Пример на Express:

const express = require('express');
const { spawn } = require('child_process');
const app = express();

app.post('/start-stream', (req, res) => {
const { input, output } = req.body;
const ffmpeg = spawn('ffmpeg', ['-i', input, '-c', 'copy', '-f', 'flv', output]);

ffmpeg.stderr.on('data', (data) => {
console.log(`FFMPEG: ${data}`);
});

res.send('Stream started');
});

Теперь любой клиент (веб-интерфейс, мобильное приложение) может управлять FFMPEG через HTTP-запросы.

Пример: видеоплатформа для онлайн-конференций. Администратор через веб-интерфейс выбирает источник (камера, презентация) и назначает выход (CDN, запись). Система формирует команду FFMPEG и запускает её через REST-сервис.

Преимущества wrapper’ов

ПреимуществоПояснение
Динамическая генерация командМожно формировать команды на основе пользовательского ввода, конфигураций, API.
Обработка ошибокЛегко перехватывать и логировать ошибки, предпринимать действия (перезапуск, уведомление).
Интеграция с системами мониторингаМожно отправлять метрики (CPU, задержка, статус) в Prometheus, Grafana и др.
МасштабируемостьОдин скрипт может управлять десятками FFMPEG-процессов.

Заключение

Интеграция FFMPEG в автоматизированные системы превращает его из утилиты командной строки в надёжный, управляемый компонент видеоплатформы. Использование служб, скриптов, wrapper’ов и API позволяет:

  • Обеспечить непрерывную работу;
  • Реагировать на события;
  • Масштабировать на десятки и сотни потоков;
  • Интегрировать с другими частями инфраструктуры.