ОсновноеRadiotalkПользовательское
Общие вопросы по интернет радио вещанию
6   •   Посмотреть все темы

Графическая география слушателей (icecast)

 

468
Klef @Klef
Сначала хотел описать настройку жидкого мыла, по шагам, чтоб он умел танцевать джигу, выводить ведущих и варить кофе, но в ********** все давным давно описано, так что пройдем по извращениям.

Итак дорогой дружок, сейчас я научу тебя делать модною динамическую картинку для своего сайта, с отображением географии ваших радиослушателей. Вот такого рода:

Внимание: текущая картинка статичная, что бы не афишировать радиостанцию.

Никакой практической ценности эта вещь не несет, только увеличивает длину вашего детородного органа и возможность гармонично вставить картинку в дизайн сайта.

Итак, у нас есть боевой сервер icecast2 который радостно вещает на ваши сотни слушателей (ну или на пару друзей), если зайти в админку его, в раздел List Mountpoints, в нем посмотреть любой ваш маунт, то там можно увидеть список слушателей поименно ip, клиент, время подключения.
Важно: у вас должен быть доступ к админке icecast
Но как вы поняли эту информацию уже можно обрабатывать как угодно (например бы генерить карту гугла с метками). Но мы же хитрые телом, поэтому будем сами генерить карту, для этого нам понадобиться старая, добрая php-шная библиотека GD, если вы не забыли мы с ней уже **********. Ну и одна из самых важных частей, это база **********

Ну обо всем по порядку.

Во первых нам понадобится карта, на которой мы будем рисовать всякие пошлости. Но любая карта не подойдет, нам понадобиться карта в определенных пропорциях.
Например эта подойдет:


А эта уже нет:


Разницу думаю увидите сами. Самый грамотный способ, это нарисовать (или кого заставить) нарисовать карту в нужном вам графическом оформлении в соответствующих пропорциях (смотри пример), либо найти в интернете, но первый способ лучше ;)

база GeoIP, есть ********** для php, но он у меня вероломно отказался работать, так что воспользуемся "**********" набором скриптов от maxmind'a, которые и будем подключать к нашему скрипту.
Качаем чистое, располагаем в удобном месте, и подключаем в начале скрипта include ("geoipcity.inc");
Так же кроме собственно скриптов, которые работают с данными GeoIP нам собственно понадобиться бинарная база GeoIPCity, но так как она платная, а те что есть в свободном доступе малость уже устарели, то берем на офф сайте ********** для наших нужд ее хватит, но а для большего шика можно использовать пару баз: полную, но старую (найденную в свободных источниках (линки не дам, ищите)), и легкую, но крайнюю версию.

Для особо продвинутых пользователей рекомендую закинуть в крон скрип, который будет рахз в месяц (числах в 5-х) скачивать крайнюю версию с офф сайта.
Типа такого:

#!/bin/sh
cd /tmp
fetch **********
gunzip GeoLiteCity.dat.gz
mv -f GeoLiteCity.dat /usr/local/share/GeoIP
chmod 644 /usr/local/share/GeoIP/GeoLiteCity.dat

команды для скачивания и разархивирования рекомендую использовать привычные вам.

Перед тем как переходить к финальной стадии написания кода поделюсь с вами скриптом, который будет нам устраивать общение с icecast, да, я ленивая скотина, и не стал писать данный кусок кода а нашел на офф форуме icecast.
Автор данного кода W. Herrmann, о чем моно и прочитать в этом коде.
**********

Итак мы подготовились, карта, база GeoIP, php модули GeoIP, скрипт icecast.class разархивированы и расположены в удобном вам месте, вы вспомнили/узнали пароль от админки то можно приступать к самому интересному и фкусному, делаем скрипт генерации карты.

Дальше следует поток кода с комментариями:


