关于离线缓存:Android ExoPlayer-同时下载视频(非DASH / HLS)并流式传输

Android ExoPlayer - downloading video (non DASH / HLS) and streaming at the same time

我想下载在ExoPlayer中流式传输的视频。

顺便说一句,甚至在使用ExoPlayer之前,我还是从HttpURLConnection提供的输入流中下载了文件并从本地存储播放了该文件。 。可以,但是并不能解决我同时进行流式传输和缓存的问题。

ExoPlayer还提供了一个缓存系统,这些似乎仅适用于DASH或HLS流类型。我没有使用这些,并且想用ExtractorRendererBuilder缓存mp4。 (此主题在此处进行了广泛介绍:https://github.com/google/ExoPlayer/issues/420)。

DefaultHttpDataSource确实具有公开HttpURLConnection的api,但是我不确定正在重用流。这是ExoPlayer中提供的示例代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    @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);
    }

我现在要做的是扩展DefaultHttpDataSource并使用HttpURLConnection获取InputStream,写入getCacheDir()中的文件。这是扩展DefaultHttpDataSource的类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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();
    }
}

我现在可以通过getURLConnection()获得InputStream来将视频保存到文件中,但是我真的不高兴再次使用InputStream来缓存视频。是否有其他API /或方法可以访问流传输发生时可以写入文件的字节数组?

我的其他堆栈溢出搜索尚未提供解决方案:

在ExoPlayer中使用缓存

ExoPlayer缓存

感谢您的时间和耐心。 >


我找到了一个仅有问题的解决方案:向后或向前搜索不起作用。

这是一段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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() );
}

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