2016-05-31 2 views
8

私は完璧に機能するラジオアプリを作っています。ラジオストリームを再生してメタデータを取得することもできます。ストリーミングサービスはshoutcastからのものです。メタデータとトラックを別々にリクエストしなくても、shoutcastストリームから分離するには

唯一の問題は、メディアプレーヤーとしてURLを追加してから、5秒ごとにタイトルとアーティストを取得することです。

私はちょうど1つのHTTPリクエストを作成してから、オーディオとメタデータを分割してメディアプレーヤーに送信できますか?

メタデータを取得するためのコード。

private void retreiveMetadata() throws IOException { 

    int metaDataOffset = 0; 

    OkHttpClient client = new OkHttpClient(); 
    Request request = new Request.Builder() 
     .addHeader("Icy-MetaData", "1") 
     .addHeader("Connection", "close") 
     .addHeader("Accept", "") 
     .url(streamUrl) 
     .build(); 

    request.headers(""); 


    Response response = client.newCall(request).execute(); 
    InputStream stream = response.body().byteStream(); 

    //Map<String, List<String>> headers = response..getHeaderFields(); 

    if (!response.headers("icy-metaint").equals("")) { 
     // Headers are sent via HTTP 

     String icyMetaInt = response.headers("icy-metaint").toString(); 
     icyMetaInt = icyMetaInt.replace("[", ""); 
     icyMetaInt = icyMetaInt.replace("]", ""); 

     metaDataOffset = Integer.parseInt(icyMetaInt); 
    } else { 

     // Headers are sent within a stream 
     StringBuilder strHeaders = new StringBuilder(); 
     char c; 
     while ((c = (char)stream.read()) != -1) { 
      strHeaders.append(c); 
      if (strHeaders.length() > 5 && (strHeaders.substring((strHeaders.length() - 4), strHeaders.length()).equals("\r\n\r\n"))) { 
       // end of headers 
       break; 
      } 
     } 

     // Match headers to get metadata offset within a stream 
     Pattern p = Pattern.compile("\\r\\n(icy-metaint):\\s*(.*)\\r\\n"); 
     Matcher m = p.matcher(strHeaders.toString()); 

     if (m.find()) { 
      metaDataOffset = Integer.parseInt(m.group(2)); 
     } 
    } 

    // In case no data was sent 
    if (metaDataOffset == 0) { 
     isError = true; 
     return; 
    } 

    // Read metadata 
    int b; 
    int count = 0; 
    int metaDataLength = 4080; // 4080 is the max length 
    boolean inData = false; 
    StringBuilder metaData = new StringBuilder(); 
    // Stream position should be either at the beginning or right after headers 
    while ((b = stream.read()) != -1) { 
     count++; 

     // Length of the metadata 
     if (count == metaDataOffset + 1) { 
      metaDataLength = b * 16; 
     } 

     if (count > metaDataOffset + 1 && count < (metaDataOffset + metaDataLength)) { 
      inData = true; 
     } else { 
      inData = false; 
     } 

     if (inData) { 
      if (b != 0) { 
       metaData.append((char)b); 
      } 
     } 

     if (count > (metaDataOffset + metaDataLength)) { 
      break; 
     } 

    } 

    // Set the data 
    metadata = IcyStreamMeta.parseMetadata(metaData.toString()); 

    // Close 
    stream.close(); 
} 

public static Map<String, String> parseMetadata(String metaString) { 
    Map<String, String> metadata = new HashMap(); 
    String[] metaParts = metaString.split(";"); 
    Pattern p = Pattern.compile("^([a-zA-Z]+)=\\'([^\\']*)\\'$"); 
    Matcher m; 
    for (int i = 0; i < metaParts.length; i++) { 
     m = p.matcher(metaParts[i]); 
     if (m.find()) { 
      metadata.put((String)m.group(1), (String)m.group(2)); 
     } 
    } 

    return metadata; 
} 

とメディアプレーヤー

String url = "http://68.68.109.106:8356/"; 
mp = new MediaPlayer(); 
mp.setAudioStreamType(AudioManager.STREAM_MUSIC); 
try { 

    mp.setDataSource(url); 
    mp.prepare(); 

} catch (IllegalArgumentException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
    Toast.makeText(context, e.toString(), Toast.LENGTH_SHORT).show(); 
} catch (SecurityException e) { 
    // TODO Auto-generated catch block 
    Log.e(TAG, "SecurityException"); 
    Toast.makeText(context, e.toString(), Toast.LENGTH_SHORT).show(); 
} catch (IllegalStateException e) { 
    // TODO Auto-generated catch block 
    Log.e(TAG, "IllegalStateException"); 
    Toast.makeText(context, e.toString(), Toast.LENGTH_SHORT).show(); 
} catch (IOException e) { 
    // TODO Auto-generated catch block 
    Log.e(TAG, "IOException"); 
    Toast.makeText(context, e.toString(), Toast.LENGTH_SHORT).show(); 
} 
+0

はい、ストリームからメタデータをdemuxするだけで済みます。詳細については、この回答を参照してください:http://stackoverflow.com/questions/4911062/pulling-track-info-from-an-audio-stream-using-php/4914538#4914538 AndroidでJava用の特定の回答が必要な場合現在ストリームデータをどのように取得しているかをコードに示す必要があります。 – Brad

+0

@Brad私の更新された回答を参照してください。ありがとう。 – Searock

答えて

1

のデータソースへのURLを渡すあなたが達成しようとするタスクを行うのは簡単ですものではありません。ストリームのメタデータはストリームの先頭でのみダウンロードされるため、後で変更すると、ストリームから「キャッシュされた」メタ情報を読み取ることができなくなります。新しいプロパティを読み込むには、ストリームを再起動する必要があります。新しいヘッダなどを取得します(ただし、ストリームが途切れてしまうため、実際には推奨されません)。

健全な技術では、 watermarking。これは、あなたが音質を破壊することなく、音質を豊かにするプロセスです。 (Usage on youtube.)これは難しいですが、ストリーム内の情報を隠す方法がいくつかあります。私はあなたが到達したい目標を達成するためにthisを読むことをお勧めします。

あなたのハードウェアは携帯電話であり、すべてのAndroidデバイスが十分なものではないため、新しいhttpリクエストを考慮する必要があります。オーディオ処理は、CPU、メモリなどの観点から考えると安価なものではありません。 5秒間のポーリングは、情報を取得する最善の方法ではありません。なぜなら、ユーザーに誤った情報を表示し、虚偽の情報が何も表示されないためです。私はmqttに基づいてサーバー側のプッシュをお勧めします。 Hereはかなり使いやすい例です。ポーリングのこの方法に基づく解決策は、より少ないトラフィックを使用し、より正確です。

関連する問題