precache method
Pre-caches HLS video segments from the network.
Parses the given HLS playlist URL, selects a specified number of segments to cache, and either immediately downloads them or queues them for later processing.
If progressListen
is true, returns a StreamController that emits progress updates.
Implementation
@override
Future<StreamController<Map>?> precache(
String url,
Map<String, Object>? headers,
int cacheSegments,
bool downloadNow,
bool progressListen,
) async {
StreamController<Map>? _streamController;
if (progressListen) _streamController = StreamController();
List<String> mediaList = await parseSegment(url.toSafeUri(), headers);
int totalSize = mediaList.length;
if (cacheSegments > totalSize) cacheSegments = totalSize;
if (mediaList.isEmpty) return _streamController;
final List<String> segments = mediaList.take(cacheSegments).toList();
final String hlsKey = url.generateMd5;
int downloadedSize = 0;
/// Downloads or loads a segment from cache and emits progress to the stream.
Future<void> processSegment(String segment) async {
final task = DownloadTask(
uri: segment.toSafeUri(),
hlsKey: hlsKey,
headers: headers,
);
Uint8List? data = await cache(task);
if (data == null) {
await download(task);
}
downloadedSize += 1;
if (_streamController?.isClosed ?? false) return;
_streamController?.sink.add({
'progress': downloadedSize / cacheSegments,
'segment_url': segment,
'parent_url': url,
'file_name': task.saveFile,
'hls_key': hlsKey,
'total_segments': segments.length,
'current_segment_index': downloadedSize - 1,
});
}
if (downloadNow) {
for (final segment in segments) {
await processSegment(segment);
}
} else {
for (final segment in segments) {
final task = DownloadTask(
uri: segment.toSafeUri(),
hlsKey: hlsKey,
headers: headers,
);
push(task);
}
}
return _streamController;
}