flutter_video_caching 0.3.11 copy "flutter_video_caching: ^0.3.11" to clipboard
flutter_video_caching: ^0.3.11 copied to clipboard

Video caching, can use with video_player package. It supports formats like m3u8 and mp4, play and cache videos simultaneously, precache the video before playing.

flutter_video_caching #

Pub Version Pub Points GitHub

flutter_video_caching is a powerful Flutter plugin for efficient video caching. It supports integration with the video_player package and works with popular formats like m3u8 (HLS) and MP4. The plugin enables simultaneous playback and caching, as well as pre-caching for smoother user experiences.

🎊 Features #

  • Multi-format support: Works with m3u8 (HLS), MP4, and other common video formats.
  • Memory & file cache: LRU-based memory cache combined with local file cache to minimize network requests.
  • Pre-caching: Download video segments in advance to ensure seamless playback.
  • Background downloading: Uses Isolates for multi-task parallel downloads without blocking the UI.
  • Priority scheduling: Supports setting download task priorities for optimized resource allocation.
  • Download resume: Supports automatic resumption of interrupted downloads.
  • Custom headers & cache file names: Allows custom HTTP headers and cache file naming.
  • Custom httpClient: Allows to configure certificate verification, custom headers, or other HTTP behaviors.

💡 Support plugin #

🕹 Installation #

Add the dependency in your pubspec.yaml:

dependencies:
  flutter_video_caching: ^newest_version

Then run:

flutter pub get

🚀 Quick Start #

1. Initialize the video proxy #

import 'package:flutter_video_caching/flutter_video_caching.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  VideoProxy.init(); // add line: init video proxy
  runApp(const HomeApp());
}

2. Use with video_player #

playControl = VideoPlayerController.networkUrl(url.toLocalUri());

3. Pre-cache a video #

VideoCaching.precache(url);

4. Platform configuration #

Since flutter_video_caching create a localhost HTTP server, configuration is necessary to allow http connections:

Android:

Create or Add to android/app/src/main/res/xml/network_security_config.xml:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <domain-config cleartextTrafficPermitted="true">
    <domain includeSubdomains="false">127.0.0.1</domain>
  </domain-config>
</network-security-config>

Config network_security_config in AndroidManifest.xml under application:

<application ... android:networkSecurityConfig="@xml/network_security_config">

iOS

Add the following to your projects Info.plist file:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>127.0.0.1</key>
        <dict>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSIncludesSubdomains</key>
            <false/>
        </dict>
    </dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
</dict>

See the example project for a full example.

⚔️ Advanced Usage #

1. Preload in PageView scenarios #

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);
    }
  },
);

2. Fallback to original URL if proxy fails #

Future initPlayControl(Uri uri) async {
  playControl = VideoPlayerController.networkUrl(uri.toLocalUri())..setLooping(true);
  playControl.addListener(playListener);
}

void playListener() {
  if (playControl.value.hasError) {
    if (playControl.value.errorDescription?.contains("Source error") ?? false) {
      initPlayControl(uri);
    }
  }
}

3. Delete cache #

// Remove cache for a single file or the entire directory
LruCacheSingleton().removeCacheByUrl(String url, {bool singleFile = false});

4. Custom request headers & cache file names #

// Custom header for playback
_controller = VideoPlayerController.networkUrl(uri, httpHeaders: {'Token': 'xxxxxxx'});

// Custom header for pre-caching
VideoCaching.precache(url, headers: {'Token': 'xxxxxxx'});

// Custom cache file name using CUSTOM-CACHE-ID
_controller = VideoPlayerController.networkUrl(uri, httpHeaders: {'CUSTOM-CACHE-ID': 'xxxxxxx'});
VideoCaching.precache(url, headers: {'CUSTOM-CACHE-ID': 'xxxxxxx'});

5. Custom URL matching #

Implement the UrlMatcher abstract class (lib/match/url_matcher.dart) to define custom logic for matching .m3u8, .ts, .mp4, m3u8 encryption keys, and cache keys. The default cache key is the same as the original URL, but with query parameters removed, only startRange and endRange are kept.

class UrlMatcherDefault extends UrlMatcher {
  @override
  bool matchM3u8(Uri uri) => uri.path.toLowerCase().endsWith('.m3u8');

  @override
  bool matchM3u8Key(Uri uri) => uri.path.toLowerCase().endsWith('.key');

  @override
  bool matchM3u8Segment(Uri uri) => uri.path.toLowerCase().endsWith('.ts');

  @override
  bool matchMp4(Uri uri) => uri.path.toLowerCase().endsWith('.mp4');

  @override
  Uri matchCacheKey(Uri uri) {
    final params = Map<String, String>.from(uri.queryParameters)
      ..removeWhere((key, _) => key != 'startRange' && key != 'endRange');
    return uri.replace(queryParameters: params.isEmpty ? null : params);
  }
}
  • Use UrlMatcher to distinguish video types.
  • Caching logic:
    • m3u8: Each segment is cached as a separate file.
    • mp4/others: The file is split into 2MB segments for caching.

