Как стать автором
Обновить

Мониторинг IPTV

Время на прочтение4 мин
Количество просмотров31K
Возникла необходимость проводить мониторинг мультикаст потоков. Начался поиск готовых решений. Первое что удалось нагуглить: 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 "<center>ошибка:" . mysql_error() . "</center>"; 
}
    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


<?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 password -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


<?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 "<tr><td style='color:".$style."'><font color='red'>".$row['date'];
    if($work!="") 
{
    echo "</font> - <font color='green'>".$work."</font>"; 
}
    echo "</td><td>";
    if($interval->format("%h") != 0)
{
    echo $interval->format("%hч. ");
}
    echo $interval->format("%iм. %sс.")."</td><td style='color:".$style."'>".$row['name']."</td></tr>";
}

?>

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

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

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

Теги:
Хабы:
Всего голосов 24: ↑21 и ↓3+18
Комментарии12

Публикации

Истории

Работа

Ближайшие события

Антиконференция X5 Future Night
Дата30 мая
Время11:00 – 23:00
Место
Онлайн
OTUS CONF: GameDev
Дата30 мая
Время19:00 – 20:30
Место
Онлайн
Конференция «IT IS CONF 2024»
Дата20 июня
Время09:00 – 19:00
Место
Екатеринбург
Summer Merge
Дата28 – 30 июня
Время11:00
Место
Ульяновская область