<?php
error_reporting(1);
//сообщаем, что на выходе будет нет текст, а графика
header ("Content-type: image/png");
//подключаем внешнии скрипты
include("icecast.class.php");
include ("geoipcity.inc");
//создаем клас к которому будем обращатся
$icecast = new icecast();
//имя шрифта, надеюсь вы не забыли про него?
$font="ft.ttf";
//список маунтов, которые чекаються
$mount[]="radio";
$mount[]="music";
$mount[]="autorj";
//размер карты по ширине, т.к. мы работаем с координатами, то пропорции карты должны быть 360х180
//остальные параметры, зависащии от размеров, расчитываються
$glob_x=900;
$glob_y=$glob_x/2;
$koeficent=$glob_x/360;
//начинаем опрашивать маунта, ничто не мешает крутить по циклу и список серверов
//думаю параметры (хост, логин и пароль админки вы уже увидели куда вбивать)
for ($nom_mount=0;$nom_mount<count($mount);$nom_mount++) {
$icecast->host = "127.0.0.1";
$icecast->port = 8000;
$icecast->mount = $mount[$nom_mount];
$icecast->user = "admin";
$icecast->passwd = "hackme";
//запрашиваем нужные нам параметры
if ($icecast->openstats()) {
if ($icecast->GetStreamStatus()) {
$listeners = $icecast->GetListeners();
//если массив списка слушателей получен, то сортируем его (сортировать не обязательно)
if (is_array($listeners)) {
sort($listeners);
//обходим и записываем в массив IP адреса
for ($i=0;$i<sizeof($listeners);$i++) {
//массив $ip =)
$ip[] = $listeners[$i]["ip"];
}
}
}
}
}
//подключаемся к БД GeoIP
$gil = geoip_open("/usr/local/share/GeoIP/GeoLiteCity.dat", GEOIP_STANDARD);
$gif = geoip_open("/usr/local/share/GeoIP/GeoIPCity.dat", GEOIP_STANDARD);
//создаем первый "нулевой" элемент массивов координат
$array_coo[]="0,0";
$array_col[]=0;
//счетчик всего слушателей
$all=0;
//максимальное количество слушателей на координату
$maxal=0;
//опять сортруем и начинаем переберать результат
sort($ip);
for ($z=0;$z<count($ip);$z++) {
//сначало запрос к лайту, получаем координаты
$geoip = GeoIP_record_by_addr($gil,$ip[$z]);
//операция с коэфицентом карты (по отношению к 360) делаем чтоб в масиве у нас хранились округленные значения
$ipx=round(($geoip->latitude)*$koeficent)/$koeficent;
$ipy=round(($geoip->longitude)*$koeficent)/$koeficent;
//на всякий пожарный ^_^
$ipx=$ipx*1;
$ipy=$ipy*1;
//если лайт база нам вернула не очень интересные данные, нулевые координаты, или же неизвестный кород, то координаты "фейковый" (с точности до страны)
if ((($ipx==0) and ($ipy==0)) or (strlen($geoip->city)==0)) {
//тогда делаем запрос к полной базе (не забыли ее найти?)
$geoip = GeoIP_record_by_addr($gif,$ip[$z]);
//к ней работаем так же как и с лайт
$ipx=round(($geoip->latitude)*$koeficent)/$koeficent;
$ipy=round(($geoip->longitude)*$koeficent)/$koeficent;
$ipx=$ipx*1;
$ipy=$ipy*1;
}
//причем в массиве храним строку с долготой и широтой сразу, через запятую
$coord=$ipx.",".$ipy;
//ищем полученную координату в массиве координат, зачем нам создавать новый элемент, если с такими координатами уже есть
$pnom=array_search($coord,$array_coo);
if ($pnom==FALSE) {
//не нашли, тогда создаем
$array_coo[]=$coord;
$array_col[]=1;
if ($maxal<1) {$maxal=1;}
} else {
//нашли, тоже отлично, увеличиваем кол-во слушателей в этой точке
$array_col[$pnom]++;
//заодно проверяем это максимум тут или как
if ($maxal<$array_col[$pnom]) {$maxal=$array_col[$pnom];}
}
$all++;
}
//закрываем базы GeoIP дабы они нам более не требуються
geoip_close($gil);
geoip_close($gif);
//создаем png для работы из нашей карты
$img=imagecreatefrompng("map.png");
//выбираем цвет чернил, которыми будем рисовать
$ink = imagecolorallocate($img, 0, 0, 0);

//и перебираем массив координат
for ($i=0;$i<count($array_coo);$i++) {
//если в координате 0 слушателей, то не обрабатываем
if ($array_col[$i]!=0) {
//узнаем размер кружка
//у меня тут по хитрому, все кружки пропорциональны относительно самого большого
//кому не нравиться данная идея, используйте свой принцып
//$kolb это диаметр кружка
//для более гармоничного круга диаметр делайте кратным двум
$kolb=round($array_col[$i]*10/$maxal)*2+1;
//теперь нам больше не нужна запятая в координатах, разбираем на два элемента (широта и долгота)
$arc=split(",",$array_coo[$i]);
//соотвественно полученные координаты умножаем на коофицент, для более гармоничного рамположения на карте
$arc[0]=$arc[0]*$koeficent;
$arc[1]=$arc[1]*$koeficent;
//т.к. 0 на графике в левов верхнем, то творим еще и такие подсчеты
$smesh_x=$glob_x/2;
$smesh_y=$glob_y/2;
//рисуем таки кружок IMG_ARC_PIE - значит, что будет заливка
imagefilledarc($img,$smesh_x+$arc[1],$smesh_y-$arc[0],$kolb,$kolb,0,360,$ink,IMG_ARC_PIE);
}
}

