mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-11-12 12:05:07 +00:00
57 KiB
57 KiB
Changelog
All notable changes to this project will be documented in this file.
This project adheres to Semantic Versioning.
This changelog is automatically generated using git-cliff.
[6.0.0] - 2026-10-13
Features
- binary: Add custom binary registration for services
- cdm: Send license_type and privacy_mode with the request to the server
- click: Change the minimum time for slow
- downloader: Adaptive worker scaling, tail boost, session parity, resume fixes
- downloader: Fan large segment batches across worker processes
- downloader: Resume failed downloads from completed segments across runs
- dl: Run user post-download scripts with metadata variables
- dl: Add --require-audio/--require-video and --warn-only alias
- drm: Let a track pin the DRM system it licenses with
- dl: Add --no-attachments to skip cover art and subtitle fonts
- dl: Add --cdm to pin one CDM device for a run
- post-scripts: Add wait option to block until the script exits
- post-scripts: Show a spinner while waiting for a script
- services: Add services_repo_force and compact refresh output
- serve: Hot-reload service repos on a timer without a restart
- serve: Gate server_cdm per service and let clients follow it
- kv: Show a progress bar while adding keys to a vault
- serve: [breaking] Gate the server's own proxies behind server_proxy
- vaults: Batch HTTP json vault writes with InsertKeys
- remote: Forward HLS segment filters to remote clients
- serve: Add --quiet mode and developer dashboard API
- serve: [breaking] Add server-held accounts for remote sessions
- serve: Forward per-session service logs to remote-dl clients
- proxy: Mask proxy credentials in console and API output
- remote: Spoof a type-only CDM so server_cdm clients need no local .wvd/.prd
- serve: Add operator dashboard endpoints and per-key rate limits
- audio: Support DTS:X Profile 2 with MP4 muxing
- dl: Add --no-postscript to skip post-scripts for one run
- api: Report the live title and the client's command line to the dashboard
- vaults: Flag and skip wrong content keys from poisoned vaults
- remote: Verify server-CDM vault keys on the client and report bad pairs
- dl: Add --proxy-download for a separate download proxy
- vaults: Report bad keys to the vault that served them
- service: Add GEOBLOCK negative geofence
- dash: Add merge_segments to append segments during the download
- manifests: Extend merge_segments rolling merge to HLS and ISM
- export: Write mediaexport files and read legacy exports through the package
- proxies: Add Control D proxy provider
- export: Record each track's KIDs
- import: Build tracks from direct-file export rows
- export: Name export files after their titles and tracks
- export: Separate export file name parts with dots
- remote: Keep slow remote session requests alive with a heartbeat
- remote: Cap server CDM licensing by height per API key and service
- remote: List only configured services on the dashboard
- serve: Relay service prompts from download jobs to the REST client
- remote: Let a remote client license with its own device identity
- dl: Add --latest-episodes N to download the N newest episodes
- setup: Add unshackle setup command and cross-platform install scripts
- remote: License with the client's device when the user picked one
- dl: Add --all-drm to license Widevine and PlayReady per track
- dl: Add --audio-description-only and --forced-subs-only
- serve: Log CDM calls for the dashboard
- serve: Reload unshackle.yaml on SIGHUP without a restart
- serve: Add --cdm-only for a CDM backend with no REST API
- service: Add wait_for_approval and return the cache for a login with no prompt
- serve: Relay approval messages to jobs and proxy remote downloads
- search: Add ANONYMOUS_SEARCH to skip the login for a service
- dl: Add --sample and --include-sample
- dl: Load the DRM system a cdm entry lists first
- api: Forward exact_lang to the service context
Bug Fixes
- downloader: Release hedge loser file handles before merge sweep
- downloader: Validate 206 on byte-range segments and force identity encoding
- downloader: Stop leaked racers holding segment handles after a failed batch
- dash: License ClearKeyCENC before decrypt
- subtitle: Convert ASS to SRT in the SDH-strip fallback
- api: Keep sub_format "original" working through the API
- webvtt: Don't shorten cues when splicing boundary duplicates
- api: Reject backslash traversal in safe_cache_key
- downloader: Honor Retry-After with cancel-safe backoff, add fault-injection bench and tests
- downloader: Keep speed-limited batches in a single process
- downloader: Fail closed on rnet content codings outside the old allowlist
- downloader: Accept a 200 whose body is exactly the requested byte-range slice
- downloader: Report rolling speed on the multiprocess progress bar
- downloaders: Submit segments in a window so progress can drain
- api: Pass adaptive_workers and download_processes to dl.result
- downloader: Validate Content-Range before placing 206 bytes
- downloader: Harden ranged reads, teardown and multiprocess sessions
- titles: Drop folder {year?} when it repeats the dated season label
- cli: Work around rich-click's patched click classes
- vaults: Look tables up by the name the vault stores
- hls: Keep ad-filtered segments out of DRM key state
- music: Remux songs into the container of their codec
- api: Survive Windows errno 13 on the job progress file
- api: Guard two more Windows errno 13 paths in the serve layer
- dl: Accept a clamped 206 and report audio-description-only titles
- services: Match service aliases without case
- downloader: Keep retrying while a cut connection makes progress
- downloader: Bound requests after a cut and stop retry nesting
- subtitle: Keep WebVTT-only cue markup out of converted subtitles
- proxies: Resolve windscribevpn hostname prefixes and uk alias
- mux: Give each parallel mux its own chapters temp file
- remote: Carry the full title and track state across the remote API
- HTTP: Simplify key retrieval condition in get_key method
- tracks: Match resolutions per range and codec
- remote: Resolve service names against the remote server
- remote: Send only the active profile's cache files to the server
- utils: Preserve _ssl_context when copying SSLCiphers adapter
- util: Remove :
- cli: Show banner when dl -q is used
- serve: License multi-key PlayReady through server CDM instead of vault subset
- remote: Raise GET timeout to 120s so large catalogs load
- cdm: Scope remote CDM licence state to its session
- remote: Pass fallback language to ISM re-parse
- ism: Signal Dolby Vision and Atmos from Smooth manifests
- dash: Number SegmentTimeline segments from startNumber
- remote: Match re-parsed manifest tracks by ID before attributes
- remote: Send per-track MPD fragments for service-built AdaptationSets
- dl: Repair damaged cookie files without rewriting them
- kv: Keep copy log rows single-spaced
- dl: Fall back to local vaults when the server CDM returns no key
- cli: Stop service tags from renaming CLI options
- dl: Log vault writes under their own title
- dl: Specify 'subtitle tracks' in error log message
- remote: Keep option choices and optional title in remote -h
- audio: Accept immersive channel layouts like 5.1.4
- serve: Resolve DRM keys for manifests with no ContentProtection PSSH
- dl: Reject local proxies when --remote targets another machine
- dl: End a cancelled track by raising instead of returning short
- services: Name the build a compiled service is missing
- serve: Lock shared session state and throttle progress writes
- downloader: Correct truncation, ranged sizing, and session carry
- dl: Cache server-CDM keys to the local vaults
- drm: License every PlayReady header until all KIDs are covered
- dash: Treat a missing FFprobe as no PSSH instead of crashing
- api: License every PlayReady header in the server CDM path
- api: Reach every PlayReady header on all server CDM routes
- api: Let the server CDM see service-supplied keys and HLS track DRM
- api: Tell the service that the client sent a cookie jar
- api: Stop serve leaking server credentials, paths, and cross-tenant data
- api: Keep error URLs readable and mask host paths in dashboard logs
- api: Reject a NUL byte in output_dir before resolving it
- manifests: Flag DASH audio using the standard description role
- api: Serialize the job progress replace to stop Windows errno 13
- api: Decode challenge bytes to UTF-8 for PlayReady license request
- proxy: Check the proxy exit IP before any service request
- cookies: Find Firefox profiles in the XDG config directory
- naming: Correct language tag rule matching and add state conditions
- config: Keep no and yes as language tags
- import: Inject only the imported title's keys into each track
- main: Remove unwanted -
- serve: Defer service hot reload while a remote session uses it
- remote: Return session cache for device-code and cache-only logins
- remote: Honor proxy client cdm_type for DRM system selection
- drm: Log missing Widevine/PlayReady PSSH at debug level
- cli: Make the click param types the one source of codec spellings
- vaults: Verify vault content keys per KID from the fragment map
- vaults: Harden the KID window check and clear a stale flag on licence
- remote: Forward nested service cache files to and from the server
- remote: Stop warning about missing keys for tracks that carry no DRM
- remote: Keep the server's own CDM when the tier licenses with server_cdm
- post-scripts: Expose {part} and all title-owned variables on failure
- serve: Apply staged service reloads when sessions end, with a max staging age
- remote: Let the server's CDM mapping decide the DRM system under server_cdm
- remote: Forward dl track selection and profile to remote sessions
- dl: Skip empty vault pushes and count cached keys once
- serve: Stop repeating server vault pushes and retry failed ones
- export: Import side-loaded subtitles and keep conflicting keys apart
- export: Strip session headers from exports and normalise merged keys
- import: Read export files through mediaexport
- export: Skip bad keys and failed writes without stopping the download
- import: Report refused titles and fail when none is usable
- drm: Give the zero-KID fallback only the track's own key
- import: Give each track only the keys it declares
- import: Stop clearly when no export or vault key exists
- export: Name the file from the first write
- import: Say an import uses the export's keys, not a server CDM
- import: Give no title keys to a track that is clear
- import: Read an HLS export that names no title language or master key
- remote: Report a missing title list and a refused track URI clearly
- tracks: Keep the Dolby Vision record when remuxing video with ffmpeg
- proxies: Match surfshark's current server api
- proxies: Skip a proxy provider that fails to load
- proxies: Return None for unservable queries and repair live providers
- proxies: Link to the expressvpn device login with the code prefilled
- cdm: Skip the server header probe for pywidevine and pyplayready remote CDMs
- api: Stop dashboard event and log reads racing worker threads
- api: Keep the worker's error on failed jobs, gate tracebacks behind --debug-api
- sanitize: Keep nonspacing marks on letters in unicode filenames
- sanitize: Normalise filenames to NFC and keep combining marks
- console: Write UTF-8 to redirected streams on Windows
- dl: Keep the --enrich original language after get_tracks
- attachment: Keep custom fonts after mux cleanup
- dl: Keep the --enrich title and year after get_tracks
- docs: Hide the release version in the header repo widget
- dl: Read the vaults first under --all-drm
- hybrid: Read the container file for a base that had the DV fixup
- cdm: Send a PlayReady licence without an XML declaration as XML
- import: Carry the HLS segment filter in an export
- cdm: Simplify cached keys retrieval in CustomRemoteCDM
- hls: Read the key id from the init segment when the PSSH has none
- api: Follow the cdm config key order for the server CDM
Documentation
- session: Correct stale pool-size comment
- Strip non-essential comments, fold key facts into docstrings
- services: Add MUSIC_EXAMPLE reference service
- Apply simplified technical english across docs and docstrings.
- Phase 2 of the prose style across docs and docstrings
- Widen supported shaka-packager range to 2.6.1 or >= 3.10.0
- dev: Correct get_chapters guidance on markers at timestamp 0
- example: Show drm_preference pinning for dual-PSSH manifests
- post-scripts: Use post-script as the one term for hooks
- api: Describe the dashboard session payload in the OpenAPI yaml
- cli: Correct --merge-video scope in cli reference
- export: Describe the export file name and its messages
Performance Improvements
- downloader: Slow-start ramp for the adaptive worker controller
- downloader: Use per-arrival reads only while a segment is hedge-raced
- dash: Collapse single-URL byte-range segments into one direct download
- downloader: Stride multiprocess chunk assignment across children
- api: Skip progress re-parse when the file is unchanged
- api: Append job history instead of rewriting the file
- downloader: Unblock hedge-loser reads at teardown
- dash: Speed up segment collection and URL templating
- dl: Parallelise mux, licensing, and vault lookups; size the shared pool
- dl: Overlap hybrid builds with muxing, tag in the mux thread, preload DRM in parallel
- hybrid: Reuse DV-side files across resolutions, trim the RPU chain, fix L6 fallback
- dl: Push vault key writes to a background thread
- drm: Decrypt fMP4 segments during download with mp4decrypt
- kv: Push whole services to SQL vaults in one call
- kv: Push keys to vaults concurrently, log one summary per title
- sample: Download only the subtitle segments around the window
- manifests: Decode manifests without charset detection
Changes
- monalisa: Remove ML-Worker and improve MonaLisa DRM
- downloader: Extract shared byte-range split helper
- console: Route interactive prompts through a themed helper
- core: [breaking] Drop leading underscores from internal definitions
- tests: Drop leading underscores from test helper functions
- music: [breaking] Make Song an ordinary Title on the generic path
- console: Style env listings like the rich-click help screens
- drm: Drop the hardcoded service branch in the license flow
- proxies: Share proxy dispatch between dl, search and resolve_proxy
Maintenance
- Restore memory/ to .gitignore from dev
- scripts: Expand bench suite for cross-machine runs
- scripts: Harden bench suite report capture
- scripts: Add attempt-1-only tail-slow fault to downloader bench
- Bump dev version to 5.5.0
- Mark install.sh executable
Builds
- deps: Pull mediaexport from github in the package metadata
- deps: Lock mediaexport at fa9357e
5.4.0 - 2026-08-15
Features
- api: Report per-episode and per-track progress on download jobs
- api: Add job retry/priority/clear, history, config and maintenance endpoints
- api: Expose choice values and multiple flag in service cli_params
- core: Add debug logging for rnet requests
- tracks: Add subtitle.type_priority config for variant ordering
- proxies: [breaking] Rewrite ExpressVPN provider to Android device login
- dl: Animate merge/decrypt/mux stages with gradient pulse bars
- tags: Add imdb_api_enabled toggle, off by default
- tags: Add OMDb metadata provider with omdb_api_key config
- cdm: Stamp remote CDM DRM type at load for reliable detection
- ism: Harden Smooth parsing and derive fps/codec from spec fields
- Original-language aware DUAL/MULTi tagging and new DUBBED variable
- drm: Add PlayReady HRESULT decoder
- drm: Detect revoked PlayReady devices from license responses
- drm: Auto-repack tracks with a residual encrypted sample entry
- dl: Extend --select-titles to movie listings
- Show git commit hash alongside the version
- Identify the running code by source hash
- dl: Add --speed-limit and serve global_speed_limit
- providers: Add TheTVDB v4 as a metadata provider
- tracks: Add subtitle.group_by to keep a language with its variants
- temp: Give each download task its own temp directory
- dl: Add -fsl/--forced-s-lang to filter forced subtitles by language
- tracks: Add language_priority to sort preferred languages first
- vaults: Support custom headers on API vault
- dl: Add tag_rules to conditionally swap the group tag
- titles: Add optional Episode.part, selected with -w s1e1.2
- enrich: Fill in the original language from metadata providers
- dl: Allow --tvdb as an --enrich metadata source
- dl: Exclude languages with a - prefix on -l, -vl, -al, -sl and -fsl
- metadata: [breaking] Authoritative id resolver and keyless imdb provider
- metadata: [breaking] Replace animeapi with a first-class anilist provider
- dl: Add absolute episode numbers filled from tvdb absolute order
- dl: Add daily date-based episodes with tvdb air-date fill
- api: Stream download job progress over server-sent events
- remote: Accept serve.users keys in api-only mode and add client auth-header fallback
- serve: Gate server CDM licensing behind a per-key server_cdm opt-in
- cli: Add named color themes and rich-formatted help
Bug Fixes
- api: Use PBKDF2 instead of SHA256 for cache-namespace hashing
- api: Pass track-selection params to service context
- remote: Add missing get_clearkey_license to RemoteService
- remote: Harden serve API access control and input handling
- core: Decode subprocess output as UTF-8 with replacement
- tracks: Treat ccextractor signal-crash as non-fatal
- downloader: Release hedge loser file handles before merge sweep
- dl: Restore real progress bars where progression is trackable
- dl: Select only best descriptive audio track per language
- dl: [breaking] Make audio/video track selection consistent and crash-safe
- tags: Point IMDbApi provider at api.tiffara.com (IMDxAPI)
- gitignore: Add memory directory to .gitignore
- dl: Prevent missing tracks error when excluding track types
- subs: Stop segmented WebVTT merge from stripping formatting
- proxies: Show ExpressVPN country/location counts at startup
- tracks: Keep regional language variants distinct in exact selection
- services: Register modules in sys.modules so repo-cloned services can self-import and remove old benchmark that should have been deleted
- Skip decrypt on mislabeled-clear segments
- Harden ClearKey/CENC decryption correctness
- import: Stop losing side-loaded subtitles and blaming the manifest URL
- ism: Emit two stsd entries so sample_description_index 2 resolves
- ism: Repair synthesized init and verify fragments decrypted
- core: Strip trailing spaces and dots in template formatting to prevent WinError 3
- templates: Use one separator style across a whole folder path
- lang: Surface orig in errors and flag the original audio track over the API
- tracks: Ignore leftover PIFF uuid when verifying decryption
- tracks: Size the no-proxy download session's connection pool
- import: Scope the merge-back and detect ISM protection
- dl: Honour --no-proxy-download for attachments
- tools: Pass -nostdin to all ffmpeg calls
- subtitles: Strip X-TIMESTAMP-MAP so WebVTT cues are not offset on conversion
- downloader: Decode content-encoded bodies instead of writing raw
- downloader: Surface failed downloads instead of returning silently
- dl: Warn when --enrich source is missing title, year, or language
- api: Carry air_date, absolute, anime and daily across the title wire
- dl: Treat audio muxed into the video as an available language
- hls: Take the key id from EXT-X-KEY when the PSSH carries none
- dl: Reset per-title language and range selection each iteration
- subtitle: Keep cue-less webvtt instead of failing the download
- services: Re-raise ClickException for better error handling in remote services cache
- dash: Resolve representations by adaptation set, not id alone
- kv: Search remote vaults that cannot list their tables
Documentation
- Restructure documentation into MkDocs Material site
- Expand config reference and genericize service names
- changelog: Regenerate with git-cliff
- Correct DRM, muxing, and proxy references (+ case-insensitive proxy prefix fix)
- Cleanup and correct documentation
- core: Drop service tags from framework comments
- Cover the TVDB provider, episode ordering and provider order
- Split configuration reference into per-area pages
- api: Note the - language exclusion prefix in the OpenAPI spec
Performance Improvements
- downloader: Cut per-segment overhead, bound stalled connections
- Little improvements here and there
- pipeline: Fix pool starvation, unlock vault writes, prep mux
- Speed up the code hash with sha1 and a plain file reader
Changes
- core: [breaking] Bundle download_track args into DownloadContext
- tracks: Honour the best token and share one match rule
Maintenance
- changelog: Update entries for new features and bug fixes
- env: Drop ML-Worker from the dependency check
- changelog: Update changelog
Builds
- deps: Cap pycaption below 2.2.27
- mypy: Enable explicit_package_bases
5.3.0 - 2026-07-01
Features
- dl: Add --merge-video to merge video language variants
- Native ExpressVPN HTTPS Proxy Provider
- Support Python 3.14 and widen range to 3.11-3.14
- Add automatic Firefox cookie and localstorage extraction
- api: Expose title description, date and cover_url in serialize_title
- api: Expose active-track segment counts and transfer speed in job progress
- vaults: Add configurable network timeout for remote vaults
- docs: Add per-vault network timeout configuration for remote vaults
- services: Load service plugins from git repos
- proxies: Add Proton VPN proxy provider
- output: Support nested directories in folder templates
- proxies: Add ProtonVPN TV login, drop cookie refresh
- titles: Add air_date for date-based episode naming
Bug Fixes
- api: Annotate routes.py to pass strict mypy
- config: Match per-service cdm keys case-insensitively
- drm: Don't switch to a mismatched CDM type during licensing
- env: Only resolve Path items in directory lists
- output: Treat
/and\as folder separators on any OS - console: Pause active live contexts during terminal input
- dl: Apply per-service decryption tool override
- hls: Stream segment merges to avoid OOM on large tracks
Documentation
- Rename to match other docs.
- config: Make docs/ canonical, slim unshackle-example.yaml to a starter
- Add MkDocs Material documentation site
- readme: Link Docs to docs.unshackle.dev, remove Wiki
- Add "Creating a Service" guide
- Fix inaccuracies in service-creation guide
Performance Improvements
- tracks: Skip redundant DV/VUI bitstream passes
- hls: Rename single decrypted range instead of re-copying
Changes
- api: Remove dead code paths in serve/remote layer
- api: Dedup handler serializers, validation, and service setup
- api: Use Event.wait and a shared to_enum helper
- api: Collapse route registration into single ROUTES table
- api: Drop dead error codes, lock error contract harness
5.2.0 - 2026-06-16
Features
- vault: Add VAULT_TAG to share key vault across services
- subtitle: Data-driven conversion registry + SubtitleEdit 5 support
- subtitle: Support 'original' sub_format to keep source format
- api: Aggregate REST download progress with weighting, track labels and mux stage
- logging: Expand debug-logging coverage, add primitives, redaction & tests
- logging: Add debug_requests flag and aggregate subtitle-conversion logs
- drm: Add native DASH ClearKey (org.w3.clearkey) support
- music: Native music core - shared helpers, album folder template, display cleanup
Bug Fixes
- core: Replace deprecated ast.Num visitor in FPS parser
- hls: Decrypt AES-128 (ClearKey) media-playlist keys + per-segment sequence IV
- dl: Mux hybrid ingredients standalone only when range explicitly requested
- dl: Make a failed subtitle non-fatal under --skip-subtitle-errors
- api: Repair REST API downloads, add /services flags & live progress
- dl: Apply per-service dl config overrides for all options
- security: Sanitize logs, redact secrets, harden XML parsing
- dl: Export DRM-free, ClearKey, MonaLisa and server-CDM tracks
- ism: Rebuild moov init segment for Smooth Streaming decrypt
- ism: Derive video colour range from CodecPrivateData SPS VUI
- subtitle: Drive SubtitleEdit 4.x with legacy /convert syntax
Changes
- cli: Replace deprecated click.MultiCommand with click.Group
- dl: Type the two-pass download helper + pin skipped_subtitles shape
5.1.0 - 2026-06-03
Features
- ip-info: Consolidate IP lookup, add ipinfo.io token support
- dl: Cache content keys in-memory to skip duplicate license requests
- mux: Add muxing.default_language to override default track per type
- hls: Detect DV-composite tracks and restore signaling post-mux
- video: Normalize SPS VUI to match manifest-derived range
- api: Sync /api/download with dl CLI flags and add serve.* defaults
- vaults: Tolerate vault failures during key get/add
- tracks: Configurable audio codec priority for tie-breaking
- dl: Live countdown for --slow delay
- dl: Gate s_lang/a_lang miss behind --best-available
- dl: Add real bitrate probing (-rvb/-rab)
- import: Reconstruct downloads from an --export sidecar
- naming: Per-service title_map remapping
- import: Include cover-art attachments in --export/--import
Bug Fixes
- manifests: Clean stale .!dev resume markers before merge
- sanitize: Preserve parentheses, strip unidecode bracket artifacts
- tracks: Honor --worst in hybrid range selection
- dl: Re-pick DV/HDR10 when HYBRID falls back under best_available
- proxies/nordvpn: Use *.proxy.nordvpn.com for HTTPS proxy
- template_formatter: Preserve dash separator around empty conditional
- dl: Prefer Atmos in -l best/all language selection
- title: Detect Atmos across all audio tracks for filename template
- title: Use original-language audio for filename metadata
- service: Render request_input prompt via rich console
- titles: Normalize odd resolutions in filename quality token
- api: Propagate Click default=None through service instantiation
- api: Load real CDM for service init in list/session/download flows
- vaults: Enable WAL on SQLite vault to fix concurrent locks
- hybrid: Correct static L6 source and reset stale L5 active area
- cli: Report broken command/service loads once and cleanly
- hls: Resolve per-rendition KID in no-EXT-X-KEY fallback
- dash: Inherit SegmentTemplate attributes across AdaptationSet/Representation
- dl: Mux all requested ranges and select highest DV alongside hybrid
- session: Proxy auth on http targets and string params support
Documentation
- Update docs to match current codebase
- output: Document muxing.default_language override
- Simplify README with demo and requirements
Changes
- routes, subtitle, track: Improve code readability by formatting list structures
- hybrid: Extract dovi_tool and run_step helpers
- ip_info: Simplify lookup and trim cache
- example: Showcase full unshackle feature surface
- dl: Declare hybrid_base_only flag and extract standalone mux helper
- Remove dead aria2c and n_m3u8dl_re downloader code
Maintenance
- pre-commit: Update hook versions in .pre-commit-config.yaml
- changelog: Update version date and add new features and fixes for 5.1.0
- changelog: Update changelog and cleanup readme
5.0.0 - 2026-05-04
Features
- dl: Add --vbitrate-range and --abitrate-range options for bitrate range selection
- remote: Server vault lookups, service CDM mapping, key display, and service param forwarding
- remote: Interactive auth handshake, server CDM, cache round-trip, and serve remote-only mode
- template: Add configurable folder naming via output_template.folder
- hls: Probe TS segments for resolution and codec when master playlist lacks RESOLUTION/CODECS tags
- downloader: Consolidate into unified requests-based downloader
- dash: Refactor segment extraction and add content period validation
- downloader: Optimize download throughput with Queue-based threading and raw reads
- session: Replace curl_cffi with rnet for TLS-fingerprinted HTTP
- session: Translate requests 'data' kwarg to rnet equivalents for compatibility
- dl: Allow --slow to accept custom delay range
- serve: Add service allowlist for global and per-user access control
- dl: Change --export flag with manifest URL, subtitles, and track info
- dl: Add download resume support via HTTP Range headers
- track: Add optional per-track session parameter
- session: Optimize header handling in session requests
- kv: Add search subcommand to look up KID across vaults
- kv: Add --local-only flag to copy/sync
- config: Per-title-type folder templates
- dl: Add --no-proxy-download flag
- docs: Add AGENTS.md to .gitignore
Bug Fixes
- Update actions/checkout to v5 in release workflow
- audio: Support 'xheaac' profile
- drm: Include external KID in PSSH when it differs from existing KIDs
- deps: Bump PyJWT minimum to 2.12.0 for CVE-2026-32597
- sanitize: Restore parentheses stripping in filename sanitization
- serve: Allow remote-only mode without output_template and fix CORS/auth for Cloudflare
- remote: Forward track selection params to server and improve error display
- subtitle: Decompress gzip/zlib responses for subtitle downloads
- drm: Add zero-KID fallback for mp4decrypt and clear HLS track.drm after download
- drm: Add track ID fallback for mp4decrypt CBCS zero-KID content
- hybrid: Read actual HDR metadata for HDR10+ to DV conversion
- template: Detect folder spacer from template separators, not raw string
- session: Native rnet proxy support and cookie compat layer
- deps: Bump aiohttp and pygments to resolve 11 security vulnerabilities
- api: Sanitize user-provided values in log statements to prevent log injection
- dl: Preserve per-language video selection in quality step
- dash: Add SIDX parsing for SegmentBase manifests and deduplicate multi-period segments
- gluetun: Support WireGuard VPN ready detection
- api: Sync REST API download endpoint with updated dl command
- drm: Handle non-UTF-8 output from shaka-packager stderr
- tags: Prevent metadata lookup failures from skipping group tag
- dl: Always report full error trace for download worker failures
- dash: Deduplicate multi-period SegmentBase segments
- dash: Expand CICP enums to full H.273 range
- drm: Pass per-segment PSSH to PlayReady license callback
- drm: Pass per-segment PSSH to Widevine license callback
- hls: Carry DRM keys forward across EXT-X-KEY rotation
Documentation
- api: Update --export from string path to boolean flag
Performance Improvements
- downloader: Optimize hot loop and threading efficiency
- downloader: Parallel byte-range fetch for single-URL tracks
Maintenance
- gitignore: Ignore binary files in unshackle/binaries/
- Update version to 5.0.0
4.0.0 - 2026-03-17
Features
- hybrid: Add L5 active area and dynamic L6 luminance metadata
- debug: Add JSONL debug logging to decryption, muxing, and all downloaders
- debug: Log binary tool versions at session start
- dl: Add --repack flag to insert REPACK tag in output filenames
- core: Add TrackRequest system for multi-codec/multi-range support
- dl: Add --output option to override download directory
- tracks: Add edition tags to output filenames
- templates: [breaking] Add customizable output filename templates
- templates: Add configurable language tagging rule engine
- Update unshackle version to 4.0.0
- dl: Add --animeapi and --enrich options for anime metadata and tagging
- dl: Add skip messages for --no-audio and --no-chapters flags
- dl: Extract closed captions from HLS manifests and improve CC extraction
- dl: Add --worst flag and SHIELD OkHttp fingerprint preset
- dl: Add --remote flag for downloading via remote unshackle server
- remote: Add server-CDM mode, manifest transfer, and region-aware proxy
- remote: Add zlib compression for API payloads and gzip transport
- remote: Fetch service list and CLI options from server for --remote help
- session: Add IP validation for session access and enhance session management
Bug Fixes
- n_m3u8dl_re: Pass all content keys for DualKey DRM decryption
- hybrid: Skip bitrate filter for DV tracks in HYBRID mode
- attachment: Sanitize filenames with illegal Windows characters
- hybrid: Accept HDR10+ tracks as valid base layer for HYBRID mode
- dl: Allow selection of audio tracks for 'all' languages in addition to 'best'
- dl: Overwrite existing files on re-download and use atomic replace
- dl: Handle cross-device moves when temp and downloads differ
- track: Fallback to requests downloader from n_m3u8dl_re for unsupported track types
- n_m3u8dl_re: Disable segment count validation for duration-based DASH
- Correct formatting and add missing newlines in selector and EXAMPLE service
- dependencies: Update pyplayready version to 0.8.3 and adjust dependencies
- drm: Update PlayReady KID extraction for pyplayready 0.8.3 compatibility
- api: Resolve Sentinel serialization, missing params, and add search endpoint
- dash: Pass period_filter to n_m3u8dl_re via filtered MPD file
- title: Add HDR Vivid Format HDR Tag
- ism: Prevent duplicate track IDs for audio tracks with same lang/codec/bitrate
- aria2c: Correct progress bar tracking for HLS downloads
- dl: Filter CC subtitle languages with --s-lang and extract all manifest CCs
- serve: Use X-Secret-Key header for REST API auth to match pywidevine
- drm: Preserve original PSSH for content_id-based Widevine manifests
- drm: Add zero-KID fallback for mp4decrypt and clear HLS track.drm after download
Documentation
- Update and correct configuration documentation
- dl: Add comprehensive list of available
dlkeys and their descriptions - Update API and configuration documentation with example service tags
Changes
- hybrid: Replace log.info with console status and add JSONL debug logging
- dl: Remove legacy multi-fetch loop for unmigrated services
- example: Migrate EXAMPLE service to track_request pattern
- providers: Extract metadata providers into modular system
- remote: Deduplicate CDM loading, proxy resolution, and license handling
Maintenance
- changelog: Update changelog for upcoming release and reorganize sections
- changelog: Update changelog
- changelog: Tag v4.0.0 release
3.0.0 - 2026-02-15
Features
- titles: Use track source attribute for service name in filenames
- debug: Add download output verification logging
- Gluetun VPN integration and remote service enhancements
- gluetun: Improve VPN connection display and Windscribe support
- serve: Add PlayReady CDM support alongside Widevine
- cdm: Add remote PlayReady CDM support via pyplayready RemoteCdm
- env: Add ML-Worker binary for DRM licensing
- video: Detect interlaced scan type from MPD manifests
- drm: Add MonaLisa DRM support to core infrastructure
- audio: Codec lists and split muxing
- proxy: Add specific server selection for WindscribeVPN
- cdm: Normalize CDM detection for local and remote implementations
- HLS: Improve audio codec handling with error handling for codec extraction
- tracks: Prioritize Atmos audio tracks over higher bitrate non-Atmos
Bug Fixes
- subs: Update SubtitleEdit CLI syntax and respect conversion_method
- n_m3u8dl_re: Include language in DASH audio track selection
- hls: Prefer media playlist keys over session keys for accurate KID matching
- deps: Upgrade vulnerable dependencies for security alerts
- serve: Use correct pywidevine users config format
- cdm: Correct error key casing in Decrypt Labs API response parsing
- api: Validate Bearer prefix before extracting API key
- serve: Correct PlayReady RemoteCDM server validation
- n_m3u8dl_re: Remove duplicate --write-meta-json argument causing download failures
- manifests: Correct DRM type selection for remote PlayReady CDMs
- proxies: Fixes WindscribeVPN server authentication
- subs: Route pycaption-unsupported formats to pysubs2 in auto mode
- proxy: Remove regional restrictions from WindscribeVPN
- proxy: Collect servers from all locations in WindscribeVPN
- downloader: Correct progress bar tracking for segmented downloads
- binaries: Search subdirectories for binary files
- dash: Handle high startNumber in SegmentTimeline for DVR manifests
- drm: Hide Shaka Packager message for MonaLisa decryption
- dash: Add CENC namespace support for PSSH extraction
- dash: Preserve MPD DRM instead of overwriting from init segment
- subtitles: Preserve sidecar originals
- mux: Avoid audio codec suffix on split-audio outputs
- dl: Prevent attachment downloads during --skip-dl
- progress: Force track bar completion on terminal states
- progress: Bind per-track bars and force terminal completion
- dl: Keep descriptive and standard audio for requested langs
- dl: Always clean up hybrid temp hevc outputs
- hls: Finalize n_m3u8dl_re outputs
- downloader: Restore requests progress for single-url downloads
- dl: Invert audio codec suffixing when splitting
- dl: Support snake_case keys for RemoteCdm
- aria2c: Warn on config mismatch and wait for RPC ready
- serve: [breaking] Make PlayReady users config consistently a mapping
- dl: Preserve proxy_query selector (not resolved URI)
- gluetun: Stop leaking proxy/vpn secrets to process list
- monalisa: Avoid leaking secrets and add worker safety
- dl: Avoid selecting all variants when multiple audio codecs requested
- hls: Keep range offset numeric and align MonaLisa licensing
- titles: Remove trailing space from HDR dynamic range label
- config: Normalize playready_remote remote_cdm keys
- titles: Avoid None/double spaces in HDR tokens
- naming: Keep technical tokens with scene_naming off
- api: Log PSSH extraction failures
- proxies: Harden surfshark and windscribe selection
- service: Redact proxy credentials in logs
- monalisa: Harden wasm calls and license handling
- hls: Remove no-op encryption_data reassignment
- serve: Default PlayReady access to none
- tracks: Close temp session and improve path type error
- main: Update copyright year dynamically in version display
Reverts
- monalisa: Pass key via argv again
Documentation
- Add configuration documentation WIP
- changelog: Add 2.4.0 release notes
- changelog: Update cliff config and regenerate changelog
- changelog: Complete 2.4.0 notes
- config: Clarify sdh_method uses subtitle-filter
Performance Improvements
- aria2c: Improve download performance with singleton manager
Changes
- remote_auth: Remove unused requests.Session
- Remove remote-service code until feature is more complete
Maintenance
- api: Remove remote services
Chore
- release: [breaking] Bump version to 3.0.0
2.3.0 - 2026-01-18
Features
- config: Add unicode_filenames option to preserve native characters
Bug Fixes
- drm: Correct PSSH system ID comparison in PlayReady
- dash: Handle placeholder KIDs and improve DRM init from segments
- dash: Handle N_m3u8DL-RE merge and decryption
- drm: Include shaka-packager binary in error messages
- subs: Strip whitespace from ASS font names
- subs: Handle negative TTML values in multi-value attributes
- drm: Filter Widevine PSSH by system ID instead of sorting
- subs: Handle WebVTT cue identifiers and overlapping multi-line cues
2.2.0 - 2026-01-15
Features
- debug: Add comprehensive debug logging for downloaders and muxing
- drm: Add CDM-aware PlayReady fallback detection
Bug Fixes
- util: Improve test command error detection and add natural sorting
- vaults: Batch bulk key operations to avoid query limits
- titles: Detect HDR10 in hybrid DV filenames correctly
- vaults: Adaptive batch sizing for bulk key operations
2.1.0 - 2025-11-27
Features
- export: Enhance track export with URL, descriptor, and hex-formatted keys
- cdm: Add per-track quality-based CDM selection during runtime DRM switching
- Merge upstream dev branch
Bug Fixes
- deps: Pin pyplayready to <0.7 to avoid KID extraction bug
- hls: Convert range_offset to int to prevent TypeError
- video: Correct CICP enum values to match ITU-T H.273 specification
- utilities: Handle space-hyphen-space separators in sanitize_filename
- utilities: Make space-hyphen-space handling conditional on scene_naming
- windscribevpn: Add error handling for unsupported regions in get_proxy method
- Restrict WindscribeVPN to supported regions
- dash: Add AdaptationSet-level BaseURL resolution
- dl: Preserve attachments when rebuilding track list
2.0.0 - 2025-11-10
Features
- Add REST API server with download management
- Add comprehensive JSON debug logging system
- cdm: Add highly configurable CustomRemoteCDM for flexible API support
- proxies: Add WindscribeVPN proxy provider support
- dl: Add --latest-episode option to download only the most recent episode
- Add service-specific configuration overrides
- Add retry handler to curl_cffi Session
- dl: Add --audio-description flag to download AD tracks
- api: Add url field to services endpoint response
- api: Complete API enhancements for v2.0.0
- api: Add default parameter handling and improved error responses
- cache: Add TMDB and Simkl metadata caching to title cache
- session: Add custom fingerprint and preset support
- fonts: Add Linux font support for ASS/SSA subtitles
- subtitle: Preserve original formatting when no conversion requested
- dl: Add --no-video flag to skip video track downloads
Bug Fixes
- Use keyword arguments for Attachment constructor in font attachment
- Only exclude forced subs when --forced-subs flag is not set
- Update lxml constraint and pyplayready import path
- tags: Gracefully handle missing TMDB/Simkl API keys
- config: Support config in user config directory across platforms
- dl: Validate HYBRID mode requirements before download
- drm: Add explicit UTF-8 encoding to mp4decrypt subprocess calls
- subtitle: Resolve SDH stripping crash with VTT files
- naming: Improve HDR detection with comprehensive transfer checks and hybrid DV+HDR10 support
- dash: Correct segment count calculation for startNumber=0
- session: Update OkHttp fingerprint presets
- session: Remove padding extension from OkHttp JA3 fingerprints
- dl: Prevent vault loading when --cdm-only flag is set
- cdm: Resolve session key handling for partial cached keys
- cdm: Apply session key fix to custom_remote_cdm
- n_m3u8dl_re: Read lang attribute from DASH manifests correctly
- subtitles: Fix closure bug preventing SDH subtitle stripping
- Ensure subtitles use requests downloader instead of n_m3u8dl_re if Descriptor.URL
- Suppress verbose fontTools logging when scanning system fonts
- tags: Skip metadata lookup when API keys not configured
Documentation
- Improve GitHub issue templates for better bug reports and feature requests
- Add dev branch and update README
- Update CHANGELOG for audio description feature
- changelog: Complete v2.0.0 release documentation
- changelog: Add --no-video flag and PR #38 credit
- changelog: Set release date for version 2.0.0
- readme: Remove dev branch warning for main merge
Changes
- session: Modernize type annotations to PEP 604 syntax
- binaries: Remove unused mypy import
- Remove unnecessary underscore prefixes from function names
- tags: Remove environment variable fallbacks for API keys
Maintenance
- api: Fix import ordering in download_manager and handlers
- Update CHANGELOG.md for version 2.0.0
1.4.8 - 2025-10-08
Features
- Add AC4 codec support in Audio class and update mime/profile handling
- Add pysubs2 subtitle conversion with extended format support
- Add --no-mux flag to skip muxing tracks into container files
- vaults: Add DecryptLabs API support to HTTP vault
- Add --exact-lang flag for precise language matching
Bug Fixes
- Optimize audio track sorting by grouping descriptive tracks and sorting by bitrate, fixes bug that does not identify ATMOS or DD+ as the highest quality available in filenaming.
- Update lxml constraint and pyplayready import path
- Dl.py
- Upgrade pyplayready to 0.6.3 and resolve import compatibility issues
- Suppress tinycss SyntaxWarning by initializing filter before imports
- (subtitle): Move pysubs2 to not be auto while in "testing" phase.
Reverts
- Remove tinycss SyntaxWarning suppression and fix isort
Documentation
- Add pysubs2 conversion_method to configuration documentation
Maintenance
- Bump version to 1.4.8
1.4.7 - 2025-09-25
Features
- Add options for required subtitles and best available quality in download command
- Add download retry count option to download function
- Add decrypt_labs_api_key to Config initialization and change duplicate track log level to debug
- Add curl_cffi session support with browser impersonation
- Update changelog for version 1.4.7
1.4.6 - 2025-09-13
Features
- Automatic audio language metadata for embedded audio tracks
- Add quality-based CDM selection for dynamic CDM switching
Bug Fixes
- Resolve service name transmission and vault case sensitivity issues
- Improve import ordering and code formatting
Maintenance
- Bump version to 1.4.6 and update changelog
1.4.5 - 2025-09-09
Features
- changelog: Update changelog for version 1.4.4 with enhanced CDM support, configuration options, and various improvements
- cdm: Enhance key retrieval logic and improve cached keys handling
- Implement intelligent caching system for CDM license requests
- tags: Enhance tag handling for TV shows and movies from Simkl data
- kv: Enhance vault loading and key copying logic
- dl: Truncate PSSH string for display in non-debug mode
- cdm: Add fallback to Widevine common cert for L1 devices
- cdm: Optimize get_cached_keys_if_exists for L1/L2 devices
- cdm: Update User-Agent to use dynamic version
Bug Fixes
- tags: Fix import order.
- cdm: Add error message for missing service certificate in CDM session
- tags: Fix formatting issues
Maintenance
- Bump version to 1.4.5 and update changelog
1.4.4 - 2025-09-02
Features
- ip-info: Add cached IP info retrieval with fallback tester to avoid rate limiting
- ip-info: Fix few more issues with the get_ip_info make sure we failover to different provider on 429 errors and allow future for more API providers to be added later.
- release: Bump version to 1.4.3 and update changelog with new features and improvements
- config: Add new configuration options for device certificate status list and language preferences
- cdm: Enhance DecryptLabsRemoteCDM to support cached keys and improve license handling
- cdm: Enhance DecryptLabsRemoteCDM with improved session management and caching support and better support for remote WV/PR
- cdm: Add DecryptLabs CDM configurations for Chrome and PlayReady devices with updated User-Agent and service certificate
- cdm: Refactor DecryptLabsRemoteCDM full support for Widevine/Playready and ChromeCDM
Bug Fixes
- dependencies: Remove unnecessary data extra requirement from langcodes
- main: As requested old devine version removed from banner to avoid any confusion the developer of this software. Original GNU is still applys.
- tags: Fix Matroska tag compliance with official specification
Changes
- drm: Simplify decrypt method by removing unused parameter and streamline logic
1.4.2 - 2025-08-14
Features
- dl: Add audio language option to override language for audio tracks
- vault: Add no_push option to Vault and its subclasses to control key reception
- hls: Enhance segment merging with recursive file search and fallback to binary concatenation
- hls: Enhance segment retrieval by allowing all file types and clean up empty segment directories. Fixes issues with VTT files from HLS not being found correctly due to new HLS "changes"
- config: Add series_year option to control year inclusion in titles and YAML configuration
- tags: Implement session management for API requests with retry logic
- release: Bump version to 1.4.2 and update changelog with new features and fixes
Bug Fixes
- dl: Adjust per_language logic to ensure correct audio track selection and not download all tracks for selected language.
1.4.1 - 2025-08-08
Features
- Implement title caching system to reduce API calls
- dl: Update language option default to 'orig' if no -l is set, avoids hardcoded en
- config: Add options for tagging with group name and IMDB/TMDB details and new API endpoint of simkl if no tmdb api key is added.
- tags: Enhance tag_file function to prioritize provided TMDB ID if --tmdb is used
- changelog: Update changelog with enhanced tagging configuration and improvements
Bug Fixes
- subtitle: Handle ValueError in subtitle filtering for multiple colons in time references fixes issues with subtitles that contain multiple colons
Changes
- Remove Dockerfile and .dockerignore from the repository
- tags: Simplify Simkl search logic and soft-fail when no results found
1.4.0 - 2025-08-05
Features
- update_checker: Enhance update checking logic and cache handling
- dl: Add option to include forced subtitle tracks
- subtitle: Add filtering for unwanted cues in WebVTT subtitles
- tracks: Add support for HLG color transfer characteristics in video arguments
- dl: Enhance language selection for video and audio tracks, including original language support
- dl: Improve DRM track decryption handling
- series: Enhance tree representation with season breakdown
- hybrid: Enhance extraction and conversion processes with dymanic spinning bars to follow the rest of the codebase.
- dl: Fix track selection to support combining -V, -A, -S flags
- titles: Better detection of DV across all codecs in Episode and Movie classes dvhe.05.06 was not being detected correctly.
- dl: Add support for services that do not support subtitle downloads
- playready: Enhance KID extraction from PSSH with base64 support and XML parsing
- Bump version to 1.4.0 and update changelog with new features and fixes
Maintenance
- Update changelog with new features, enhancements, and fixes for version 1.3.0
- Bump unshackle version to 1.3.0 in uv.lock
1.3.0 - 2025-08-03
Features
- Add update check interval configuration and implement rate limiting for update checks
- Implement terminal cleanup on exit and signal handling in ComfyConsole
- Add Unspecified_Image option to Transfer enum in Video class.
- Enhance credential management and CDM configuration in unshackle.yaml
- Update path of update_check.json to .gitignore
- Add scene naming option to configuration and update naming logic in titles
- Add unshackle-example.yaml to replace the unshackle.yaml file, you can now make changes to the unshackle.yaml file and pull from the the repo without issues.
- drm: Add support for mp4decrypt as a decryption method
Bug Fixes
- Correct URL handling and improve key retrieval logic in HTTP vault
- Rename 'servers' to 'server_map' for proxy configuration in unshackle.yaml to resolve nord/surfshark incorrect named config
Changes
- Replace log.exit calls with ValueError exceptions for error handling in Hybrid class
Maintenance
- Bump version to 1.3.0 and update changelog with mp4decrypt support and enhancements
1.2.0 - 2025-07-30
Features
- dl: Enhance hybrid processing to handle HDR10 and DV tracks separately by resolution, Hotfix for -q 2160,1080 both tracks will have Hybrid correctly now.
- hybrid: Display resolution of HDR10 track in hybrid mode console output and clean up unused code
- subtitle: Add information into unshackle.yaml on how to use new Subby subtitle conversion.
- vaults: Enhance vault loading with success status
- attachment: Ensure temporary directory is created for downloads
- tracks: Add duration fix handling for video and hybrid tracks
- hybrid: Add HDR10+ support for conversion to Dolby Vision and enhance metadata extraction
- Update version to 1.1.1 and add update checking functionality
- Bump version to 1.2.0 and update changelog, I'll eventually learn symantic versioning.
Changes
- env: Enhance dependency check with detailed categorization and status summary
Maintenance
- workflow: Remove Docker build and publish workflow, its too messy at the moment doing manual builds for now.
1.1.0 - 2025-07-30
Features
- Update version display in main.py
- proxies: Add SurfsharkVPN support
- binaries: Add support for
MKVToolNixandmkvpropedit - subtitles: Integrate
subbylibrary for enhanced subtitle processing and conversion methods - hybrid: Implement HDR10+DV hybrid processing and injection support
- EXAMPLE: Add support for HDR10 and DV tracks in hybrid mode
Bug Fixes
- cfg: Update services directory handling
- binaries: Improve local binary search functionality
- env: Update binary search functionality to use
binaries.find - env: Update
Shaka-Packagerbinary retrieval method - env: Improve handling of directory paths in
infocommand - install: Improve UV installation process and error handling
- download: Skip Content-Length validation for compressed responses in curl_impersonate and requests. The fix ensures that when Content-Encoding indicates compression, we skip the validation by setting content_length = 0, allowing the downloads to complete successfully.
- dl: Check for dovi_tool availability in hybrid mode
- download: Skip Content-Length validation for compressed responses in curl_impersonate and requests
Maintenance
- Bump version to 1.1.0 in pyproject.toml, __init__.py, and uv.lock to follow correct Semantic Versioning.
- Add CHANGELOG.md to document notable changes and version history
[1.0.1] - 2025-07-20
Features
- Enhance CONFIG.md with new configuration options for curl_impersonate, filenames, n_m3u8dl_re, and nordvpn
- Update .gitignore and enhance README with planned features
- Add .github/ to .gitignore to exclude GitHub-related files
- Implement VideoCodecChoice for enhanced codec selection
- Add Dockerfile and GitHub Actions workflow for building and publishing Docker image
- Update GitHub Actions workflow for Docker image build and add Docker installation instructions to README
Bug Fixes
- Change default value of set_terminal_bg to False
- Add video_only condition to subtitle track selection logic fixes issues where ccextractor would run even with -V enabled
- Add SubtitleCodecChoice for resolving issues with config clicktype selection, using names like VTT or SRT was not working as expected
- Update shaka packager version and enhance Docker run command with additional volume mounts
Changes
- Streamline README by removing outdated service and legal information and moved it directly to the WIKI
- Reorganize Planned Features section in README for clarity
- Improve track selection logic in dl.py