xue_hua_video_cache 1.2.2
xue_hua_video_cache: ^1.2.2 copied to clipboard
Video caching plugin with XueHUAEVideoCache.initialize entry and a Rust core.
Changelog #
All notable changes to this project are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
1.2.0 - 2026-07-03 #
Added #
ContentLengthProbe— deduplicated origin content-length resolution (cache → single in-flightGETper URI); shared by range playback, precache, andisCached- Dedicated content-length metadata slot —
CacheKey::for_content_lengthstores file size separately so thebytes=0-1probe range stays free for real data; legacy metadata in the old slot is migrated on read hls_key_for_url()— canonical HLS playlist directory key via normalized URL (to_safe_uri→ MD5); ADR-0001 documents invariants for precache, proxy, and removalremoveCacheByUrl(..., headers: ...)— optional request headers (required whencustom_cache_idhost override was used during precache)- Range responder paths — explicit
probe_fast/bounded_range/probe_getdispatch with diagnostic logging; HTTP 502 viawrite_bad_gatewaywhen a probe cannot resolve asset size - Tests —
download_stream_test.dart; Rust coverage for cache-key stability, content-length migration, HLS key normalization, precache orchestrator, and range response helpers
Changed #
- Default segment size — 2 MB → 512 KB for lower first-byte latency (
initialize(segmentSize:)still overrides in MB units) RangeResponderrewrite — removed HEAD-basedhead(); usesContentLengthProbe; emitsContent-Rangeonly on 206; bounded ranges can stream body length without a known file total- HTTPS / TLS — reqwest now trusts bundled Mozilla root certs (
webpki-root-certs) instead ofrustls-platform-verifier, giving uniform TLS behavior across platforms and avoiding AndroidCertPathValidatorrejecting certs without an OCSP responder asRevoked - MP4 cache keys — ranged entry MD5 serializes query parameters in sorted key order so keys are stable across process restarts
- HLS precache /
isCached— playlist keys usehls_key_for_url; queued HLS precache waits via segment-levelhls_segments_cachedinstead of re-probing content length downloadStream— returns the same stream instance across accesses (cached in_DownloadBridge)- Download pool debounce — scheduler round debounce 500 ms → 30 ms
- Precache progress — HLS and MP4 parallel precache emit progress only after a segment is actually cached; a failed download aborts the batch
Fixed #
- Probe-fast playback — when origin content-length probe fails, respond with 502 instead of
bytes 0-1/*, which AVFoundation and similar players reject as malformed removeCacheByUrl(singleFile: true)— purges full-file entry, content-length metadata, all ranged segments, legacybytes=0-1slot, and matching HLS segment entries- HLS precache counting — already-cached segments no longer inflate failure counts or emit spurious progress events
- Android
minSdk— restored to 19 (no longer raised to 22 for the removed platform-verifier AAR)
Removed #
- Android JNI TLS initializer —
XueHuaTls.java,android_tls.rs, and ProGuard consumer rules (superseded by bundled root certs) RangeResponder::head()— superseded byContentLengthProbe
Migration notes #
- Segment size default changed — existing on-disk ranged segments keyed under the old 2 MB boundaries will not match new 512 KB segments; clear cache or bump cache keys if you rely on persisted segments after upgrade
- HLS playlist keys changed — keys now derive from normalized URLs; re-precache HLS content after upgrade if you depend on persisted playlist directories
removeCacheByUrl— pass the same optionalheadersused during precache whencustom_cache_idhost override is enabled
1.1.0 - 2026-06-29 #
Changed #
- Dart layer — merged shallow
DownloadManagerandLruCacheSingletonwrappers intoXueHuaVideoCache;DownloadTaskmoved tolib/src/download_task.dart. Public barrel API unchanged. - Rust runtime seam — introduced
ProxyRuntimebundle (AppContext+DownloadManager+LruCache); parsers receive injected runtime viaUrlParserFactory; FRB api usesrequire_runtime(). Parser layer no longer callsrequire_state()orLruCacheSingleton::instance(). - Range parser modules — split
RangeParserCommonintoSegmentResolver,SegmentFetcher,RangeResponder, andPrecacheOrchestrator; MP4/Default parsers delegate to the four modules. - Precache progress (breaking) —
XueHuaVideoCache.precachewithprogressListen: truenow returnsStream<PrecacheProgressEvent>?instead ofStreamController<Map>?; usePrecacheProgressEventfrom the main barrel. - HLS parser modules — split
UrlParserM3U8intohls_registry,hls_playlist_resolver,hls_concurrent_orchestrator, andhls_playlist_rewriter;UrlParserM3U8is a thin router; HLS cache delegates toSegmentResolver::resolve.
Evaluated / No change #
- Rust api vs domain layer — evaluated merging
rust/src/api/withparser/video_caching.rs; decided to keep both:api/remains the FRB seam (DTO conversion,StreamSinkwiring,require_runtime());parser/video_caching.rsstays as domain dispatch viaUrlParserFactory.
1.0.1 - 2026-06-28 #
Fixed #
- Hot restart — calling
XueHuaVideoCache.initialize()after a Flutter hot restart no longer throwsXueHUAEVideoCache already initialized; native state is reused and the proxy is restarted idempotently RustLib.init()— skip re-initialization when flutter_rust_bridge is already loaded in the same process
Added #
- Regression test
test/hot_restart_init_test.dartand Rust unit testinit_twice_is_idempotent
1.0.0 - 2026-06-28 #
First stable release with a Rust core and unified Dart entry point.
Added #
XueHuaVideoCache— unified static API for proxy init, pre-cache, download control, and cache removalXueHuaVideoCache.initialize()— starts local proxy, LRU cache, and download pool- Rust core — local HTTP proxy, LRU memory/disk cache, streaming Range downloads, MP4/M3U8 parsers
- Pre-cache & cache check —
XueHuaVideoCache.precache/isCached/parseHlsMasterPlaylist - Download helpers —
downloadStream,allDownloadTasks, pause / resume / cancel by id or URL; HLS-awarecancelTaskAboutUrl - URL extensions —
String.toLocalUri()/toLocalUrl()and related helpers ignoreQueryKeys— stable cache keys when query params vary (e.g.token)- Health monitor — 10s proxy health check with full
restart()on failure - Example app — butterfly.mp4 demo with
video_player - Tests — Rust unit tests; opt-in butterfly network E2E;
./scripts/test_butterfly.shsmoke script - Documentation — bilingual README (EN / zh-CN) and this changelog
Platform support #
- Android, iOS, macOS, Linux, Windows (FFI plugin via Cargokit)
Known limitations #
- No custom
UrlMatcher/HttpClientBuilderon the Dart side (useignoreQueryKeysinstead) - Dart LRU introspection API is minimal (
removeCacheByUrlonly) - HLS long-video cancellation and
download_now: falsequeueing should be validated in production workloads - Large segment files are read fully into memory on download completion (memory pressure for very large segments)