web-dev-qa-db-ja.com

PHP)を使用してオーディオストリームからトラック情報を取得する

PHPを使用してオーディオストリームからトラック情報を取得することは可能ですか?私はいくつかの掘り下げを行いましたが、見つけることができる最も近い関数はstream_get_transportsですが、私のホストはfsockopen()を介したhttpトランスポートをサポートしていないため、その関数が他に何を返すかを確認するためにさらに調整する必要があります。

現在、AOLストリームからアーティストをプルしてメタデータを追跡しようとしています。

19
Levi Hackwith

これはSHOUTcastストリームであり、可能です。 ID3タグとは全く関係ありません。これを行うために少し前にスクリプトを作成しましたが、もう見つかりません。先週、かなり完全なスクリプトを持っている別の人が同じことをするのを手伝いましたが、それは私のものではないので、ソースを投稿することはできません。ただし、 [email protected] にメールを送っていただければ、彼と連絡を取ります。

とにかく、これがあなた自身でそれをする方法です:

最初に行う必要があるのは、サーバーに直接接続することです。 HTTPを使用しないでください。おそらくcURLを使用することもできますが、その価値よりもはるかに面倒になる可能性があります。 fsockopen()doc )で接続します。必ず正しいポートを使用してください。また、多くのWebホストが多くのポートをブロックすることにも注意してください。ただし、通常はポート80を使用できます。幸い、AOLがホストするSHOUTcastストリームはすべてポート80を使用します。

次に、クライアントと同じようにリクエストを行います。

_GET /whatever HTTP/1.0_

ただし、_<CrLf><CrLf>_を送信する前に、この次のヘッダーを含めてください。

_Icy-MetaData:1_

これは、メタデータが必要であることをサーバーに通知します。次に、_<CrLf>_のペアを送信します。

わかりました。サーバーは一連のヘッダーで応答してから、データの送信を開始します。これらのヘッダーには、_icy-metaint:8192_などが含まれます。その8192はメタ間隔です。これは重要であり、本当に必要な唯一の価値です。通常は8192ですが、常にではないので、実際にこの値を読んでください。

基本的には、8192バイトのMP3データ、次にメタのチャンク、次に8192バイトのMP3データ、続いてメタのチャンクを取得することを意味します。

8192バイトのデータを読み取り(このカウントにヘッダーが含まれていないことを確認してください)、それらを破棄してから、次のバイトを読み取ります。このバイトはメタデータの最初のバイトであり、メタデータの長さを示します。このバイトの値(ord()doc )を含む実際のバイト)を取得し、16を掛けます。結果は、メタデータ用に読み取るバイト数です。それらのバイト数を文字列変数に読み込んで、操作します。

次に、この変数の値をトリミングします。どうして?文字列の最後に_0x0_が埋め込まれているため(16バイトの倍数に均等に収まるようにするため)、trim()doc )がそれを処理しますわたしたちのため。

次のようなものが残ります。

_StreamTitle='Awesome Trance Mix - DI.fm';StreamUrl=''_

これを解析するための選択方法を選択させていただきます。個人的には、おそらく_;_を2に制限して分割しますが、_;_を含むタイトルには注意してください。エスケープ文字の方法がわかりません。少し実験することはあなたを助けるはずです。

使い終わったら、サーバーから切断することを忘れないでください!

そこにはたくさんのSHOUTcastMetaDataリファレンスがあります。これは良いものです: http://www.smackfu.com/stuff/programming/shoutcast.html

50
Brad

これをチェックしてください: https://Gist.github.com/fracasula/578171

これは、ストリーミングURLからMP3メタデータ(StreamTitle)を抽出できるPHP関数を備えたちょっとした要点です。

通常、ストリーミングサーバーは応答にicy-metaintヘッダーを配置します。これは、メタデータがストリームで送信される頻度を示します。この関数は、その応答ヘッダーをチェックし、存在する場合は、intervalパラメーターをそれに置き換えます。

それ以外の場合、関数は間隔を尊重してストリーミングURLを呼び出し、メタデータが存在しない場合は、オフセットパラメーターから開始して再帰を再試行します。

<?php

/**
 * Please be aware. This Gist requires at least PHP 5.4 to run correctly.
 * Otherwise consider downgrading the $opts array code to the classic "array" syntax.
 */