To use your custom UrlMatcher, pass it to VideoProxy.init().

6. Custom HttpClient #

You can customize the HTTP client used for video downloading and caching by implementing the HttpClientBuilder interface. This allows you to configure certificate verification, custom headers, or other HTTP behaviors.

Example: Allow Self-Signed Certificates

class HttpClientCustom extends HttpClientBuilder {
  @override
  HttpClient create() {
    return HttpClient()
      ..badCertificateCallback = (X509Certificate cert, String host, int port) {
        // Print certificate info for debugging
        debugPrint('Certificate subject: ${cert.subject}');
        debugPrint('Issuer: ${cert.issuer}');
        debugPrint('Valid until: ${cert.endValidity}');
        debugPrint('SHA-1 fingerprint: ${cert.sha1}');

        // Custom verification logic: here simply allow all certificates, should be stricter in real applications
        // For example, verify if the certificate fingerprint matches the expected value
        return true;
      };
  }
}

To use your custom client, pass it to VideoProxy.init().

Note: Allowing all certificates is insecure and should only be used for testing. In production, implement strict certificate validation.

🪧 Core Api #

1. VideoProxy.init: #

  /// Initializes the video proxy server and related components.
  ///
  /// [ip]: Optional IP address for the proxy server to bind.<br>
  /// [port]: Optional port number for the proxy server to listen on.<br>
  /// [maxMemoryCacheSize]: Maximum memory cache size in MB (default: 100).<br>
  /// [maxStorageCacheSize]: Maximum storage cache size in MB (default: 1024).<br>
  /// [logPrint]: Enables or disables logging output (default: false).<br>
  /// [segmentSize]: Size of each video segment in MB (default: 2).<br>
  /// [maxConcurrentDownloads]: Maximum number of concurrent downloads (default: 8).<br>
  /// [urlMatcher]: Optional custom URL matcher for video URL filtering.<br>
  /// [httpClientBuilder]: Optional custom HTTP client builder for creating HTTP clients.<br>
  static Future<void> init({
    String? ip,
    int? port,
    int maxMemoryCacheSize = 100,
    int maxStorageCacheSize = 1024,
    bool logPrint = false,
    int segmentSize = 2,
    int maxConcurrentDownloads = 8,
    UrlMatcher? urlMatcher,
    HttpClientBuilder? httpClientBuilder,
  })

2. VideoCaching.precache: #

  /// Pre-caches the video at the specified [url].
  ///
  /// [url]: The video URL to be pre-cached.
  /// [headers]: Optional HTTP headers for the request.
  /// [cacheSegments]: Number of segments to cache (default: 2).
  /// [downloadNow]: If true, downloads segments immediately; if false, pushes to the queue (default: true).
  /// [progressListen]: If true, returns a [StreamController] with progress updates (default: false).
  ///
  /// Returns a [StreamController] emitting progress/status updates, or `null` if not listening.
  static Future<StreamController<Map>?> precache(
    String url, {
    Map<String, Object>? headers,
    int cacheSegments = 2,
    bool downloadNow = true,
    bool progressListen = false,
  })

❓ FAQ #

1. How to set the maximum cache limit? #

Set maxMemoryCacheSize and maxStorageCacheSize in VideoProxy.init.

2. How to track download progress? #

VideoProxy.downloadManager.stream.listen((Map map) {
});

For .m3u8:

{
  'progress': 0.0,                // Download progress (0.0 ~ 1.0)
  'segment_url': url,             // Current segment URL being downloaded
  'parent_url': url,              // Main m3u8 playlist URL
  'file_name': '',                // Name of the segment file
  'hls_key': '',                  // The HLS key (generated from the URI) for the download, used to generate the cache directory,
                                  // so that the segments of the same video can be cached in the same directory.
  'total_segments': 0,            // Total number of segments
  'current_segment_index': 0,     // Index of the current segment being downloaded
}

For .mp4:

{
  'progress': 0,                  // Download progress (0 ~ 100)
  'url': url,                     // MP4 file URL
  'startRange': 0,                // Start byte of the current download range
  'endRange': 0,                  // End byte of the current download range
}

3. Does the library support download resume? #

Yes. Downloaded segments are loaded from local cache, and unfinished segments will resume downloading when playback restarts.

🔧 Contributing #

Contributions are welcome! Please submit issues and pull requests.

🛡 License #

This project is licensed under the MIT License.


For more detailed API documentation, please refer to the source code here.

30
likes
160
points
1.09k
downloads

Publisher

unverified uploader

Weekly Downloads

Video caching, can use with video_player package. It supports formats like m3u8 and mp4, play and cache videos simultaneously, precache the video before playing.

Repository (GitHub)

Documentation

API reference

License

MIT (license)

Dependencies

crypto, flutter, flutter_hls_parser, http, logger, path, path_provider, synchronized

More

Packages that depend on flutter_video_caching