2016-06-12 31 views
10

Vorrei scaricare un video in streaming in ExoPlayer.Android ExoPlayer - download video (non DASH/HLS) e streaming allo stesso tempo

Come parte e anche prima di usare ExoPlayer ho scaricato un file da un flusso di input fornito da HttpURLConnection e riprodotto il file dalla memoria locale. Questo è ok, tuttavia non risolve il mio problema di streaming e caching simultanei.

ExoPlayer fornisce anche un sistema di memorizzazione nella cache e questi sembrano funzionare solo per i tipi di flusso DASH o HLS. Sto usando nessuno di questi e voglio mettere in cache mp4 con lo ExtractorRendererBuilder. (Questo argomento è ampiamente trattato qui: https://github.com/google/ExoPlayer/issues/420).

DefaultHttpDataSource ha un'API che espone HttpURLConnection ma non sono sicuro che sto riutilizzando il flusso. Ecco il codice degli esempi forniti in ExoPlayer.

@Override 
    public void buildRenderers(DemoPlayer player) { 
     Allocator allocator = new DefaultAllocator(BUFFER_SEGMENT_SIZE); 
     Handler mainHandler = player.getMainHandler(); 

     // Build the video and audio renderers. 
     DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(mainHandler, null); 
     DataSource dataSource = new DefaultUriDataSource(context, bandwidthMeter,userAgent); 
     ExtractorSampleSource sampleSource = new ExtractorSampleSource(uri,dataSource,allocator, 
       BUFFER_SEGMENT_COUNT * BUFFER_SEGMENT_SIZE, mainHandler, player, 0); 
     MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(context, 
       sampleSource, MediaCodecSelector.DEFAULT, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 5000, 
       mainHandler, player, 50); 
     MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource, 
       MediaCodecSelector.DEFAULT, null, true, mainHandler, player, 
       AudioCapabilities.getCapabilities(context), AudioManager.STREAM_MUSIC); 
     TrackRenderer textRenderer = new TextTrackRenderer(sampleSource, player, 
       mainHandler.getLooper()); 

     // Invoke the callback. 
     TrackRenderer[] renderers = new TrackRenderer[DemoPlayer.RENDERER_COUNT]; 
     renderers[DemoPlayer.TYPE_VIDEO] = videoRenderer; 
     renderers[DemoPlayer.TYPE_AUDIO] = audioRenderer; 
     renderers[DemoPlayer.TYPE_TEXT] = textRenderer; 
     player.onRenderers(renderers, bandwidthMeter); 
    } 

Quello che ho fatto oggi è estendere DefaultHttpDataSource e utilizzare HttpURLConnection per ottenere un InputStream, scrivere in un file in getCacheDir(). Ecco la classe che estende DefaultHttpDataSource:

public class CachedHttpDataSource extends DefaultHttpDataSource { 
    public CachedHttpDataSource(String userAgent, Predicate<String> contentTypePredicate) { 
     super(userAgent, contentTypePredicate); 
    } 

    public CachedHttpDataSource(String userAgent, Predicate<String> contentTypePredicate, TransferListener listener) { 
     super(userAgent, contentTypePredicate, listener); 
    } 

    public CachedHttpDataSource(String userAgent, Predicate<String> contentTypePredicate, TransferListener listener, int connectTimeoutMillis, int readTimeoutMillis) { 
     super(userAgent, contentTypePredicate, listener, connectTimeoutMillis, readTimeoutMillis); 
    } 

    public CachedHttpDataSource(String userAgent, Predicate<String> contentTypePredicate, TransferListener listener, int connectTimeoutMillis, int readTimeoutMillis, boolean allowCrossProtocolRedirects) { 
     super(userAgent, contentTypePredicate, listener, connectTimeoutMillis, readTimeoutMillis, allowCrossProtocolRedirects); 
    } 

    public HttpURLConnection getURLConnection(){ 
     HttpURLConnection connection = getConnection(); 

     return getConnection(); 
    } 
} 

posso ora ottenere un InputStream via getURLConnection() per salvare il video in un file, ma io non sono davvero felice di riutilizzare un InputStream per memorizzare nella cache il video. C'è qualche altra API/o metodo che dà accesso a un array di byte che posso scrivere su un file mentre lo streaming ha luogo?

mie altre ricerche StackOverflow non hanno ancora dato una soluzione:

Using cache in ExoPlayer

ExoPlayer cache

Grazie per il vostro tempo e pazienza.

risposta

2

Ho trovato una soluzione con un solo problema: cercare indietro o avanti non funziona.

Questo è il pezzo di codice:

public void preparePlayer(String videoUri) { 
    MediaSource videoSource = 
      new ExtractorMediaSource(Uri.parse(videoUri), dataSourceFactory, extractorsFactory, handler, null); 
    exoPlayer.prepare(videoSource); 
    exoPlayer.setPlayWhenReady(true); 
} 

public DataSource.Factory buildDataSourceFactory() { 
    return new DataSource.Factory() { 
     @Override 
     public DataSource createDataSource() { 
      LeastRecentlyUsedCacheEvictor evictor = new LeastRecentlyUsedCacheEvictor(CACHE_SIZE_BYTES); 
      File cacheDir = //Your cache dir 
      SimpleCache simpleCache = new SimpleCache(cacheDir, evictor); 
      DataSource dataSource = buildMyDataSourceFactory().createDataSource(); 
      int cacheFlags = CacheDataSource.FLAG_BLOCK_ON_CACHE | CacheDataSource.FLAG_CACHE_UNBOUNDED_REQUESTS; 
      return new CacheDataSource(simpleCache, dataSource, cacheFlags, CACHE_SIZE_BYTES); 
     } 
    }; 
} 

private DefaultDataSource.Factory buildMyDataSourceFactory() { 
    return new DefaultDataSourceFactory(context, "jesty-android", new DefaultBandwidthMeter()); 
} 

Fonte: https://github.com/google/ExoPlayer/issues/420#issuecomment-244652023

Problemi correlati