//рисуем всякие надписи
imagettftext($img,8,0,20,20,$ink,$font,"Special 4 radiotalk");
imagettftext($img,8,0,20,36,$ink,$font,"GeoIP");
imagettftext($img,8,0,20,52,$ink,$font,"listeners: ".$all);
//у меня сервер по гринвичу. А у вас?
$dat=date("n/j/24y g:ia",time()+14400);
$mr=imagettfbbox (8,0, $font, $dat);
imagettftext($img,8,0,$glob_x-20-$mr[2],22,$ink,$font,$dat);
//черестрочный формат, не помешает
imageInterlace($img, 1);
//отдаем пользователю
imagepng($img);
//уничтожаем следы жизнидеятельности
imagedestroy($img);
?>


Результат работы кода:


Ну и традиционно: данный код лишь направление в котором следует изучать этот вопрос. Это базовый код. Много чего можно и нужно добавить. Так же каждый желающий может написать свой код, более оптимизирован, более красивый.

468
Klef @Klef
Еще насчет GeoIP
Точность Lite версии **********

30
Alexander @Alexander_Sizintsev
Klef пишет:

Еще насчет GeoIP
Точность Lite версии **********


что-то я попыался сделать, хрен что получилось... вот **********

30
Alexander @Alexander_Sizintsev
как лечить напасть?

6245
Тарас @tarasian666
у вас проблемы с генерированием изображения, точнее там вообще ничего не сгенерировалось, смотрите лог ошибок

30
Alexander @Alexander_Sizintsev
tarasian666 пишет:

у вас проблемы с генерированием изображения, точнее там вообще ничего не сгенерировалось, смотрите лог ошибок


Судя по логу, ошибка в 46 строке.

И вот что это:

//подключаемся к БД GeoIP
$gil = geoip_open("/usr/local/share/GeoIP/GeoLiteCity.dat", GEOIP_STANDARD);
$gif = geoip_open("/usr/local/share/GeoIP/GeoIPCity.dat", GEOIP_STANDARD);


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

6245
Тарас @tarasian666
а конкретно что пишет ошибка?

30
Alexander @Alexander_Sizintsev
tarasian666 пишет:

а конкретно что пишет ошибка?



[08-Oct-2012 12:14:19] PHP Fatal error: Call to undefined function geoip_open() in /php/geo/index.php on line 46

6245
Тарас @tarasian666
в php не включено или не установлено расширение geoip

30
Alexander @Alexander_Sizintsev
tarasian666 пишет:

в php не включено или не установлено расширение geoip


да вот в том-то и дело, что сказали что поставили =/

6245
Тарас @tarasian666
значит или не активировали или не перезапустили сервер после этого, так всегда )

30
Alexander @Alexander_Sizintsev
Вопрос есть: а эти GeoLiteCity.dat, GeoIPCity.dat устанавливаются вместе с расширением GeoIP???

6245
Тарас @tarasian666
вместе с geoip, но это не проблема, можно их самому скачать куда угодно

30
Alexander @Alexander_Sizintsev
tarasian666 пишет:

вместе с geoip, но это не проблема, можно их самому скачать куда угодно


А можете подсказать где скачать? ссылка на одну есть, а вот на вторую что-то нету =(

6245
Тарас @tarasian666
Для особо продвинутых пользователей рекомендую закинуть в крон скрип, который будет рахз в месяц (числах в 5-х) скачивать крайнюю версию с офф сайта.


и ниже код и ссылка

30
Alexander @Alexander_Sizintsev
tarasian666 пишет:

Для особо продвинутых пользователей рекомендую закинуть в крон скрип, который будет рахз в месяц (числах в 5-х) скачивать крайнюю версию с офф сайта.


и ниже код и ссылка


Блин что-то нихрена не выходит вообще =(

6245
Тарас @tarasian666
тогда учить мат часть )

30
Alexander @Alexander_Sizintsev
tarasian666 пишет:

тогда учить мат часть )


Я тебя умоляю...

Странно почему не пашет... =/ ладно тогда как хостер появится попробую решить =)

6245
Тарас @tarasian666
если ошибка прежняя - мучить хостера, если что то типа syntax error или not fount тогда искать причину

30
Alexander @Alexander_Sizintsev
tarasian666 пишет:

если ошибка прежняя - мучить хостера, если что то типа syntax error или not fount тогда искать причину



Это понятно. спс за помощь...