Drop null keys from every licence, server and export source, not only Widevine. dl now finds remote sessions and imports through ServerKeySource instead of private fields.
The export writes mediaexport content_periods per manifest; an import that re-fetches the MPD (no saved snapshot) drops the periods a service filtered.
A manifest snapshot module now saves and restores DASH/ISM parser state for --remote and export/import, so an import keeps the service's period filter without fetching the manifest.
cast_dl_params feeds ctx.params to dl() and dl.result() as on the CLI. A string lang value now returns 400 instead of splitting into letters, and -r accepts HDR10+.
Some packagers renumber AdaptationSet and Representation ids in every Period, so audio took video segments after the first Period. A match never crosses codec, size or language.
Use the service_name local in handle_single_server_cdm, assign service_data once in /api/services, and keep the TERMINAL_STATUSES comment on its constant.
Swagger now owns route registration instead of adding a second dead copy of every route; add json_body, enqueue_job, serialize_tracks and client_credential, build the serve middleware list once, and scan the users once per request.
Run session-tracks serialization, request cache IO, session cache dir removal (now outside the store lock), history reads and gzip over 1 MiB on worker threads; cache the per-key PBKDF2 namespace and key_id.
Session update events carry the new action as action_entry instead of the full log; access lines stay out of the log ring unless --debug. Job events build and redact their dict once, the progress interval matches the 0.5 s poll, and dashboard stats are serialized once.
Cache proxy provider catalogues (10 min), reuse vaults and CDMs across one batch licence call, and cache the health update check, /api/services entries and parsed service config.yaml.
The tool writes to a temporary file through run_step, which gains a timeout that hides the command line. A missing tool now raises instead of skipping.
A licence that builds a new key dict left decrypt_verified on the old one, so a falsely flagged key stayed flagged and a replacement key went unchecked. Both relicence passes now share one step that clears the flag.
A bad value now gets 400 INVALID_PARAMETERS at submit and the worker casts each option; a flat dl key such as quality or lang no longer fills a service option of the same name.
RnetCookieAdapter stores cookies by domain, path and name and sends path, secure and a leading-dot domain to rnet. It also takes server-rotated values, and worker children and track sessions get the cookies with their paths.
standard_resolution() replaces the aspect-ratio logic in naming and is shared by -q matching, export names and progress/hybrid labels, so 1920x1088, 1916x1076, portrait and DCI sizes get standard names.
Tracks with different KID sets still query the vaults at the same time, but wait for one licence lock and check the key cache again before they licence.
Smooth Streaming TTML times cues from each fragment's start; a whole track stacked into the first fragment. Also stop rebase_ttml failing on a track with no cues.
DASH reads the AudioChannelConfiguration scheme (Dolby mask, CICP index incl. immersive layouts, channel count); HLS and ISM counts map 6/7/8 to 5.1/6.1/7.1.
Fix the bugs the type errors exposed (RnetSession.send body, HLS proxy session, title cache fallback, mux progress) and gate mypy in pre-commit, warn-only in CI.
A service option named like a dl option (e.g. --profile) is no longer dropped or mixed with the dl value; the server casts nested values and keeps cli defaults nested.
server_cdm: true on a remote_services entry now licenses remote runs with the server CDM even when the service has its own cdm entry, which stays the local-run device and the fallback. A services.<TAG>.server_cdm replaces the server value for one service, per-service entries match the tag in any case, and the configured fallback logs at info.
BREAKING CHANGE: with server_cdm: true, a per-service cdm entry no longer makes your own device license remote sessions; use dl --cdm or services.<TAG>.server_cdm: false.