2016-06-12 29 views
10

Ich möchte ein Video herunterladen, das im ExoPlayer streamt.Android ExoPlayer - Video herunterladen (nicht DASH/HLS) und gleichzeitig streamen

Als eine Seite und noch vor der Verwendung von ExoPlayer habe ich eine Datei aus einem Eingabestream von HttpURLConnection heruntergeladen und spielte die Datei aus dem lokalen Speicher. Das ist in Ordnung, aber es löst nicht mein Problem des gleichzeitigen Streaming und Caching.

ExoPlayer bietet auch ein Caching-System und diese scheinen nur für DASH- oder HLS-Stream-Typen zu funktionieren. Ich benutze keine von diesen und möchte mp4 mit dem ExtractorRendererBuilder zwischenspeichern. (Dieses Thema wird hier ausführlich behandelt: https://github.com/google/ExoPlayer/issues/420).

DefaultHttpDataSource hat eine API, die HttpURLConnection freilegt, aber ich bin nicht sicher, ob ich den Stream wiederverwende. Hier ist der Code aus den Beispielen im 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); 
    } 

Was habe ich jetzt getan ist DefaultHttpDataSource zu erweitern und verwenden HttpURLConnection einen Inputstream zu bekommen, in eine Datei in getCacheDir() schreiben. Hier ist die Klasse, die DefaultHttpDataSource erweitert:

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

kann ich jetzt einen Inputstream über getURLConnection() erhalten, um Video in eine Datei zu speichern, aber ich bin nicht wirklich glücklich, wieder einen Inputstream mit dem Video cachen. Gibt es eine andere API/Methode, die Zugriff auf ein Byte-Array gibt, das ich in eine Datei schreiben kann, während das Streaming stattfindet?

Meine andere Stackoverflow Suche hat keine Lösung noch gegeben:

Using cache in ExoPlayer

ExoPlayer cache

Vielen Dank für Ihre Zeit und Geduld.

Antwort

2

Ich fand eine Lösung mit nur einem Problem: Suche nach rückwärts oder vorwärts funktioniert nicht.

Dies ist das Stück Code:

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

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