Мониторинг IPTV

в 7:06, , рубрики: ffmpeg, iptv, linkedin, linux, Работа с видео

Возникла необходимость проводить мониторинг мультикаст потоков. Начался поиск готовых решений. Первое что удалось нагуглить: IPTV-Analyzer, NetUP IPTVProbe. У каждого решения были свои недостатки или стоили немалых денег. Было принято решение создать свой собственный мониторинг. Основная задача уведомлять и логировать падение мультикаст потока.

Механизм:
С помощью ffmpeg подключаемся к потоку в течение NN времени, кадр начинает снимать с NN секунды, чтобы не было артефактов на картинке. Если в течение NN секунд не получается что-то получить, то пишем в базу с ошибкой снятия. Все довольно просто.

Приступим к установке основных компонентов:
sudo apt-get install apache2 php5 mysql-server libapache2-mod-php5 libapache2-mod-auth-mysql php5-mysql ffmpeg

apache – для web-интерфейса.
mysql — в базе будем хранить данные, необходимые для статистики, и список каналов.
ffmpeg – нам будет необходим для снятия скриншотов с мультикаст-потока.

Основные компоненты установлены, приступим к настройке.

В директории (по умолчанию используемая apache2 /var/www/ ) создаем файл dbinit.php c настройками подключения к базе:

<?php
$dbhost = "localhost";
$dbname = "name";
$dbuser = "user";
$dbpass = "password";
mysql_connect($dbhost, $dbuser, $dbpass);
mysql_query("set character_set_client='utf8'");
mysql_query("set character_set_results='utf8'");
mysql_query("set collation_connection='utf8_general_ci'");
mysql_select_db($dbname);
?>

Структура базы:
date – TIMESTAMP (Дата падения или поднятия канала)
name – TEXT (Имя канала)
state – TEXT (Состояние: true-поднятие, false-падение)

Необходимо это для дальнейшего расчета сколько времени канал был в дауне.

Создаем скрипт, который будет генерировать ну и, собственно, «мониторить» каналы.
Назовем его gen.php

<?php
include "dbinit.php";
$query = "SELECT * FROM `name`";
$result = mysql_query($query);

if (!$result) { print "ошибка:" . mysql_error() . ""; }
elseif (mysql_num_rows($result) == 0) { print ""; }
else {
$rows = array();
while ($row = mysql_fetch_assoc($result)) { $rows[]= $row; }
foreach($rows as $row) {
echo exec('/usr/bin/timeout 20s /usr/bin/time -f %U -o /var/www/tmp/'.$row['name'].'.txt /usr/bin/ffmpeg -i udp://@'.$row['mcast'].' -y -f image2 -sameq -t 0.001 -ss 00:00:4 -s 120*80 /var/www/screen/'.$row['mcast'].'.jpg');
echo exec('/bin/cp -f /var/www/tmp/'.$row['mcast'].'.txt /var/www/rez/');
}
}
?>

Рассмотрим подробнее строки скрипта.
Для выполнения скрипта ставим таймаут выполнения (timeout 20s ), если канал будет недоступен — он будет висеть очень долго.
Время снятия скриншота пишем в файл: /usr/bin/time -f %U -o /var/www/tmp/'.$row['name'].'.txt
Снятие скриншота /usr/bin/ffmpeg -i udp://@'.$row['name'].' -y -f image2 -sameq -t 0.001 -ss 00:00:4 -s 120*80 /var/www/screen/'.$row['name'].'.jpg

Получение результатов и добавление их в базу:
Создадим файл rez.php

$lines = file ('rez/'.$row['mcast'].'.txt');
if ($lines[0]=='') {
$last_result=mysql_result(mysql_query("select state from name where name='".$row['name']."' order by date desc limit 0,1"),0);
if($last_result=='true') {
$query = "INSERT INTO `name` (`date`, `name`, `state`) VALUES ('{$date}', '{$row['name']}', 'false');";
mysql_query($query) or die(mysql_error()); }
foreach ($A as $v) {
echo exec('/usr/bin/perl /usr/local/scripts/jabber_alert.pl -e '.$v.'jabber.server -n tv@jabber.server -w 5password -y '.translitIt ($row['name']).'-'.$row['mcast'].' << "EOF" read -d "^D" input'); } } else {
$last_result=mysql_result(mysql_query("select state from name where name='".$row['name']."' order by date desc limit 0,1"),0);
echo $last_result;
if($last_result=='false') {
$query = "INSERT INTO `name` (`date`, `name`, `state`) VALUES ('{$date}', '{$row['name']}', 'true');";
mysql_query($query) or die(mysql_error()); }
echo $row['name']." ". $lines[1]."Работает "; } } }

При удачном снятии скриншота время выполнения записывается в файл, если не получилось файл будет пустой. В скрипте выполняем проверку на содержимое в файле.

Рассылаем по джаберу о упавшем канале
echo exec('/usr/bin/perl /usr/local/scripts/jabber_alert.pl -e '.$v.'jabber.server -n tv@jabber.server -w password -y '.translitIt ($row['name']).'-'.$row['mcast'].' << "EOF" read -d "^D" input');

jabber_alert.pl

Создаем index.php

foreach($rows as $row)
{
$work=mysql_result(mysql_query("select date from name where date>'".$row['date']." order by date limit 0,1'"),0);
$date1 = new DateTime($work);
$date2 = new DateTime($row['date']);
$interval = $date2->diff($date1);
if($work=="") { $style="red"; } else { $style=""; }
echo "

".$row['date'];
if($work!="") { echo "
- ".$work.""; }
echo " ";
if($interval->format("%h") != 0) { echo $interval->format("%hч. "); }
echo $interval->format("%iм. %sс.")." ".$row['name']."

";
}

Выводим упавшие/поднятые каналы и раскрашиваем их.

Добавляем в крон выполнение двух скриптов.
Решение не столь изящно, но оно работает и свои задачи выполняет.

Доработав можно получить такое:

Мониторинг IPTV

Автор: bigvc

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js