Skip to main content

http_cache_stream 0.3.0 copy "http_cache_stream: ^0.3.0" to clipboard
http_cache_stream: ^0.3.0 copied to clipboard

Simultaneously download, cache, and stream remote content. Perfect for media players and any plugin that streams web content.

A Flutter package that simultaneously downloads, caches, and streams remote content. Perfect for media players and any plugin that streams web content.

Motivation #

The ability to simultaneously download and cache files remains a highly requested feature of video and audio playback plugins. By creating a local HTTP server, HttpCacheStream supports virtually any plugin that streams from web links. Unlike traditional caching solutions, HttpCacheStream works while the file is still downloading - allowing immediate playback of media files.

Features #

  • Simultaneous Download and Streaming - Start playing media instantly while downloading
  • Persistent Caching - Cache files locally for offline playback
  • Range Request Support - Efficient seeking in media players
  • Resumable Downloads - Continue downloads after app restart
  • HTTP Server - Works with any media player supporting HTTP URLs
  • Custom Headers - Configure both request and response headers

Getting Started #

Using http_cache_stream to simultaneously cache and stream a video file:

import 'package:http_cache_stream/http_cache_stream.dart';

// Initialize the cache manager once, at app startup
await HttpCacheManager.init();

// Get a local cache URL for any remote resource
final sourceUrl = Uri.parse('https://example.com/video.mp4');
final cacheUrl = HttpCacheManager.instance.getCacheUrl(sourceUrl);
// Example output: http://127.0.0.1:4612/example.com/video.mp4

// Pass it directly to your media player
final videoPlayerController = VideoPlayerController.networkUrl(cacheUrl);
await videoPlayerController.initialize();
videoPlayerController.play();

The cache stream is created and managed automatically — no lifecycle management required. For direct access to the HttpCacheStream instance (e.g., to monitor download progress or configure per-stream settings), use createStream instead. See HttpCacheStream below.

See the example project to learn how to use http_cache_stream with video_player, audioplayers, and just_audio

Platform configuration #

Since http_cache_stream utilizes a localhost HTTP server, configuration is necessary to allow cleartext (non-HTTPS) connections:

iOS/macOS #

Add the following to your projects Info.plist file:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

iOS can reclaim the local server's socket while the app is suspended in the background. The server recovers automatically, but a player that connects immediately on resume may fail with a connection error (-1004). To handle this, call HttpCacheManager.instance.ensureActive() before retrying the request.

Android: #

Create 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>

Reference the file in android/app/src/main/res/AndroidManifest.xml by adding the following entry under application:

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

See the example project for a full example.

Without the local server #

If your app reads streams directly (through createStream and HttpCacheStream.request) rather than handing a URL to a player, you can skip the local server entirely. No socket is bound, so no cleartext or network-server configuration is needed, and it works in sandboxes that refuse to bind one (e.g. a macOS App Sandbox without the com.apple.security.network.server entitlement):

await HttpCacheManager.init(startServer: false);

final stream = HttpCacheManager.instance.createStream(sourceUrl);
final response = await stream.request(start: 0); // downloads and caches as it streams
await for (final chunk in response.stream) {
  // ...
}

Without a server there is no cache URL: getCacheUrl and HttpCacheStream.cacheUrl throw a CacheServerUnavailableException (check HttpCacheManager.hasServer or HttpCacheStream.hasCacheUrl), and ensureActive() does nothing.

Core Components #

HttpCacheManager #

The central manager for all cache streams:

// Initialize once, at app startup
await HttpCacheManager.init();
final cacheManager = HttpCacheManager.instance;

// Get a cache URL — the recommended way to integrate with media players
final cacheUrl = cacheManager.getCacheUrl(sourceUrl);

// Pre-cache files:
await cacheManager.preCacheUrl(Uri.parse('https://example.com/file.mp3'));

// Configure global settings
cacheManager.config.requestHeaders[HttpHeaders.userAgentHeader] = 'MyApp/1.0';

