패키지, 저장소 및 앱 카테고리 검색

패키지 상세v1.1.6

flutter_video_caching

비디오 캐싱은 video_player 패키지와 함께 사용할 수 있습니다. m3u8 및 mp4와 같은 형식을 지원하며, 비디오를 동시에 재생하고 캐시할 수 있으며, 재생 전에 비디오를 사전 캐시할 수 있습니다.

AndroidiOSmacOSWindowsLinux
30일 다운로드
2.6천
좋아요
61
Pub 점수
160

패키지 설치

flutter pub add flutter_video_caching

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

Flutter_video_caching은 Flutter 애플리케이션에서 효율적인 비디오 캐싱을 가능하게 하는 패키지로, video_player 패키지와 호환됩니다. m3u8 및 mp4와 같은 일반적인 형식을 지원하여 비디오를 동시에 재생하고 캐시할 수 있습니다. 또한 재생 전에 비디오를 사전 캐시할 수 있어 로드 시간을 줄이고 사용자 경험을 향상시킵니다. 오프라인 시청과 부드러운 스트리밍에 적합하며, Android, iOS, macOS, Windows, Linux 플랫폼에서 작동합니다.

사용 사례

  • 오프라인 비디오 재생
  • 저지연 스트리밍
  • 더 빠른 액세스를 위한 비디오 사전 로드
  • 미디어 집약적 앱 성능 최적화
  • HLS (m3u8) 및 MP4 형식 지원

주요 기능

  • 동시 재생 및 캐싱
  • 프리캐시 지원
  • HLS (m3u8) 및 MP4 형식 호환성
  • 크로스 플랫폼 지원
  • video_player와의 원활한 통합

적합한 대상

  • 오프라인 비디오 액세스가 필요한 앱
  • 스트리밍 또는 교육용 앱
  • 고용량의 비디오 콘텐츠를 가진 애플리케이션
  • video_player를 사용하는 개발자
  • 여러 운영 체제를 대상으로 하는 프로젝트

고려 사항

  • 추가 스토리지 관리 필요
  • 캐시 파일로 인해 앱 크기가 증가할 수 있습니다
  • 캐시 정리 전략이 필요합니다
  • video_player 패키지에 종속됨
  • 플랫폼별 캐싱 동작은 다를 수 있습니다

원본 README

연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.

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.

Version 1.x.x released, to migrate from v0.4.x, please refer to MIGRATION.MD.

🎊 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: 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.

5. Cache url with token parameter

If your video URL contains token parameters that change frequently, you can override matchCacheKey in UrlMatcher to define a custom cache key that ignores the token parameters, so that the video can be cached and reused even when the token changes.

class UrlMatcherCustom extends UrlMatcherDefault {
    @override
    Uri matchCacheKey(Uri uri) {
      final params = Map<String, String>.from(uri.queryParameters)
        ..removeWhere((key, _) => key != 'token'); // Remove all parameters except 'token'
      return uri.replace(queryParameters: params.isEmpty ? null : params);
    }
}

Then pass your custom UrlMatcher to VideoProxy.init():

VideoProxy.init(
  urlMatcher: UrlMatcherCustom(),
);

⚔️ 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. Check cache
// Check whether the video was cached
VideoCaching.isCached(url, headers: {'Token': 'xxxxxxx'}, cacheSegments = 2);
6. 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().

7. 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
  Dio create() {
    Dio dio = Dio();
    dio.httpClientAdapter = IOHttpClientAdapter(createHttpClient: () {
      final client =
      HttpClient(context: SecurityContext(withTrustedRoots: false));
      // You can test the intermediate / root cert here. We just ignore it.
      client.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;
      };
      return client;
    });
    return dio;
  }
}

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.

8. Monitor download progress
VideoProxy.downloadManager.stream.listen((task) {
  // Handle download progress updates
  task.progress; // Download progress (0.0 ~ 1.0)
});
9. Cancel tasks associated with a URL

If you want to cancel all download tasks related to a specific URL, you can use the following method. For example, if the user navigates away from a video page and you want to stop downloading the remaining segments. This will cancel all tasks that have the specified URL as their main m3u8 playlist URL or MP4 file URL.

VideoProxy.downloadManager.cancelTaskAboutUrl(url);
10. Foreground recovery

After the app goes to the background, the video proxy server may be killed by the system. You can check if the server is running when the app resumes, and restart it if necessary.

// In app lifecycle listener (e.g., AppLifecycleListener.onResume)
void onResume() async {
  if (!await VideoProxy.isRunning()) {
    await VideoProxy.restart();
  }
  // Then re-open media in your video players
}

🪧 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>
  /// [cacheDir]: Custom cache directory path (default: '').<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,
    String cacheDir = '',
    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,
  })

🎛 Local Video Server

1. To start video server

run main.dart in server directory.

2. Config local domain name
Macos

run scutil --get LocalHostName in terminal to get your computer name. Then you can use http://computer-name.local:8080 to access services.

Windows

Modify the hosts in C:\Windows\System32\drivers\etc\hosts, add 127.0.0.1 computer-name.local to the end of the file. Then you can use http://computer-name.local:8080 to access services.

Linux

Modify the hosts in /etc/hosts, add 127.0.0.1 computer-name.local to the end of the file. Then you can use http://computer-name.local:8080 to access services.

❓ 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.

4. After the cache reaches the maximum value set by the memory cache or storage cache, how does the plugin handle the cache?

LRU (Least Recently Used) cache, which evicts the least recently accessed item when the cache is full, making space for new data, based on the principle that recently used data is more likely to be used again soon.

🔧 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.

카테고리

의존성

의존성 목록 9 개

소스 저장소

이 패키지를 사용하는 프로젝트

아직 데이터가 없습니다.