I would like to download a video that is streaming in ExoPlayer.
As an aside and even before using ExoPlayer I downloaded a file from an input stream provided by HttpURLConnection
and played the file from local storage. This is ok, however it does not solve my problem of simultaneous streaming and caching.
ExoPlayer also provides a caching system and these seem to work only for DASH or HLS stream types. I am using none of these and want to cache mp4 with the ExtractorRendererBuilder
. (This topic is covered quite extensively here: https://github.com/google/ExoPlayer/issues/420).
DefaultHttpDataSource
does have an api that exposes HttpURLConnection
but I am not sure I am reusing the stream. Here is the code from the samples provided 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);
}
What I have done now is extend DefaultHttpDataSource
and use HttpURLConnection to get an InputStream, write to a file in getCacheDir()
. Here is the class that extends 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();
}
}
I can now get an InputStream via getURLConnection() to save video into a file but I am not really happy using an InputStream again to cache the video. Is there any other API/ or method that gives access to a byte array that I can write to a file while streaming takes place ?
My other stackoverflow searches have not given a solution yet:
Thanks for your time and patience.
I found a solution with just an issue: seeking backward or forward is not working.
This is the piece of 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() );
}
Source: https://github.com/google/ExoPlayer/issues/420#issuecomment-244652023