2017-11-04 2 views
0

Hiya Ich versuche, eine einfache Radio-Anwendung mit dem folgenden Stream zu machen: http://lb.topradio.be/topradio.mp3.ExoMedia/Exoplayer MP3-Metadaten-Extraktor

Momentan verwende ich ExoMedia als Standard-Audioplayer.
Es hat diese setMetadataListener Methode, die nie aufgerufen wird, weil in der Mp3Extractor Klasse die peekId3Data Methode diese Überprüfung hat.

if (scratch.readUnsignedInt24() != Id3Decoder.ID3_TAG) { 
    // Not an ID3 tag. 
    break; 
} 

Jedoch, wenn ich den gleichen Strom in VLC Media Player werfen ist es in der Lage, die Metadaten aus dem Stream erfolgreich zu holen.
Wie funktioniert das?
Kann ich dies mit einer benutzerdefinierten Extractor replizieren?

Dank

Antwort

0

Es gibt ein Problem auf dem Exoplayer repository geöffnet. Grundsätzlich werden die Metadaten über Header übertragen, nicht im Stream selbst.

Ich hatte einen Erfolg mit der audiostream-metadata-retriever, obwohl ich einige Track-Synchronisationsprobleme hatte wegen der Stream-Caching und Metadaten ankommen, bevor der eigentliche Song zu spielen beginnt.

Edit:

RxJava Umsetzung:

private long icyMetaInt = 1000; 

public void showStreamData() { 
    Log.d(TAG, "Show stream metadata"); 
    streamService.getStreamData() 
      .subscribeOn(Schedulers.io()) 
      .repeatWhen(delays -> delays.concatMap(metaIntDelay -> { 
       Log.d(TAG, "icyMetaDelay = " + icyMetaInt + "ms "); 
       return Observable.timer(icyMetaInt, TimeUnit.MILLISECONDS); 
      })) 
      .subscribe(new Observer<Response<ResponseBody>>() { 
       @Override 
       public void onSubscribe(Disposable disposable) { 
        Log.d(TAG, "OnSubscribe"); 
       } 

       @Override 
       public void onNext(Response<ResponseBody> response) { 
        Log.d(TAG, "onNext - " + response); 
        if (response.isSuccessful()) { 
         InputStream stream = response.body().byteStream(); 
         if (stream != null) { 
          icyMetaInt = Integer.parseInt(response.headers().get("icy-metaint")); 
          ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
          try { 
           long skipped = stream.skip(icyMetaInt); 
           while (skipped != icyMetaInt) { 
            skipped += stream.skip(icyMetaInt - skipped); 
           } 

           int symbolLength = stream.read(); 
           int metaDataLength = symbolLength * 16; 
           if (metaDataLength > 0) { 
            for (int i = 0; i < metaDataLength; ++i) { 
             int metaDataSymbol = stream.read(); 
             if (metaDataSymbol > 0) { 
              baos.write(metaDataSymbol); 
             } 
            } 

            String result = baos.toString() 
              .replace("StreamTitle=", "") 
              .replaceAll("'", "") 
              .replaceAll(";", ""); 
            baos.reset(); 

            Log.d(TAG, result); 
            runOnUiThread(() -> textView.setText(result)); 

            Log.d(TAG, response.headers().get("ice-audio-info")); 
            Log.d(TAG, response.headers().get("icy-description")); 
            Log.d(TAG, response.headers().get("icy-genre")); 
            Log.d(TAG, response.headers().get("icy-name")); 
            Log.d(TAG, response.headers().get("icy-url")); 
           } 

          } catch (IOException e) { 
           onError(e); 
           Log.e(TAG, "Failed to obtain metadata"); 
          } finally { 
           try { 
            baos.close(); 
            stream.close(); 
           } catch (IOException e) { 
            onError(e); 
           } 
          } 
         } 
        } 
       } 

       @Override 
       public void onError(Throwable throwable) { 
        Log.d(TAG, "onError"); 
        throwable.printStackTrace(); 
       } 

       @Override 
       public void onComplete() { 
        Log.d(TAG, "onComplete"); 
       } 
      }); 
} 

Retrofit-Schnittstelle:

import io.reactivex.Observable; 
import okhttp3.ResponseBody; 
import retrofit2.Response; 
import retrofit2.http.GET; 
import retrofit2.http.Headers; 
import retrofit2.http.Streaming; 

public interface StreamService { 

    @GET("stream") 
    @Headers("Icy-MetaData:1") 
    @Streaming 
    Observable<Response<ResponseBody>> getStreamData(); 
} 
+0

Dank für diese Antwort, Goran. Ihr Link für den Issue Tracker ist gebrochen, denke ich. Aber Sie haben mich auf den richtigen Weg gebracht. Ich habe diese Bibliothek als eine Inspiration verwendet, um die Metadaten mit Retrofit und Rx etwas sauberer imho holen. – tim

+0

Sie haben Recht, ich habe den Link korrigiert. Ich stimme zu, dass die Bibliothek ein bisschen übertrieben ist und das einfache Antworten reichen würde. Werde es selbst ausprobieren wenn ich Zeit habe. Bitte akzeptiere die Antwort. – GoranNSW