ОсновноеRadiotalkПользовательское
Технологии вещания, софт, скрипты
7   •   Посмотреть все темы

Нужен скрипт для извлечения названия играющего трека.

 

14
Тихон @uglion_ru
Что-то не могу нигде найти такой скрипт. Может кому встречался? Или хоть объясните, откуда берëтся информация о треке, попробую сам написать.

0
120
Александр @Aleksandr_Boyko
чем вещаете?

0
382
Grigorij @gyurgin_1
Есть несколько способов получения метаданных: парсить сайт или shoutcast / icecast статусные страницы непосредственно вещателя, получать непосредственно из потока, получать при помощи несложных инструментов от вещателя непосредственно. Первый - самый, шустрый и для вещателя безболезненный, второй достаточно нормален, но иногда может и не сработать, ну а третий сами понимаете подразумевает контакт с вещателем. Насколько я понял самый реальный два Вас способ номер два. в свое время был изобретен php script
  1. <?php
  2. function getMp3StreamTitle($streamingUrl, $interval, $offset = 0, $headers = true)
  3. {
  4. $needle = 'StreamTitle=';
  5. $ua = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36';
  6. $opts = array(
  7. 'http' => array(
  8. 'method' => 'GET',
  9. 'header' => 'Icy-MetaData: 1',
  10. 'user_agent' => $ua
  11. )
  12. );
  13. if (($headers = get_headers($streamingUrl)))
  14. foreach($headers as $h)
  15. if (strpos(strtolower($h) , 'icy-metaint') !== false && ($interval = explode(':', $h) [1])) break;
  16. $context = stream_context_create($opts);
  17. if ($stream = fopen($streamingUrl, 'r', false, $context))
  18. {
  19. $buffer = stream_get_contents($stream, $interval, $offset);
  20. fclose($stream);
  21. if (strpos($buffer, $needle) !== false)
  22. {
  23. $title = explode($needle, $buffer) [1];
  24. return substr($title, 1, strpos($title, ';') - 2);
  25. }
  26. else return getMp3StreamTitle($streamingUrl, $interval, $offset + $interval, false);
  27. }
  28. else throw new Exception("Unable to open stream [{$streamingUrl}]");
  29. }
  30. $url = $_REQUEST['url'];
  31. echo getMp3StreamTitle($url, 19200);
  32. ?>
что то в этом роде, у меня кстати как оказалось несколько таких до сих пор работают. По GET запросу с ?url=полный путь к потоку отдает title.
Примерно вот как тут: ********** (линком прошу не злоупотреблять).
В общем, надеюсь в нужном направлении подтолкнул...

Отредактировано gyurgin_1 - 17.07.2015
0
14
Тихон @uglion_ru
Aleksandr.Boyko пишет:

чем вещаете?


Александр, я не вещаю, у меня сайт для прослушивания радиостанций. Чтоб не плодить внешние линки, вот мой пост в разделе рекламы: **********

upd. Немного пообжился на форуме, привёл профиль в порядок. Теперь ссылку можно и в подписи посмотреть.

Я смотрю, что закинув радиопоток в винамп, он как-то извлекает названия треков, вот и задумался.

Отредактировано uglion_ru - 18.07.2015
0
14
Тихон @uglion_ru
gyurgin_1, большое спасибо, сегодня буду разбираться.

В программировании я хорошо шарю только в Delphi, поэтому сейчас испытываю сложности. Смотрите, скрипт я установил на свой сервер, он работает прекрасно: **********

Но как ответ сервера воткнуть вот в такую структуру я не понял:

<div>
// Здесь должен быть ответ сервера
</div>

