libtorrent_flutter 1.7.8
libtorrent_flutter: ^1.7.8 copied to clipboard
Native libtorrent 2.0 bindings for Flutter with a built-in HTTP streaming server for instant torrent video playback. Supports Windows, Linux, macOS, iOS, and Android.
Changelog #
1.7.8 #
- Revert: Rolled back streaming engine changes from 1.7.6–1.7.7 (wider priority window, prefetch changes, notifySeek API, FIN detection) — reverted to the stable 1.7.4 streaming logic with the 1.7.5
is_ephemeralbug fix - Kept: Android encryption build (OpenSSL 3.2.1,
-Dencryption=ON,-O3 -flto) from 1.7.6
1.7.7 #
- Seeking: Added
notifySeek()API — Dart can now notify the native engine of a seek directly, bypassing HTTP detection entirely. When using players like mpv that buffer heavily (~150 MB demuxer cache), seeks within the cached region never triggered a new HTTP range request, causing 25+ second delays. The engine now responds to seeks within milliseconds regardless of player cache state - Seeking: Non-blocking FIN/RST detection in the HTTP send loop — uses
WSAPoll/poll+MSG_PEEK recvbetween send iterations to detect when the player closes the connection, enabling faster seek recovery for out-of-cache seeks - Seeking: On seek, all non-tail piece priorities are reset to
dont_download— prevents old-position pieces from competing for bandwidth with the new seek target - Streaming: Widened priority lookahead from current+2 to current+8 pieces with staggered priorities (first 3 at priority 6, rest at priority 4) and wider deadline spacing — keeps the download pipeline full while concentrating bandwidth on the immediate piece
- Streaming: Expanded disk prefetch from 3 to 5 pieces — more pieces are pre-read from storage while the current piece is being sent, reducing I/O stalls between pieces
1.7.6 #
- Build (Android): Enabled encryption — libtorrent is now compiled with
-Dencryption=ONand statically linked against OpenSSL 3.2.1 cross-compiled for each ABI. Peers can now negotiate encrypted connections (pe_enabled/pe_forced), dramatically improving peer availability and download speeds in swarms that prefer or require encryption - Build (Android): Cross-compiles OpenSSL 3.2.1 as static libraries (
libssl.a,libcrypto.a) forarm64-v8a,armeabi-v7a, andx86_64— no runtime OpenSSL dependency on the device - Build (Android): Upgraded compiler optimization from
-O2to-O3with link-time optimization (-flto) for faster piece hashing, alert processing, and streaming throughput - Build (Android): Removed
-DTORRENT_USE_SSL=0from the bridge build — encryption settings in C++ (pe_enabled/pe_forced) are no longer silently ignored - Build (Android): Added
-fPICto OpenSSL cross-compilation for armeabi-v7a — fixes linker error with 32-bit ARM assembly relocations - Streaming: Reduced memory copies per piece from 3 to 1 —
ReadResultnow usesshared_ptr<vector<char>>so piece data flows from alert to cache to socket without redundant copies - Streaming: Widened priority lookahead from current+2 to current+5 pieces — more peers download ahead of playback, reducing stalls on unstable connections
- Streaming: Expanded disk prefetch from 1 to 3 pieces — next 3 downloaded pieces are pre-read from libtorrent storage while the current piece is being sent to the player
- Streaming: Increased socket send buffer from 2 MB to 8 MB — prevents kernel buffer stalls on fast networks
1.7.5 #
- FIX: Added
is_ephemeralcheck around themetadata_received_alerthandler so that only streaming torrents get paused/zeroed after metadata, not regular downloads
1.7.4 #
- Streaming: Removed
sequential_downloadmode — piece order is now driven entirely byset_piece_deadline, libtorrent's purpose-built time-critical mechanism. Improves seek recovery and swarm efficiency - Streaming: Added hot piece cache —
on_piece_readpopulatesCachePiecebuffers in memory,read_piece_datachecks cache first. Instant re-reads for player probes, overlapping range requests, and small backward seeks - Streaming: Trailing retention window — last 3 played pieces are kept alive instead of being immediately set to
dont_download. Handles player re-reads and small rewinds without re-downloading - Streaming: Adaptive bitrate estimation — startup piece count and buffer reporting now scale with file size. A 1.2 GB file gets ~2 critical startup pieces; a 4 GB file gets 1–2 instead of the old fixed 5, dramatically reducing time-to-first-frame for large files
- Streaming: Tail (moov atom) priority lowered from
top_priorityto priority 5 with 1000 ms deadlines — head startup pieces (priority 7, deadline 0–100 ms) always win the time-critical picker, preventing tail downloads from stealing bandwidth at startup - Seeking: Trailing retention window is flushed on seek — old played pieces are dropped to
dont_downloadimmediately, freeing all bandwidth for the new seek position
1.7.3 #
- FIX (CRASH): Fixed
SIGABRTcrash on stream shutdown —cache->close()destroyedTorrReaderobjects and their mutexes while HTTP client threads were still using them. Reordered shutdown to join all threads before closing the cache - FIX: Added guard in
close_reader()to skip cleanup if the cache is already closed, preventing double-free of reader mutexes - FIX:
read_piece_data()now checksactiveflag in its wait predicate — threads wake immediately on shutdown instead of blocking for up to 10 seconds - FIX:
lt_destroy_sessionno longer holdsstreams_muwhile joining threads, preventing deadlock with the alert thread - HARDENING: All thread entry points (
handle_connection, client thread lambda), shutdown paths (lt_stop_stream,lt_destroy_session), and cache cleanup (close_reader,TorrCache::close) wrapped in try-catch — the native library will never crash the app, even on unexpected shutdown races
1.7.2 #
- FIX (CRASH): Fixed
SIGABRTcrash (pthread_mutex_destroy called on a destroyed mutex) when stopping a stream — HTTP client handler threads were detached and continued accessingStreamEnginemutexes after the engine was destroyed. Client threads are now tracked, joined, and their sockets force-closed during shutdown - FIX: Fixed potential double-close of the HTTP listen socket during stream shutdown
- FIX:
lt_destroy_sessionnow properly closes listen sockets and joins client threads before destroying stream engines
1.7.1 #
- Streaming: Replaced TorrServer-style async cache pipeline with lt2http-style direct storage reads — pieces are read straight from libtorrent disk storage instead of going through an intermediate RAM cache, eliminating seek delays
- Streaming: Narrowed priority window from 25-piece gradient (Now/Next/Readahead/High/Normal) to just current piece + 2 ahead — focuses 100% of bandwidth on what the player actually needs
- Streaming: 100% forward cache — everything ahead of playback, nothing behind. A 64 MB cache can now stream a 60 GB file by aggressively evicting played pieces
- FIX: Fixed downloads being killed during gaps between player HTTP requests —
clear_priority_impl()was setting ALL pieces todont_downloadwhen no readers existed - FIX: Protected current reader piece and next piece from cache eviction, preventing evict-download-evict loops at piece boundaries
- FIX: Removed detached threads that spawned
clean_pieces()andget_removable_pieces()on every piece write/read — these overrodeserve_rangepriorities and stopped downloads - Build (Windows): Reduced DLL size from 9.4 MB to 146 KB
1.7.0 #
- FIX (macOS): Fixed crash on launch —
libssl.3.dylib/libcrypto.3.dylibwere referenced via hardcoded Homebrew paths (/opt/homebrew/opt/openssl@3/lib/...), which don't exist on end-user machines. The dylib now uses@loader_path/references and bundles OpenSSL alongside the plugin - Build (macOS): Added
install_name_toolPOST_BUILD step in CMakeLists.txt to automatically rewrite OpenSSL load paths during compilation - Build (macOS): Added
build_macos.sh— one-command script that builds the dylib, copies OpenSSL from Homebrew, fixes all dylib cross-references, and places files inmacos/andprebuilt/macos/universal/ - Packaging (macOS): Updated podspec to vendor
libssl.3.dylibandlibcrypto.3.dylibalongside the main plugin dylib - Streaming: Improved seek performance — 5 deadline pieces at deadline=0, unlimited unchoke slots, optimized
cancel_non_critical()timing - Engine:
unchoke_slots_limitchanged from 4 to unlimited (-1) — fixes issue where only 4 peers would upload despite hundreds connected
1.6.9 #
- Engine: Complete rewrite of the C++ streaming engine — new priority system, HTTP server, and piece management
- Streaming: 5-level priority gradient (NOW=7, NEXT=6, READAHEAD=5, BACK=1, SKIP=0) — only downloads the playback window and head/tail metadata, not the entire file
- Streaming:
set_piece_deadline()for time-critical downloads — pieces requested from multiple peers simultaneously, slow requests auto-cancelled - Streaming: Adaptive readahead window (3–50 pieces) grows with smooth playback, resets on seek
- Streaming: 8-piece backward buffer keeps recently-played pieces available for quick rewinds
- Streaming: Configurable RAM piece cache via
maxCacheBytes— from 128MB for smart TVs to 2GB for desktops. Sliding window eviction with safe-zone protection around the playhead - Seeking: Threaded HTTP connection handler — new connections preempt old ones instantly via socket close, no more blocking the accept loop
- Seeking:
clear_piece_deadlines()on seek — immediately stops downloading for old position and redirects bandwidth to new target - Seeking: Aggressive seek deadlines (6 pieces at 200ms spacing) at the new position
- Seeking:
seek_generationcounter aborts blocked piece waits within milliseconds - Performance: Condition-variable-based piece waiting — zero CPU polling
- Performance: Alert-driven piece tracking via
piece_finished_alert— no status polling for piece availability - Performance: Piece data cache with safe-zone (5 pieces around playhead never evicted), smart trim on seek preserves nearby cached data
- Tuning:
max_failcount=3— peers survive seek transitions instead of being dropped - Tuning:
peer_turnover5% every 30s — faster replacement of slow peers - Tuning: Connection flood on startup (
connection_speed=200,torrent_connect_boost=200) for fast peer acquisition - API:
startStream()now acceptsmaxCacheBytesto control RAM usage (0 = default ~128MB) - API: Backward-compatible
bufferPctgetter onStreamInfo - API: New
StreamStateenum (idle, buffering, ready, seeking, error) andstreamStatefield onStreamInfo - API: New fields on
StreamInfo:bufferSeconds,bufferPieces,readaheadWindow,activePeers,downloadRate - Compat: All existing API methods preserved —
addMagnet(),startStream(),stopStream(),disposeTorrent(), etc. work unchanged
1.6.8 #
- iOS: Built XCFramework with both device (arm64-iphoneos) and simulator (arm64+x86_64-iphonesimulator) slices — iOS Simulator now works on Apple Silicon and Intel Macs
- iOS: Replaced fat
.abinary with.xcframework— Apple's recommended approach for multi-platform static libraries - iOS: Updated podspec to use
vendored_frameworkswith SDK-conditional-force_loadlinker flags - CI: Build workflow now compiles libtorrent + torrent_bridge for three iOS targets (arm64 device, arm64 simulator, x86_64 simulator) and packages them via
xcodebuild -create-xcframework - Publish: Dropped Android x86_64 prebuilt from pub package to stay under 100 MB limit
1.6.6 #
IOS fixes
1.6.6 #
- FIX (iOS): Added
SystemConfigurationframework dependency to podspec — resolvesUndefined symbol: _SCNetworkReachabilityCreateWithAddresslinker errors when building for iOS release
1.6.5 #
- CRITICAL FIX: Concurrent connections (head + tail) were killing each other — every new HTTP connection overwrote a global request ID, instantly aborting the other. Players that open two connections (VLC, mpv, ExoPlayer) would loop endlessly until enough pieces were cached. Replaced with a seek-generation counter that only aborts stale connections on actual seeks
- FIX: Tail/metadata range requests no longer hijack
read_head— the priority loop stays focused on the playback position instead of jumping to the end of the file - Streaming: LRU piece cache (48 entries) — avoids repeated disk reads for recently served pieces
- Streaming: Head + tail preload on stream start — first 5 pieces get staggered deadlines, last ~512KB is pre-fetched for container metadata (MKV cues, MP4 moov)
- Streaming: Dynamic readahead window (8–40 pieces) scales with download speed, targeting ~15s of buffer
- Streaming: Wider inline lookahead (6 pieces) with staggered deadlines during serve
- Seeking: Cache invalidation on seek — evicts stale pieces, preserves tail pieces
- Seeking: Wider post-seek focus (5 queued pieces instead of 2)
- Engine: Fixed
suggest_mode— was set as bool instead of the correct enum value - Engine: Fixed
torrent_connect_boostexceeding documented max (255) - Engine:
mixed_mode_algorithmset topeer_proportional— stops starving uTP peers behind NAT - Engine: Added DHT bootstrap nodes,
piece_extent_affinity,auto_sequential - Engine: Tuned send buffer watermarks, peer turnover, socket buffer sizes
- Serve: DLNA headers for smart TV compatibility
- Serve: CORS OPTIONS preflight support
- Serve: 2MB send buffer, 1MB send chunks
- Serve: Case-insensitive HTTP Range header parsing
- Serve: Adaptive priority loop interval (100ms buffering, 250ms steady)
1.6.4 #
- CRITICAL FIX: HTTP server sent
Connection: keep-alivebut closed the socket after every request — VLC trusted the keep-alive promise, tried to reuse the dead connection, got a broken pipe, and rendered a black screen. Fixed by switching toConnection: close, which correctly tells the player to open a new TCP connection for each range request. This is the standard model used by other torrent streaming servers. - Serve: HEAD requests now return headers and close cleanly without falling through to the data-serving path
- Serve: Removed redundant
whileloop around single-use connection handling — the code now clearly reflects the one-request-per-connection model
1.6.3 #
- Streaming: Instant start — staggered piece deadlines (0ms, 500ms, 1000ms…) on startup instead of flat 0ms for all. libtorrent's time-critical picker now funnels all bandwidth to piece 0 first, so playback can begin as soon as 1 piece arrives instead of waiting for 8
- Streaming: Shrunk critical window from 6 pieces → 2, hot window from 9 → 5, readahead from 15 → 6 — concentrates bandwidth on the most urgent data per libtorrent's streaming docs: "any block you request that is not urgent takes away bandwidth from urgent pieces"
- Streaming: Buffer percentage now based on the 2-piece critical window — reports "ready" faster since it no longer waits for 6 pieces
- Seeking: Tighter seek focus — 2 pieces at staggered near-zero deadlines + 2 more at 200ms stagger (was 4 all at 0ms), reducing bandwidth dilution on seek
- Seeking: Seek cooldown reduced from 1000ms → 100ms — priority loop resumes almost immediately after a seek instead of staying blind for a full second
- Seeking: Wait timeout reduced from 120s → 30s — fails faster on dead peers instead of hanging
- Performance: Priority loop now runs every 100ms (was 200ms) for faster reaction to playback position changes
- Performance: libtorrent
tick_intervalset to 100ms (was 500ms default) — internal scheduler reacts 5x faster to deadline changes and priority updates - Serve: Inline lookahead reduced from 5 → 3 pieces with 100ms stagger (was 10ms) — less bandwidth competition with the current piece
1.6.2 #
- CRITICAL FIX: Removed
force_recheck()from cache eviction — it was re-hashing the ENTIRE torrent, marking ALL pieces (including currently streaming ones) as unknown, killing the stream - Streaming: Capped readahead window to 50% of cache capacity — prevents downloading so far ahead that the cache overflows and evicts data at the current playback position
- Streaming: Hard safety floor — cache eviction NEVER evicts anything within 5 pieces of the current playhead, regardless of cache pressure
1.6.1 #
- Streaming: Fixed serial pipeline stall after seek —
serve_rangenow pre-primes the next 5 pieces with priority 7 and staggered deadlines before eachwait_for_piececall, so the swarm downloads them in parallel instead of one at a time - Streaming: Reduced seek cooldown from 3s → 1s — the new serve_range lookahead covers the gap, so the priority loop can resume sooner and set broader readahead windows
1.6.0 #
- Streaming: Rewrote priority system using torrest-cpp's proven priority-only-upgrade pattern — never downgrade piece priorities, staggered
i*10msdeadlines for the hot window - Streaming: Increased critical window from 3 → 5 pieces at deadline=0ms for faster initial playback
- Streaming: Total seek focus — on seek, all piece priorities are wiped and ONLY the seek position + 3 pieces get deadline=0ms with a 3-second cooldown before the priority loop resumes
- Streaming:
wait_for_piecetimeout increased from 15s → 120s to prevent "Stream ends prematurely" errors during slow torrent startup - Streaming: Reduced readahead buffer from 30 → 15 pieces to concentrate bandwidth closer to the playhead
- Engine: Added
no_recheck_incomplete_resume— skips file recheck on resume for faster startup - Engine: Added
allow_multiple_connections_per_ip— connects to seedboxes, VPNs, and shared NAT peers - Engine: Added
peer_connect_timeout=3sfor faster peer handshakes - Engine: Tuned timeouts to stop peer churn (
piece_timeout2→5s,request_timeout2→4s,peer_timeout5→10s) — proven by libtorrent issue #7666, torrest, and Elementum - Engine:
whole_pieces_thresholdincreased 5 → 20, forcing fast peers to complete whole pieces instead of scattering blocks
1.5.0 #
- Streaming: Removed speculative tail preloading — the engine no longer downloads the last 4MB of a file at startup. Modern players (MPV, VLC, etc.) fetch container metadata (MP4 moov atom, MKV cues) on-demand via HTTP range requests, which the built-in server already supports
- Streaming: Head-only preload now sets 8 pieces at flat deadline=0ms instead of staggered 30ms intervals, focusing 100% of startup bandwidth on the beginning of the file
- Streaming: Removed file anchor logic from the priority loop that re-prioritized the last 2 pieces every 200ms, which competed with the playhead for bandwidth
- Performance: Startup time reduced from ~30–60s to ~5–15s by eliminating bandwidth competition between head and tail piece downloads
1.4.0 #
- Platform: Added iOS support
1.3.0 #
- Platform: Added iOS support (arm64 device + x86_64 simulator, universal static library)
- CI: New
build-iosjob cross-compiles libtorrent + torrent_bridge as a static.afor iOS, merged withlipo - Packaging: iOS podspec with
-force_loadso all FFI symbols are visible viaDynamicLibrary.process()
1.2.0 #
- License: Switched to GPL v3 (OSI-approved)
- Streaming: Dual-end preloading — fetches first 4MB and last 4MB of the file simultaneously on stream start. The tail contains the MP4/MKV moov atom (seek table), enabling instant seeking without buffering the whole file first
- Streaming: Staggered 30ms piece deadlines on the head (down from 45ms) for faster playback start
- API:
disposeTorrent(id)— stop streams, remove torrent, and delete files in one call - API:
disposeAll()— clean up every torrent and stream at once (ideal for exit button) - API:
startStream()now acceptsmaxCacheBytesfor a sliding window RAM cache limit - API:
init()now acceptsdefaultSavePath(defaults to system temp dir — no permission setup needed) - API:
addMagnet()andaddTorrentFile()savePathis now optional (usesdefaultSavePath) - README: Fully rewritten with complete API documentation and code examples
1.1.0 #
- Streaming: Removed
sequential_downloadflag (conflicts withset_piece_deadline) - Streaming: Reduced readahead from 150 to 30 pieces to avoid excessive pre-buffering
- Streaming:
clear_piece_deadlines()on seek + 1-second cooldown for faster seek response - Streaming: Re-enabled uTP for incoming and outgoing connections (reaches more peers behind NAT)
- Cache: Configurable RAM cache limit with percentage-based sliding window eviction (10% safety buffer, min 5 pieces)
- Save path: Defaults to system temp directory on all platforms
- CI: Automatic GitHub Release creation with zipped native libraries on every build
- pubspec: Added
repository,issue_tracker, andtopicsfields for pub.dev discoverability
1.0.0 #
- Initial release
- Native libtorrent 2.0 bindings via Dart FFI
- Built-in HTTP streaming server with byte-range support
- Windows, Linux, macOS, and Android support with prebuilt binaries (no build required)
- Auto-fetches best public trackers on startup
- Magnet link and .torrent file support
- Per-file streaming with automatic largest-file selection
torrentUpdatesandstreamUpdatesstreams for reactive UI- DHT, PEX, LSD peer discovery