flutter_video_caching is a powerful flutter plugin for caching video. It can be use with video_player package. It supports formats like m3u8 and mp4, play and cache videos simultaneously, precache the video before playing.
Features
Multi-format support
: supports common video formats such as m3u8 (HLS) and MP4Memory and file cache
: implements LRU (least recently used) memory cache strategy, combined with local file cache to reduce network requestsPre-caching mechanism
: supports downloading video clips in advance to improve the continuous playback experienceBackground download
: uses Isolate to achieve multi-task parallel download without blocking UI threadsPriority scheduling
: supports setting priorities for download tasks and optimizes resource allocation
Getting started
dependencies:
flutter_video_caching: 0.3.0
Usage
1. Init video proxy
import 'package:flutter_video_caching/flutter_video_caching.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
VideoProxy.init();
runApp(const HomeApp());
}
API: VideoProxy.init():
/// Initialize the video proxy server.
///
/// [ip] is the IP address of the proxy server.
/// [port] is the port number of the proxy server.
/// [maxMemoryCacheSize] is the maximum size of the memory cache in MB.
/// [maxStorageCacheSize] is the maximum size of the storage cache in MB.
/// [logPrint] is a boolean value to enable or disable logging.
/// [segmentSize] is the size of each segment in MB.
/// [maxConcurrentDownloads] is the maximum number of concurrent downloads.
static Future<void> init({
String? ip,
int? port,
int maxMemoryCacheSize = 100,
int maxStorageCacheSize = 1024,
bool logPrint = false,
int segmentSize = 2,
int maxConcurrentDownloads = 8,
})
2. Use with video_player
playControl = VideoPlayerController.networkUrl(url.toLocalUri());
3. Precache video
VideoCaching.precache(url);
API: VideoCaching.precache:
VideoCaching.precache(String url, {
int cacheSegments = 2,
bool downloadNow = true,
})
4. Use in PageView
PageView.builder(
controller: pageController,
itemCount: urls.length,
itemBuilder: (context, index) {
return VideoPlayerWidget(url: urls[index]);
},
onPageChanged: (index) {
if (index + 1 < urls.length) {
VideoCaching.precache(urls[index + 1], downloadNow: false);
}
},
);
5. Revert video uri proxy when proxy server is broken
Future initPlayControl(Uri uri) async {
playControl = VideoPlayerController.networkUrl(uri.toLocalUri())..setLooping(true);
playControl.addListener(playListener);
}
void playListener() {
if (playControl.value.hasError) {
print("errorDescription: ${playControl.value.errorDescription}");
if (playControl.value.errorDescription!.contains("Source error")) {
initPlayControl(uri);
}
}
}
6. Delete cache
// params: [singleFile]
// true: just delete the cache of the file associated with the link
// false: delete all caches under the directory associated with the link, including the directory
LruCacheSingleton().removeCacheByUrl(String url, {bool singleFile = false});
7. Custom request header
Setup for playing:
_controller = VideoPlayerController.networkUrl(uri,
httpHeaders: {'Token': 'xxxxxxx'});
Setup for precache:
VideoCaching.precache(url, headers: {'Token': 'xxxxxxx'});
Custom cache file name, the default file name generate by full url, if you want to custom the file name, pass CUSTOM-CACHE-ID
to headers.
_controller = VideoPlayerController.networkUrl(uri,
httpHeaders: {'CUSTOM-CACHE-ID': 'xxxxxxx'});
VideoCaching.precache(url, headers: {'CUSTOM-CACHE-ID': 'xxxxxxx'});
8. Custom url match
class UrlMatcherDefault extends UrlMatcher {
@override
bool matchM3u8(Uri uri) {
return uri.path.toLowerCase().endsWith('.m3u8');
}
@override
bool matchM3u8Key(Uri uri) {
return uri.path.toLowerCase().endsWith('.key');
}
@override
bool matchM3u8Segment(Uri uri) {
return uri.path.toLowerCase().endsWith('.ts');
}
@override
bool matchMp4(Uri uri) {
return uri.path.toLowerCase().endsWith('.mp4');
}
@override
Uri matchCacheKey(Uri uri) {
Map<String, String> params = {};
params.addAll(uri.queryParameters);
params.removeWhere((key, _) => key != 'startRange' && key != 'endRange');
uri = uri.replace(queryParameters: params.isEmpty ? null : params);
return uri;
}
}
Use UrlMatcher
to distinguish video types. For example: m3u8 matches URLs ending with .m3u8.
flutter_video_caching file cach logic:
- m3u8: Each segment will be saved into one file.
- mp4 and others: The entire file will be split into multiple files, each with a size of 2Mb.
The cache name of the file is generated by saveFile
/uri
+ ?startRange=xx&endRange=xx
(startRange and endRange are used in mp4).
QA
1. How to set the maximum cache limit?
Answer:
Memory and file cache: implements LRU (least recently used) memory cache strategy, combined with local file cache to reduce network requests.
/// Initialize the video proxy server.
///
/// [ip] is the IP address of the proxy server.
/// [port] is the port number of the proxy server.
/// [maxMemoryCacheSize] is the maximum size of the memory cache in MB.
/// [maxStorageCacheSize] is the maximum size of the storage cache in MB.
/// [logPrint] is a boolean value to enable or disable logging.
/// [segmentSize] is the size of each segment in MB.
/// [maxConcurrentDownloads] is the maximum number of concurrent downloads.
static Future<void> init({
String? ip,
int? port,
int maxMemoryCacheSize = 100,
int maxStorageCacheSize = 1024,
bool logPrint = false,
int segmentSize = 2,
int maxConcurrentDownloads = 8,
})
2. How to track download progress in video?
Answer:
VideoProxy.downloadManager.stream.listen((task) {
print('${task.uri}, ${task.progress}, ${task.downloadedBytes}, ${task.totalBytes}');
});
The code show above, can track download progress for each segments of hls format, but no whole video link.
For m3u8, it track progress on each ts file. For mp4, it track progress on splite segment.
Currently, the function of tracking the download progress of the entire video has not been developed.
3. Does this library handle download resume case?
Answer:
For e.g.: user download https://example.ts file, assume it has more than 50ts file (segment).
Use Case: user download the hls video, out of 50, 10ts file was downloaded, during downloading other ts files, user terminate the app.
When user replay the video, the downloaad task will be continue, and 10ts file will be loaded from file system, then continue to download rest 40ts file.
Libraries
- cache/lru_cache
- cache/lru_cache_impl
- cache/lru_cache_memory
- cache/lru_cache_singleton
- cache/lru_cache_storage
- download/download_isolate_entry
- download/download_isolate_instance
- download/download_isolate_msg
- download/download_isolate_pool
- download/download_manager
- download/download_status
- download/download_task
- ext/file_ext
- ext/gesture_ext
- ext/int_ext
- ext/list_ext
- ext/log_ext
- ext/socket_ext
- ext/string_ext
- ext/uri_ext
- flutter_video_caching
- global/config
- match/url_matcher
- match/url_matcher_default
- parser/url_parser
- parser/url_parser_default
- parser/url_parser_factory
- parser/url_parser_m3u8
- parser/url_parser_mp4
- parser/video_caching
- proxy/local_proxy_server
- proxy/video_proxy