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

В предыдущих частях лекции мы рассматривали 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:
- Скачать и установить NSSM.
- Запустить
nssm install FFMPEG_Camera. - Указать:
- Путь к
ffmpeg.exe - Аргументы:
-i rtsp://... -f flv rtmp://... - Рабочую папку
- Путь к
- Установить тип перезапуска: «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 секунд. Если лимит превышен — служба отключается.
Циклический опрос камер
В системах видеонаблюдения или трансляций может потребоваться динамически подключаться к камерам — например, по расписанию, при срабатывании датчика или при запросе пользователя.
Для этого используется скрипт, который:
- Получает список активных камер (из базы, API, конфигурационного файла);
- Проверяет, запущен ли FFMPEG для каждой из них;
- Запускает или останавливает процесс при необходимости.
Пример на 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 позволяет:
- Обеспечить непрерывную работу;
- Реагировать на события;
- Масштабировать на десятки и сотни потоков;
- Интегрировать с другими частями инфраструктуры.