如何不调用ExoPlayer.prepare()预加载ProgressiveMediaSource视频
无需ExoPlayer实例实现视频预加载的方案
你遇到的核心问题是ProgressiveMediaSource.prepareSource()本身不会主动触发媒体数据下载——它仅完成MediaSource的初始化工作,必须依赖Player实例驱动数据加载。要绕开Player实现预加载,直接利用ExoPlayer的缓存机制主动拉取数据到缓存即可,具体实现如下:
实现思路
复用你已配置好的CacheDataSource.Factory,直接创建DataSource实例,手动读取媒体流数据。CacheDataSource会自动将读取到的内容写入你设置的SimpleCache中,以此达到预加载的效果。这种方式完全基于缓存组件完成,不需要创建ExoPlayer实例。
代码实现
1. 预加载工具方法(推荐用协程在后台执行)
import android.content.Context import com.google.android.exoplayer2.upstream.CacheDataSource import com.google.android.exoplayer2.upstream.DataSource import com.google.android.exoplayer2.upstream.DefaultHttpDataSource import com.google.android.exoplayer2.upstream.SimpleCache import com.google.android.exoplayer2.util.Util import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.io.IOException import java.io.InputStream import java.net.URI suspend fun preloadVideoToCache( context: Context, cache: SimpleCache, videoUri: String, preloadBytes: Long = 5 * 1024 * 1024 // 预加载前5MB,可按需调整 ) = withContext(Dispatchers.IO) { val dataSourceFactory = CacheDataSource.Factory() .setCache(cache) .setUpstreamDataSourceFactory( DefaultHttpDataSource.Factory() .setUserAgent(Util.getUserAgent(context, "ExoplayerDemo")) ) .setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR) var dataSource: DataSource? = null var inputStream: InputStream? = null try { dataSource = dataSourceFactory.createDataSource() val dataSpec = DataSource.DataSpec(URI.create(videoUri).toUri()) inputStream = dataSource.open(dataSpec) val buffer = ByteArray(8192) var totalRead = 0L var read: Int // 读取指定字节数的内容,直到完成或流结束 while (totalRead < preloadBytes && inputStream.read(buffer).also { read = it } != -1) { totalRead += read // 无需处理读取到的数据,CacheDataSource会自动完成缓存 } } catch (e: IOException) { // 处理加载异常,比如网络错误、资源不存在等 e.printStackTrace() } finally { inputStream?.close() dataSource?.close() } }
2. 调用预加载方法
在合适的时机(比如App启动、进入目标页面时)调用:
// 在Activity或ViewModel的后台逻辑中执行 lifecycleScope.launch { preloadVideoToCache( context = this@YourActivity, cache = SimpleMediaPlayer.simpleCache, videoUri = "https:xxxxxxx/Sending+Data+to+a+New+Activity+with+Intent+Extras.mp4" ) }
关键说明
- 生效原理:CacheDataSource在读取网络数据时,会自动将内容写入你配置的SimpleCache,后续使用ExoPlayer播放该视频时,会优先从缓存读取,实现预加载效果。
- 预加载量控制:通过
preloadBytes参数可指定预加载的字节数,避免一次性加载整个视频占用过多存储和带宽。 - 线程要求:必须在后台线程执行,否则会阻塞主线程导致ANR,示例中用协程
Dispatchers.IO是最便捷的方式。 - 异常处理:记得捕获IO异常,避免因网络错误等情况导致崩溃。
内容的提问来源于stack exchange,提问作者coderror
相关产品推荐
相关产品推荐

