php
  • audio-streaming
  • shoutcast
  • icecast
  • 2013-04-04 86 views 4 likes 
    4

    我發現了一個腳本,可以從Icecast或Shoutcast流中提取藝術家&標題名稱。 我希望腳本在歌曲改變時自動更新,此時它的工作只在我執行時進行。我是PHP的新手,所以任何幫助將不勝感激。 謝謝!PHP腳本從Shoutcast/Icecast流中提取藝術家和標題

    define('CRLF', "\r\n"); 
    
    class streaminfo{ 
    public $valid = false; 
    public $useragent = 'Winamp 2.81'; 
    
    protected $headers = array(); 
    protected $metadata = array(); 
    
    public function __construct($location){ 
        $errno = $errstr = ''; 
        $t = parse_url($location); 
        $sock = fsockopen($t['host'], $t['port'], $errno, $errstr, 5); 
        $path = isset($t['path'])?$t['path']:'/'; 
        if ($sock){ 
         $request = 'GET '.$path.' HTTP/1.0' . CRLF . 
          'Host: ' . $t['host'] . CRLF . 
          'Connection: Close' . CRLF . 
          'User-Agent: ' . $this->useragent . CRLF . 
          'Accept: */*' . CRLF . 
          'icy-metadata: 1'.CRLF. 
          'icy-prebuffer: 65536'.CRLF. 
          (isset($t['user'])?'Authorization: Basic '.base64_encode($t['user'].':'.$t['pass']).CRLF:''). 
          'X-TipOfTheDay: Winamp "Classic" rulez all of them.' . CRLF . CRLF; 
         if (fwrite($sock, $request)){ 
          $theaders = $line = ''; 
          while (!feof($sock)){ 
           $line = fgets($sock, 4096); 
           if('' == trim($line)){ 
            break; 
           } 
           $theaders .= $line; 
          } 
          $theaders = explode(CRLF, $theaders); 
          foreach ($theaders as $header){ 
           $t = explode(':', $header); 
           if (isset($t[0]) && trim($t[0]) != ''){ 
            $name = preg_replace('/[^a-z][^a-z0-9]*/i','', strtolower(trim($t[0]))); 
            array_shift($t); 
            $value = trim(implode(':', $t)); 
            if ($value != ''){ 
             if (is_numeric($value)){ 
              $this->headers[$name] = (int)$value; 
             }else{ 
              $this->headers[$name] = $value; 
             } 
            } 
           } 
          } 
          if (!isset($this->headers['icymetaint'])){ 
           $data = ''; $metainterval = 512; 
           while(!feof($sock)){ 
            $data .= fgetc($sock); 
            if (strlen($data) >= $metainterval) break; 
           } 
           $this->print_data($data); 
           $matches = array(); 
           preg_match_all('/([\x00-\xff]{2})\x0\x0([a-z]+)=/i', $data, $matches, PREG_OFFSET_CAPTURE); 
           preg_match_all('/([a-z]+)=([a-z0-9\(\)\[\]., ]+)/i', $data, $matches, PREG_SPLIT_NO_EMPTY); 
           echo '<pre>';var_dump($matches);echo '</pre>'; 
           $title = $artist = ''; 
           foreach ($matches[0] as $nr => $values){ 
            $offset = $values[1]; 
            $length = ord($values[0]{0}) + 
              (ord($values[0]{1}) * 256)+ 
              (ord($values[0]{2}) * 256*256)+ 
              (ord($values[0]{3}) * 256*256*256); 
            $info = substr($data, $offset + 4, $length); 
            $seperator = strpos($info, '='); 
            $this->metadata[substr($info, 0, $seperator)] = substr($info, $seperator + 1); 
            if (substr($info, 0, $seperator) == 'title') $title = substr($info, $seperator + 1); 
            if (substr($info, 0, $seperator) == 'artist') $artist = substr($info, $seperator + 1); 
           } 
           $this->metadata['streamtitle'] = $artist . ' - ' . $title; 
          }else{ 
           $metainterval = $this->headers['icymetaint']; 
           $intervals = 0; 
           $metadata = ''; 
           while(1){ 
            $data = ''; 
            while(!feof($sock)){ 
             $data .= fgetc($sock); 
             if (strlen($data) >= $metainterval) break; 
            } 
            //$this->print_data($data); 
            $len = join(unpack('c', fgetc($sock))) * 16; 
            if ($len > 0){ 
             $metadata = str_replace("\0", '', fread($sock, $len)); 
             break; 
            }else{ 
             $intervals++; 
             if ($intervals > 100) break; 
            } 
           } 
           $metarr = explode(';', $metadata); 
           foreach ($metarr as $meta){ 
            $t = explode('=', $meta); 
            if (isset($t[0]) && trim($t[0]) != ''){ 
             $name = preg_replace('/[^a-z][^a-z0-9]*/i','', strtolower(trim($t[0]))); 
             array_shift($t); 
             $value = trim(implode('=', $t)); 
             if (substr($value, 0, 1) == '"' || substr($value, 0, 1) == "'"){ 
              $value = substr($value, 1); 
             } 
             if (substr($value, -1) == '"' || substr($value, -1) == "'"){ 
              $value = substr($value, 0, -1); 
             } 
             if ($value != ''){ 
              $this->metadata[$name] = $value; 
             } 
            } 
           } 
          } 
          fclose($sock); 
          $this->valid = true; 
         }else echo 'unable to write.'; 
        }else echo 'no socket '.$errno.' - '.$errstr.'.'; 
    } 
    
    
    public function print_data($data){ 
        $data = str_split($data); 
        $c = 0; 
        $string = ''; 
        echo "<pre>\n000000 "; 
        foreach ($data as $char){ 
         $string .= addcslashes($char, "\n\r\0\t"); 
         $hex = dechex(join(unpack('C', $char))); 
         if ($c % 4 == 0) echo ' '; 
         if ($c % (4*4) == 0 && $c != 0){ 
          foreach (str_split($string) as $s){ 
          //echo " $string\n"; 
          if (ord($s) < 32 || ord($s) > 126){ 
           echo '\\'.ord($s); 
          }else{ 
           echo $s; 
          } 
          } 
          echo "\n"; 
          $string = ''; 
          echo str_pad($c, 6, '0', STR_PAD_LEFT).' '; 
         } 
         if (strlen($hex) < 1) $hex = '00'; 
         if (strlen($hex) < 2) $hex = '0'.$hex; 
          echo $hex.' '; 
         $c++; 
        } 
        echo " $string\n</pre>"; 
    } 
    
    public function __get($name){ 
        if (isset($this->metadata[$name])){ 
         return $this->metadata[$name]; 
        } 
        if (isset($this->headers[$name])){ 
         return $this->headers[$name]; 
        } 
        return null; 
    } 
    } 
    
    $t = new streaminfo('http://64.236.34.196:80/stream/1014'); // get metadata 
    
    
    echo Meta Interval: $t->icymetaint; 
    echo Current Track: $t->streamtitle; 
    
    +0

    感謝這個腳本。我只是繼續找到解析流數據HTML頁面的內容,這些內容可能會與未來版本的Icecast/Shoutcast打交道。 (參考:http://stackoverflow.com/questions/25268050/php-icecast-now-playing-script-is-not-working/25344443#25344443) – 2015-02-17 01:33:19

    回答

    0

    您將需要不斷地以設定的時間間隔查詢流以查找歌曲何時改變。

    這可以通過安排cron工作來完成。 如果在Windows上,你應該如果你想運行PHP腳本,讓您的元數據是最新的(我假設你正在做一個網站,並在這裏使用HTML音頻標籤),您可以使用Windows Task Scheduler

    +0

    我怎樣才能設置間隔與PHP? – 2013-04-04 06:42:39

    +1

    使用cron,查看更新後的答案。 – 2013-04-04 07:24:09

    +0

    我可以在Windows機器上使用cron嗎? – 2013-04-04 08:12:03

    0

    使用帶有ajax函數的ontimeupdate事件。如果你不是,你可能應該查看你的音頻播放文檔的類似。

    <audio src="http://ip:port/;" ontimeupdate="loadXMLDoc()"> 
    

    你可以找到一個很好的例子,在這裏http://www.w3schools.com/php/php_ajax_php.asp

    你想一次使用PHP回聲功能的所有相關信息使用一個PHP變量在腳本的最末端。

    <?php .... 
    $phpVar=$streamtitle; 
    $phpVar2=$streamsong; 
    $result="I want my string to look like this: <br> {$phpVar} {$phpVar2}"; 
    echo $result; 
    ?> 
    

    ,然後使用由.onreadystatechange調用的函數使用.resonseText來修改你的網站,你想要的特定元素(這將包含相同的內容,你的PHP腳本的回波)。

    0

    將網頁刷新4小時後,這是我發現的唯一Shoutcast元數據腳本!謝謝。

    爲了不斷運行,爲什麼不使用setInterval和jQuery的AJAX調用結合?

    <script> 
    $(function() { 
        setInterval(getTrackName,16000); 
    }); 
    
    function getTrackName() { 
        $.ajax({ 
        url: "track_name.php" 
        }) 
        .done(function(data) { 
        $("#results").text(data); 
        }); 
    } 
    </script> 
    

    此外,你最後一對'回聲'行正在爲我打破腳本。只要把Meta Interval的引號等等......

    相關問題