2017-11-04 19 views
0

안녕하세요, 다음 스트림으로 간단한 라디오 응용 프로그램을 만들려고합니다 : http://lb.topradio.be/topradio.mp3.ExoMedia/Exoplayer MP3 메타 데이터 추출기

현재 기본 오디오 플레이어로 편의상 ExoMedia를 사용하고 있습니다.
Mp3Extractor 클래스에는 peekId3Data 메서드가이 검사를하기 때문에 결코 호출되지 않는이 setMetadataListener 메서드가 있습니다.

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

그러나 VLC Media Player에서 동일한 스트림을 던질 때 스트림에서 메타 데이터를 성공적으로 가져올 수 있습니다.
어떻게 작동합니까?
Extractor 맞춤 설정으로이를 복제 할 수 있습니까?

감사

답변

0

Exoplayer repository에 열 문제가있다. 기본적으로 메타 데이터는 스트림 자체가 아니라 헤더를 통해 전송됩니다.

audiostream-metadata-retriever으로 성공했지만 실제 노래가 재생되기 전에 스트림 캐싱과 메타 데이터가 도착하기 때문에 일부 동기화 문제가있었습니다.

편집 :

RxJava 구현 :

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"); 
       } 
      }); 
} 

개조 인터페이스 :이 답변, 고란에 대한

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

감사합니다. 문제 추적기에 대한 링크가 깨졌습니다. 그러나 당신은 나를 위해 올바른 길을 걸었습니다. 이 라이브러리를 사용하여 Retrofit 및 Rx를 사용하여 메타 데이터를 가져오고 조금 더 깨끗한 imho를 얻습니다. – tim

+0

맞습니다. 링크를 수정했습니다. 나는 도서관이 약간 과잉이고 간단한 응답을 가져 오는 것으로 충분할 것이라고 동의한다. 시간이있을 때 혼자 힘으로 시도해 봅니다. 대답을 수락하십시오. – GoranNSW