Видимо это надо делать через ajax и вешать обновление по таймеру. Но у меня никак не получается :(

Отредактировано uglion_ru - 18.07.2015
0
14
Тихон @uglion_ru
В общем набросал следующий код:

  1. function createObject() {
  2. var request_type;
  3. var browser = navigator.appName;
  4. if(browser == "Microsoft Internet Explorer"){
  5. request_type = new ActiveXObject("Microsoft.XMLHTTP");
  6. }else{
  7. request_type = new XMLHttpRequest();
  8. }
  9. return request_type;
  10. }
  11. var http = createObject();
  12. function rad_trackname(){
  13. http.open('get', 'radio.uglion.ru/radio/gettrackname.php?url=http://online.radiorecord.ru:8102/dub_128');
  14. http.onreadystatechange = ServerReply;
  15. http.send(null);
  16. }
  17. function ServerReply() {
  18. if(http.readyState == 4){
  19. var response = http.responseText;
  20. if(response == ''){
  21. document.getElementById('track_name').innerHTML = 'Datas not found';
  22. } else {
  23. document.getElementById('track_name').innerHTML = response;
  24. }
  25. }
  26. }


В итоге получаю вместо названия песни Datas not found. Т.е. response = '' Я думал, что там должно быть название песни. В скрипте так вот: echo getMp3StreamTitle($url, 19200); При вызове через адресную строку всё возвращается как надо.

upd Продолжил копать. Оказалось, что http.status = 0, а не 200. В чём проблема?

upd2 Разобрался. Видимо всё дело было в кросс-доменных запросах. Если запускать с сервера, то работает.

Результат тут: **********

Завтра html поправлю, а то уже с ног валюсь. Всем спасибо за помощь. :)

Отредактировано uglion_ru - 18.07.2015
0
14
Тихон @uglion_ru
К сожалению данный метод работает не со всеми радиостанциями. Хотя винамп извлекает названия песен отовсюду, где эта информация есть. Например, отсюда: **********

0
14
Тихон @uglion_ru
Здравствуйте. Довольно долго уже терзает одна проблемка. Пользуюсь скриптом, выдёргивающим названия треков из потока. Скрипт работает и с SHOUTcast и с icecast. Однако с некоторыми потоками он всё-таки не справляется. Например вот с таким:

**********

Вместо названия трека выдаёт сразу кучу информации, включая само название.

