Использование кеша в ExoPlayer
Я ищу любой пример реализации кеша в ExoPlayer.
ExoPlayer имеет в своей библиотеке различные классы, относящиеся к кешу, и Google объясняет в этом видео, что мы можем реализовать его с классом CacheDataSource, но Google не предоставляет никакой демонстрации в теме. К сожалению, это довольно сложно использовать, поэтому в настоящее время я ищу примеры (без успеха в Google).
Кто-нибудь преуспеет или имеет какую-либо информацию, которая поможет? Спасибо.
Ответы
Ответ 1
Вот решение для ExoPlayer 2. +
Создайте собственный источник данных кеша factory
class CacheDataSourceFactory implements DataSource.Factory {
private final Context context;
private final DefaultDataSourceFactory defaultDatasourceFactory;
private final long maxFileSize, maxCacheSize;
CacheDataSourceFactory(Context context, long maxCacheSize, long maxFileSize) {
super();
this.context = context;
this.maxCacheSize = maxCacheSize;
this.maxFileSize = maxFileSize;
String userAgent = Util.getUserAgent(context, context.getString(R.string.app_name));
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
defaultDatasourceFactory = new DefaultDataSourceFactory(this.context,
bandwidthMeter,
new DefaultHttpDataSourceFactory(userAgent, bandwidthMeter));
}
@Override
public DataSource createDataSource() {
LeastRecentlyUsedCacheEvictor evictor = new LeastRecentlyUsedCacheEvictor(maxCacheSize);
SimpleCache simpleCache = new SimpleCache(new File(context.getCacheDir(), "media"), evictor);
return new CacheDataSource(simpleCache, defaultDatasourceFactory.createDataSource(),
new FileDataSource(), new CacheDataSink(simpleCache, maxFileSize),
CacheDataSource.FLAG_BLOCK_ON_CACHE | CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR, null);
}
}
И игрок
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory =
new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
SimpleExoPlayer exoPlayer = ExoPlayerFactory.newSimpleInstance(this, trackSelector);
MediaSource audioSource = new ExtractorMediaSource(Uri.parse(url),
new CacheDataSourceFactory(context, 100 * 1024 * 1024, 5 * 1024 * 1024), new DefaultExtractorsFactory(), null, null);
exoPlayer.setPlayWhenReady(true);
exoPlayer.prepare(audioSource);
Это работает очень хорошо.
Ответ 2
Вот пример, который заменяет источник демо-данных на OkHttp, по умолчанию нет кеша
https://github.com/b95505017/ExoPlayer/commit/ebfdda8e7848a2e2e275f5c0525f614b56ef43a6
https://github.com/b95505017/ExoPlayer/tree/okhttp_http_data_source
Таким образом, вам просто нужно правильно настроить OkHttp-кеш, и запросы должны быть кэшированы.
Ответ 3
Я реализовал его так, как в построителе рендеринга
private static final int BUFFER_SEGMENT_SIZE = 64 * 1024;
private static final int BUFFER_SEGMENT_COUNT = 160;
final String userAgent = Util.getUserAgent(mContext, appName);
final DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
final Allocator allocator = new DefaultAllocator(BUFFER_SEGMENT_SIZE);*
Cache cache = new SimpleCache(context.getCacheDir(), new LeastRecentlyUsedCacheEvictor(1024 * 1024 * 10));
DataSource dataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
CacheDataSource cacheDataSource = new CacheDataSource(cache, dataSource, false, false);
ExtractorSampleSource sampleSource = new ExtractorSampleSource(uri
, cacheDataSource
, allocator
, BUFFER_SEGMENT_COUNT * BUFFER_SEGMENT_SIZE
, new Mp4Extractor());
Ответ 4
В документации Exoplayer указан класс DashDownloader и приведен пример кода для этого типа источника. (Нажмите [Рамки], чтобы вернуться к навигации по документации. Мне пришлось удалить ее, чтобы получить глубокую ссылку.)
Ответ 5
По умолчанию ExoPlayer не кэширует медиа (видео, аудио и т.д.). Например, если вы хотите воспроизвести видеофайл онлайн, каждый раз, когда ExoPlayer будет открывать соединение, читайте данные, а затем воспроизводите их.
К счастью, он предоставляет нам некоторые интерфейсы и классы реализации для поддержки кэширования мультимедиа в нашем приложении.
Вы можете написать свой собственный кеш, который реализует данные интерфейсы из ExoPlayer. Для простоты я покажу вам, как включить кэш с помощью классов реализации.
Шаг 1: Укажите папку, содержащую ваши медиа файлы. В Android для более мелкой папки кэша (менее 1 МБ) вы должны использовать getCacheDir, в противном случае вы можете указать предпочитаемую папку кэша, например, getFileDir.
Шаг 2: Укажите размер папки кеша и политики, когда размер будет достигнут. Есть 2 API
- NoOpCacheEvictor, который никогда не удаляет/удаляет файлы кэша. В зависимости от расположения вашей папки кэша, если она находится во внутренней памяти, папка будет удалена, когда пользователи очистят данные приложения или удалят приложение.
- LeastRecentlyUsedCacheEvictor, который сначала будет удалять/удалять наименее недавно использованные файлы кэша. Например, если размер вашего кэша составляет 10 МБ, то при достижении этого размера он автоматически найдет и удалит файлы, которые использовались не так давно.
Положите это вместе
val renderersFactory = DefaultRenderersFactory(context.applicationContext)
val trackSelector = DefaultTrackSelector()
val loadControl = DefaultLoadControl()
val player = ExoPlayerFactory.newSimpleInstance(context, renderersFactory, trackSelector, loadControl)
player.addListener(this)
// Specify cache folder, my cache folder named media which is inside getCacheDir.
val cacheFolder = File(context.cacheDir, "media")
// Specify cache size and removing policies
val cacheEvictor = LeastRecentlyUsedCacheEvictor(1 * 1024 * 1024) // My cache size will be 1MB and it will automatically remove least recently used files if the size is reached out.
// Build cache
val cache = SimpleCache(cacheFolder, cacheEvictor)
// Build data source factory with cache enabled, if data is available in cache it will return immediately, otherwise it will open a new connection to get the data.
val cacheDataSourceFactory = CacheDataSourceFactory(cache, DefaultHttpDataSourceFactory("ExoplayerDemo"))
val uri = Uri.parse("Put your media url here")
val mediaSource = ExtractorMediaSource.Factory(cacheDataSourceFactory).createMediaSource(uri)
player.prepare(mediaSource)
Ответ 6
В дополнение к ответу Бао Ле, здесь можно использовать версию CacheDataSourceFactory
Kotlin, в которой хранится один экземпляр SimpleCache
для решения проблемы записи нескольких объектов Cache в один и тот же каталог.
class CacheDataSourceFactory(private val context: Context,
private val maxCacheSize: Long,
private val maxFileSize: Long) : DataSource.Factory {
private val defaultDatasourceFactory: DefaultDataSourceFactory
private val simpleCache: SimpleCache by lazy {
val evictor = LeastRecentlyUsedCacheEvictor(maxCacheSize)
SimpleCache(File(context.cacheDir, "media"), evictor)
}
init {
val userAgent = Util.getUserAgent(context, context.packageName)
val bandwidthMeter = DefaultBandwidthMeter()
defaultDatasourceFactory = DefaultDataSourceFactory(context,
bandwidthMeter,
DefaultHttpDataSourceFactory(userAgent, bandwidthMeter))
}
override fun createDataSource(): DataSource {
return CacheDataSource(simpleCache,
defaultDatasourceFactory.createDataSource(),
FileDataSource(),
CacheDataSink(simpleCache, maxFileSize),
CacheDataSource.FLAG_BLOCK_ON_CACHE or CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR,
null)
}
}