function getMp3StreamTitle($streamingUrl, $interval, $offset = 0, $headers = true)
{
    $needle = 'StreamTitle=';
    $ua = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36';

    $opts = [
            'http' => [
            'method' => 'GET',
            'header' => 'Icy-MetaData: 1',
            'user_agent' => $ua
        ]
    ];

    if (($headers = get_headers($streamingUrl))) {
        foreach ($headers as $h) {
            if (strpos(strtolower($h), 'icy-metaint') !== false && ($interval = explode(':', $h)[1])) {
                break;
            }
        }
    }

    $context = stream_context_create($opts);

    if ($stream = fopen($streamingUrl, 'r', false, $context)) {
        $buffer = stream_get_contents($stream, $interval, $offset);
        fclose($stream);

        if (strpos($buffer, $needle) !== false) {
            $title = explode($needle, $buffer)[1];
            return substr($title, 1, strpos($title, ';') - 2);
        } else {
            return getMp3StreamTitle($streamingUrl, $interval, $offset + $interval, false);
        }
    } else {
        throw new Exception("Unable to open stream [{$streamingUrl}]");
    }
}

var_dump(getMp3StreamTitle('http://str30.creacast.com/r101_thema6', 19200));

これがお役に立てば幸いです。

14

これは、HttpClientを使用してメタデータを取得するためのC#コードです。

public async Task<string> GetMetaDataFromIceCastStream(string url)
    {
        m_httpClient.DefaultRequestHeaders.Add("Icy-MetaData", "1");
        var response = await m_httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
        m_httpClient.DefaultRequestHeaders.Remove("Icy-MetaData");
        if (response.IsSuccessStatusCode)
        {
            IEnumerable<string> headerValues;
            if (response.Headers.TryGetValues("icy-metaint", out headerValues))
            {
                string metaIntString = headerValues.First();
                if (!string.IsNullOrEmpty(metaIntString))
                {
                    int metadataInterval = int.Parse(metaIntString);
                    byte[] buffer = new byte[metadataInterval];
                    using (var stream = await response.Content.ReadAsStreamAsync())
                    {
                        int numBytesRead = 0;
                        int numBytesToRead = metadataInterval;
                        do
                        {
                            int n = stream.Read(buffer, numBytesRead, 10);
                            numBytesRead += n;
                            numBytesToRead -= n;
                        } while (numBytesToRead > 0);

                        int lengthOfMetaData = stream.ReadByte();
                        int metaBytesToRead = lengthOfMetaData * 16;
                        byte[] metadataBytes = new byte[metaBytesToRead];
                        var bytesRead = await stream.ReadAsync(metadataBytes, 0, metaBytesToRead);
                        var metaDataString = System.Text.Encoding.UTF8.GetString(metadataBytes);
                        return metaDataString;
                    }
                }
            }
        }

        return null;
    }
1
Tommy Ovesen

コードfra_casulaをどうもありがとう。これは、PHP <= 5.3(元のバージョンは5.4を対象としています)で実行されているわずかに簡略化されたバージョンです。また、同じ接続リソースを再利用します。

自分のニーズのために例外を削除し、代わりに何も見つからない場合はfalseを返しました。

    private function getMp3StreamTitle($Steam_url)
    {
        $result = false;
        $icy_metaint = -1;
        $needle = 'StreamTitle=';
        $ua = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36';

        $opts = array(
            'http' => array(
                'method' => 'GET',
                'header' => 'Icy-MetaData: 1',
                'user_agent' => $ua
            )
        );

        $default = stream_context_set_default($opts);

        $stream = fopen($Steam_url, 'r');

        if($stream && ($meta_data = stream_get_meta_data($stream)) && isset($meta_data['wrapper_data'])){
            foreach ($meta_data['wrapper_data'] as $header){
                if (strpos(strtolower($header), 'icy-metaint') !== false){
                    $tmp = explode(":", $header);
                    $icy_metaint = trim($tmp[1]);
                    break;
                }
            }
        }

        if($icy_metaint != -1)
        {
            $buffer = stream_get_contents($stream, 300, $icy_metaint);

            if(strpos($buffer, $needle) !== false)
            {
                $title = explode($needle, $buffer);
                $title = trim($title[1]);
                $result = substr($title, 1, strpos($title, ';') - 2);
            }
        }

        if($stream)
            fclose($stream);                

        return $result;
    }
1
Simon