А вот код скрипта:

  1. <?php
  2. define('CRLF', "\r\n");
  3. class streaminfo{
  4. public $valid = false;
  5. public $useragent = 'Winamp 2.81';
  6. protected $headers = array();
  7. protected $metadata = array();
  8. public function __construct($location){
  9. $errno = $errstr = '';
  10. $t = parse_url($location);
  11. if ( @!$t['port'] ) {
  12. $t['port'] = '80';
  13. }
  14. $sock = fsockopen($t['host'], $t['port'], $errno, $errstr, 5);
  15. $path = isset($t['path'])?$t['path']:'/';
  16. if ($sock){
  17. $request = 'GET '.$path.' HTTP/1.0' . CRLF .
  18. 'Host: ' . $t['host'] . CRLF .
  19. 'Connection: Close' . CRLF .
  20. 'User-Agent: ' . $this->useragent . CRLF .
  21. 'Accept: */*' . CRLF .
  22. 'icy-metadata: 1'.CRLF.
  23. 'icy-prebuffer: 65536'.CRLF.
  24. (isset($t['user'])?'Authorization: Basic '.base64_encode($t['user'].':'.$t['pass']).CRLF:'').
  25. 'X-TipOfTheDay: Winamp "Classic" rulez all of them.' . CRLF . CRLF;
  26. if (fwrite($sock, $request)){
  27. $theaders = $line = '';
  28. while (!feof($sock)){
  29. $line = fgets($sock, 4096);
  30. if('' == trim($line)){
  31. break;
  32. }
  33. $theaders .= $line;
  34. }
  35. $theaders = explode(CRLF, $theaders);
  36. foreach ($theaders as $header){
  37. $t = explode(':', $header);
  38. if (isset($t[0]) && trim($t[0]) != ''){
  39. $name = preg_replace('/[^a-z][^a-z0-9]*/i','', strtolower(trim($t[0])));
  40. array_shift($t);
  41. $value = trim(implode(':', $t));
  42. if ($value != ''){
  43. if (is_numeric($value)){
  44. $this->headers[$name] = (int)$value;
  45. }else{
  46. $this->headers[$name] = $value;
  47. }
  48. }
  49. }
  50. }
  51. if (!isset($this->headers['icymetaint'])){
  52. $data = ''; $metainterval = 512;
  53. while(!feof($sock)){
  54. $data .= fgetc($sock);
  55. if (strlen($data) >= $metainterval) break;
  56. }
  57. $this->print_data($data);
  58. $matches = array();
  59. preg_match_all('/([\x00-\xff]{2})\x0\x0([a-z]+)=/i', $data, $matches, PREG_OFFSET_CAPTURE);
  60. preg_match_all('/([a-z]+)=([a-z0-9\(\)\[\]., ]+)/i', $data, $matches, PREG_SPLIT_NO_EMPTY);
  61. echo '<pre>';var_dump($matches);echo '</pre>';
  62. $title = $artist = '';
  63. foreach ($matches[0] as $nr => $values){
  64. $offset = $values[1];
  65. $length = ord($values[0]{0}) +
  66. (ord($values[0]{1}) * 256)+
  67. (ord($values[0]{2}) * 256*256)+
  68. (ord($values[0]{3}) * 256*256*256);
  69. $info = substr($data, $offset + 4, $length);
  70. $seperator = strpos($info, '=');
  71. $this->metadata[substr($info, 0, $seperator)] = substr($info, $seperator + 1);
  72. if (substr($info, 0, $seperator) == 'title') $title = substr($info, $seperator + 1);
  73. if (substr($info, 0, $seperator) == 'artist') $artist = substr($info, $seperator + 1);
  74. }
  75. $this->metadata['streamtitle'] = $artist . ' - ' . $title;
  76. }else{
  77. $metainterval = $this->headers['icymetaint'];
  78. $intervals = 0;
  79. $metadata = '';
  80. while(1){
  81. $data = '';
  82. while(!feof($sock)){
  83. $data .= fgetc($sock);
  84. if (strlen($data) >= $metainterval) break;
  85. }
  86. $len = join(unpack('c', fgetc($sock))) * 16;
  87. if ($len > 0){
  88. $metadata = str_replace("\0", '', fread($sock, $len));
  89. break;
  90. }else{
  91. $intervals++;
  92. if ($intervals > 100) break;
  93. }
  94. }
  95. $metarr = explode(';', $metadata);
  96. foreach ($metarr as $meta){
  97. $t = explode('=', $meta);
  98. if (isset($t[0]) && trim($t[0]) != ''){
  99. $name = preg_replace('/[^a-z][^a-z0-9]*/i','', strtolower(trim($t[0])));
  100. array_shift($t);
  101. $value = trim(implode('=', $t));
  102. if (substr($value, 0, 1) == '"' || substr($value, 0, 1) == "'"){
  103. $value = substr($value, 1);
  104. }
  105. if (substr($value, -1) == '"' || substr($value, -1) == "'"){
  106. $value = substr($value, 0, -1);
  107. }
  108. if ($value != ''){
  109. $this->metadata[$name] = $value;
  110. }
  111. }
  112. }
  113. }
  114. fclose($sock);
  115. $this->valid = true;
  116. }else echo 'unable to write.';
  117. }else echo 'no socket '.$errno.' - '.$errstr.'.';
  118. }
  119. public function print_data($data){
  120. $data = str_split($data);
  121. $c = 0;
  122. $string = '';
  123. echo "<pre>\n000000 ";
  124. foreach ($data as $char){
  125. $string .= addcslashes($char, "\n\r\0\t");
  126. $hex = dechex(join(unpack('C', $char)));
  127. if ($c % 4 == 0) echo ' ';
  128. if ($c % (4*4) == 0 && $c != 0){
  129. foreach (str_split($string) as $s){
  130. if (ord($s) < 32 || ord($s) > 126){
  131. echo '\\'.ord($s);
  132. }else{
  133. echo $s;
  134. }
  135. }
  136. echo "\n";
  137. $string = '';
  138. echo str_pad($c, 6, '0', STR_PAD_LEFT).' ';
  139. }
  140. if (strlen($hex) < 1) $hex = '00';
  141. if (strlen($hex) < 2) $hex = '0'.$hex;
  142. echo $hex.' ';
  143. $c++;
  144. }
  145. echo " $string\n</pre>";
  146. }
  147. public function __get($name){
  148. if (isset($this->metadata[$name])){
  149. return $this->metadata[$name];
  150. }
  151. if (isset($this->headers[$name])){
  152. return $this->headers[$name];
  153. }
  154. return null;
  155. }
  156. }
  157. $url = $_REQUEST['url'];
  158. $t = new streaminfo($url); // get metadata
  159. if ( mb_detect_encoding($t->streamtitle, 'UTF-8,Windows-1251') == 'Windows-1251') {
  160. echo iconv( "Windows-1251","UTF-8", $t->streamtitle);
  161. }
  162. else {
  163. echo $t->streamtitle;
  164. }
  165. ?>