// Delete inactive cache files
await cacheManager.deleteCache();

HttpCacheStream #

Provides direct access to the download, cache, and streaming state for a specific URL. Use createStream when you need to monitor progress or configure per-stream settings.

final cacheStream = cacheManager.createStream(Uri.parse('https://example.com/file.mp3'));

// Start download explicitly (optional — begins automatically on first request)
cacheStream.download();

// Monitor CacheState for position and source length
cacheStream.cacheStateStream.listen((state) {
  print('${state.position} / ${state.sourceLength} bytes');
});

// Release when done — the stream will be paused and eventually disposed
// automatically according to StreamLifecycleConfig.
// Call dispose() instead to tear down immediately.
cacheStream.release();

CacheMetadata #

Each cached file has associated metadata stored in a companion .metadata file, which contains:

  • Original source URL
  • Response headers from the server
  • Additional cache information
// Get metadata for all cached files
final allMetadata = await cacheManager.cacheMetadataList();
final activeOnly = await cacheManager.cacheMetadataList(active: true);
final inactiveOnly = await cacheManager.cacheMetadataList(active: false);

// Get metadata for a specific URL
final metadata = cacheManager.getCacheMetadata(Uri.parse('https://example.com/video.mp4'));

// Delete cache files
await metadata?.cacheFiles.delete();

Metadata is automatically managed by HttpCacheStream, but you can also work with it directly to inspect or manipulate the cache without creating stream instances.

Advanced Usage #

Cache Configuration #

Configure both global and per-stream settings:

// Global configuration
final globalConfig = HttpCacheManager.instance.config;
globalConfig.requestHeaders[HttpHeaders.userAgentHeader] = 'MyApp/1.0';

// Per-stream configuration
final cacheStream = cacheManager.createStream(Uri.parse('https://example.com/file.mp3'));
cacheStream.config.copyCachedResponseHeaders = true;

Stream Lifecycle #

When createStream is used, call release() instead of dispose() to hand the stream back to the cache manager. The behavior after release is controlled by StreamLifecycleConfig:

// Configure globally (applies to all streams)
HttpCacheManager.instance.config.lifecycleConfig = StreamLifecycleConfig(
  pauseAfter: Duration(seconds: 10),   // Pause the download after 10s of inactivity
  disposeAfter: Duration(minutes: 5),  // Fully dispose the stream after 5 minutes
);

Call dispose() to tear down a stream immediately, bypassing the lifecycle configuration.

Range Request Controls #

When a client requests a byte range that's significantly ahead of what's currently cached, the library can initiate a separate direct connection to the source, rather than waiting for the sequential cache download to reach that position. The rangeRequestSplitThreshold setting controls this behavior by defining how many bytes ahead a request must be to trigger a separate connection.

// Set the threshold for creating a split download (in bytes)
cacheStream.config.rangeRequestSplitThreshold = 5 * 1024 * 1024; // 5MB

// Disable split downloads
cacheStream.config.rangeRequestSplitThreshold = null;

Cache Validation #

// Check if cache is still valid
final isValid = await cacheStream.validateCache();
if (isValid == false) {
  // Cache is invalid, reset it
  await cacheStream.resetCache();
}

// Enable automatic validation of outdated cache
cacheStream.config.validateOutdatedCache = true;

Credits #

http_cache_stream began as a custom implementation of just_audio's LockCachingAudioSource, a feature enabling simultaneous streaming and caching of audio files. Many thanks goes out to the developer and contributors of just_audio.

24
likes
0
points
2.68k
downloads

Publisher

verified publishercoltongrubbs.com

Weekly Downloads

Simultaneously download, cache, and stream remote content. Perfect for media players and any plugin that streams web content.

Repository (GitHub)
View/report issues

Topics

#cache #streaming #video #audio #http

License

unknown (license)

Dependencies

crypto, flutter, http, path, path_provider, rxdart, synchronized

More

Packages that depend on http_cache_stream