Подскажите, как побороть проблему?

0
419
gyurgin_ @gyurgin_
Выдачу покажите, выдернем что надо.

0
2
paradice @paradice
уже есть у кого то подобие универсального скрипта для этой задачи? :-) поделитесь пожалуйста

0
419
gyurgin_ @gyurgin_
Да есть, но дергать таким образом метаданные не то чтобы не хорошо, даже совсем плохо.
Сотня слушателей принапряжет сервер, тысячя просто нагнет.
Нужен скрипт - обработчик, ну api, как его не назови, смысл один.
Надо - я покажу как.

0
95
Rodos @Rodos
Мое интернет радио вещает по цепочке RadioBoss > ********** > ********** и я не доволен тем, что названия песен (в том числе русские) не отображаются на веб-плеере. Видны только английские названия песен. Пытался вместо RadioBoss трансляцию вести через плеер Winamp. Но в этом случае даже английские названия песен пропадают (их нет на веб-плеере). Все тэги в моих песнях надписаны. Вот посмотрите сами. Как можно исправить кодировку, чтобы все языки отображались?
Наткнулся на такое сообщение ********** и такую **********, но пока не рискую ничего делать. У кого есть опыт, посоветуйте, как мне исправить кодировку.

uglion.ru, сайт ********** просто ретранслирует имеющееся радио или является хостингом (аналогией сервера Shoutcast)? Свю проблему с неотбражением русских тэгов я описал выше. Если знаете решение ,поделитесь. Кстати, откуда вы берете этот код и можно ли через него поменять кодировку?

Отредактировано Rodos - 06.10.2016
0
156
Eugene @MechanisM
Если речь идет об Icecast - пока я использую самый идеальный вариант для получения имен треков - Icecast сам их шлет серверу когда они меняются и делает это для каждого маунта, сервер кладет в базу данных все данные. Да, я реализовал свой собственный yp-directory. Кроме названий треков он еще шлет кол-во слушателей и другую инфу(практически всю по каждому маунту).
И для этого всего-то нужно:
  1.  
  2. <directory>
  3. <yp-url-timeout>15</yp-url-timeout>
  4. <yp-url>https://your-server.radio/yp</yp-url>
  5. </directory>

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

Отредактировано MechanisM - 22.10.2016
0
419
gyurgin_ @gyurgin_
Ну это для цивильного радиокаталога, топикстартер тут без спросу хочет на свой сайт потоки подключить. Потому, к примеру от меня можно помощи не ждать.
Кроме названий треков он еще шлет кол-во слушателей и другую инфу(практически всю по каждому маунту).

Подтягиваете данные или реально шлет еще что то кроме метаданных, количества и "add", "remove", "touch" ? Что то я там не наблюдал больше ничего...

0
95
Rodos @Rodos
Двумя постами выше я описал свою проблему. Убедившись в том что причиной отсуствия русских и на других языках (кроме английского) названий песен является сервер Shoutcast 1 перешел на Shoutcast 2. Сейчас в Панели администратора названия на всех языках корректно отображаются. Нажимаю в панели админа кнопку URL потока и мое радио звучит. Однако на ********** мое радио уже не находится по поиску в отличии от прошлого (хотя название то же), а в других каталогах радио (сайтах) на веб-плеере оно хоть звучит, но по-прежнему не видны названия песен на других (кроме английского) языках. Там отображаются вопросительные знаки вместо букв. Что надо еще переключить или пoменять в настройках чтобы был полный порядок?

0





Согласие на обработку данных на нашем сайте

Продолжая просматривать страницу, вы соглашаетесь с использованием файлов «Cookie» и с Политикой конфиденциальности «Privacy».
Наверху или внизу страницы вы можете изменить валюту и язык по умолчанию. Английская версия сайта ещё находится в доработке и доступна не полностью.