Commit Graph
375 Commits
Author SHA1 Message Date
imSp4rky ecf17baffe feat(tracks): add native track names with muxing.track_names
Set muxing.track_names to native to name an unnamed track in its own language (中文(繁體), Português (Portugal)) in place of English. The same script and region rules apply. --list, the muxed names and the REST API track_name follow the option. A test fixture resets the muxing options, so a local unshackle.yaml cannot change test results.
2026-10-24 12:43:50 -06:00
imSp4rky 1175035317 feat(tracks): name unnamed tracks by language and tag subtitle scripts
Unnamed tracks get the English language name (default region left out); subtitle tags gain the script their region implies (zh-TW -> zh-Hant-TW). Refs #169
2026-10-24 10:59:21 -06:00
imSp4rky 83514d12fe fix(core): cut user-facing errors and warnings to one line 2026-10-23 20:23:05 -06:00
imSp4rky dfc99783b5 fix(downloader): report spent segment retries in one line without the URL
The session message names the host, not the signed URL, and a segment that fails every attempt prints one line with no traceback. API job errors come from the exception.
2026-10-23 19:47:12 -06:00
imSp4rky d8663b0dad fix(tracks): flag every encrypted sample entry type after decrypt 2026-10-23 17:14:12 -06:00
imSp4rky 9f054269db fix(vaults): copy no vault key from a clear track
kid_windows returns an empty map for an MP4 with no encrypted sample entry or protecting senc, so the key check judges, flags and copies nothing for it.
2026-10-23 16:59:40 -06:00
imSp4rky 3345422790 fix(drm): load a bare PlayReady WRMHEADER from DASH, HLS and ISM manifests
PlayReady.from_pssh_b64 wraps a bare UTF-16LE WRMHEADER in a PlayReady Object and keeps that as pssh_b64. DASH and ISM log and skip a PlayReady entry they cannot parse.
2026-10-23 15:55:01 -06:00
imSp4rky cc4bf19706 fix(vaults): stop false bad-key flags from a failed decode check
Judge a vault KID only on a file whose KID map holds it, tell remote vaults of a bad pair only once another key replaces it, and let the server CDM unflag a pair it returns; the server never flags a CDM-licensed pair. Log FFmpeg stderr on a failed check and name the missing CDM when none is set.
2026-10-23 15:31:26 -06:00
imSp4rky eeaf16cd83 fix(remote): keep each session cookie's domain, path and secure flag
The client set server cookies with no domain and sent all of them to every host, so a CDN refused segment requests with 400 header too large. rnet sessions now send cookies too.
2026-10-23 09:42:01 -06:00
imSp4rky af69e8aad4 feat(proxy): try bare --proxy providers in proxy_providers key order
Basic stays first and Control D last; the rest follow their config key order. Geofence and proxy_map lookups go through pick_proxy and skip a provider that fails.
2026-10-23 08:20:39 -06:00
imSp4rky 71f293161e fix(cfg): show only the duplicate-key warning, once 2026-10-22 20:43:40 -06:00
imSp4rky 3e9c26bd46 refactor(config): log the duplicate-key warning without the python warning prefix 2026-10-22 20:16:35 -06:00
imSp4rky 9dd97bcd25 feat(config): warn with the lines of a duplicate key in any config load 2026-10-22 20:12:59 -06:00
imSp4rky f83a594c91 fix(cfg): give the lines of each duplicate config key instead of crashing 2026-10-22 19:45:46 -06:00
imSp4rky 1ec236f61b feat(proxy): accept an @ selector as a server_map value
A value starting with - or @ applies to its region (fr: -datacamp); a value with @ after a server is a whole query (fr: fr-bod@195.86.24.103). A selector in --proxy still wins.
2026-10-22 14:03:25 -06:00
imSp4rky 4753fcd7bc feat(proxy): select a vpn server by network or ip with @
On NordVPN, Windscribe and Surfshark, `@<name>` keeps and `@-<name>` skips a hosting network; `@<ip>` and `@-<ip>` pick or skip one server. The connect line names the server, IP and network. Surfshark pins an IP through a loopback TLS port.
2026-10-22 13:53:30 -06:00
imSp4rky 0eaefcaa2b fix(proxy): name the reason when the Control D forwarder answers 502 2026-10-21 18:35:26 -06:00
imSp4rky a7e68b7d20 fix(tracks): keep a locked segment file from hiding the download error
On Windows a worker can still hold a .!dev file open when a track fails; cleanup now ignores that OSError and still stashes the segments.
2026-10-21 18:25:50 -06:00
imSp4rky 5086dafff3 feat(api)!: add a server drain and never answer with a 5xx
POST/DELETE /api/dashboard/drain refuses new sessions and jobs (SERVER_DRAINING, 409) and warns open sessions. A CDN can replace a 5xx body, so server errors are now 422, retryable ones and the tunnel check 424, and a new middleware turns any 5xx into 422.

BREAKING CHANGE: INTERNAL_ERROR, DOWNLOAD_ERROR, WORKER_ERROR and the fallback return 422 instead of 500; NETWORK_ERROR and SERVICE_UNAVAILABLE return 424 instead of 503; /api/tunnel/check failures return 424 instead of 502.
2026-10-21 17:15:33 -06:00
imSp4rky 23614fd938 feat(remote): add --local-proxy to send server requests through the client
A reverse tunnel over the remote connection: the server's service traffic leaves through the client's own network. Only the client dials. Adds the tunnel-test command.
2026-10-21 17:09:37 -06:00
imSp4rky afaff8e070 feat(api): tag each error with a ref and count errors by service
Every structured error carries a short ref, appended to its message and logged with the request; /api/dashboard/status gains per-service error counts. Gzip now compresses in place.
2026-10-21 14:39:37 -06:00
imSp4rky 39ec591c48 fix(api)!: send service and DRM errors as 422, not 502
Cloudflare replaces an origin 502 body with its own page, so clients got "502: Bad gateway" in place of the error and resent each failed licence.

BREAKING CHANGE: SERVICE_ERROR and DRM_ERROR now return HTTP 422 instead of 502.
2026-10-21 11:43:33 -06:00
imSp4rky e5c339934c fix(remote): send the typed --proxy to the server when it resolved to loopback
dl and search keep the typed --proxy value, so --proxy controld:ca --remote sends the server the Control D resolver, not this machine's forwarder. The Control D log names the location and masks the resolver ID in place of 127.0.0.1.
2026-10-21 11:03:10 -06:00
imSp4rky f5bd24b5e9 fix(import): take a missing title language from the exported tracks
A title with no language now takes the language of an original-language track, else a
video track, so an unlabelled MPD re-parses and -l orig works. A track that no longer
matches its manifest is dropped with a warning instead of failing at download.
2026-10-21 10:36:03 -06:00
imSp4rky 1b20b2bbf9 test(api): give the deep-nesting cache payload case a short id 2026-10-20 20:31:20 -06:00
imSp4rky 012bf45270 fix(hls): keep PlayReady session-data keys by matching the URN string 2026-10-20 20:05:03 -06:00
imSp4rky 96d6a4f1b2 fix(api): split global speed limit across job workers 2026-10-20 20:03:03 -06:00
imSp4rky 3ffc7a9735 fix(api): validate quality and bitrate params like dl and pass cdm_only to services
Reject bad quality, bitrate/range conflicts and malformed ranges with a 400, convert quality in the worker, and pass cdm_only into ctx.params.
2026-10-20 19:59:38 -06:00
imSp4rky 639d51c41b feat(api): apply services.<TAG>.dl as defaults for API download jobs 2026-10-20 19:57:03 -06:00
imSp4rky f2273b8e97 feat(dl): keep failed track segments across runs in a resume stash
Stash a failed or cancelled track's segments outside the task temp dir and restore them on the next download. Also drop a pre-sized data file with its .!dev control file.
2026-10-20 19:53:42 -06:00
imSp4rky 5b9120a7f1 fix(api): refuse peer cache files that name types other than datetime
The server and the client both check a forwarded cache file before they write it, because Cacher decodes it with jsonpickle. The session-create cache write now runs off the event loop.
2026-10-20 19:48:13 -06:00
imSp4rky 08a2257be3 fix(api): parse client cookies with the dl cookie parser 2026-10-20 12:46:44 -06:00
imSp4rky ef75ea7d7a feat(dl): add --local to override a remote: true service config 2026-10-19 14:25:03 -06:00
imSp4rky 3aaf9c4107 fix(services): route a service remote from services.<TAG>.dl.remote
Click picks the subcommand before the dl callback applies the service config, so Services.resolve_command now applies remote and server first. A REST API job routes from its request only.
2026-10-19 14:19:07 -06:00
imSp4rky 1a8e633fdc feat(dash): flag dv profile 8 tracks from supplementalCodecs and use hdr10+dv as the hybrid 2026-10-18 17:18:11 -06:00
imSp4rky 2cc5e44957 feat(search): add --remote to search through a remote server
The client sends its credentials, cookies and cache, but none for an anonymous-search service. The API relay uses the same path.
2026-10-18 13:23:04 -06:00
imSp4rky 2dd2046d65 fix(tracks): match probed hdr10p tracks on remote and hint dv+hdr10p on -r HDR10P
match_track treats HDR10 and HDR10P as equal in its attribute fallback. -r HDR10P warns that a DV track carries HDR10+ when one does.
2026-10-18 12:24:10 -06:00
imSp4rky 6fdfeb9cae test: replace real service tags and brands with generic placeholders 2026-10-18 12:17:08 -06:00
imSp4rky 768e35d905 feat(hybrid): use a dv track that carries hdr10+ as the hybrid of its resolution 2026-10-18 12:11:02 -06:00
imSp4rky d7c6907329 feat(tracks): probe dv tracks for hdr10+ and list them as DV+HDR10P
A DV track that carries HDR10+ keeps its DV range and gets Video.hdr10plus, sent in the REST track JSON and to remote clients.
2026-10-18 11:43:44 -06:00
imSp4rky 811e0a19c0 feat(tracks): probe HDR10 tracks for HDR10+ SEI before selection
Relabel HEVC HDR10 tracks whose first fragment carries ST 2094-40 SEI as HDR10P, for dl, the REST API and remote sessions. Config key hdr10plus_probe (default true).
2026-10-17 18:58:48 -06:00
imSp4rky 338adc5ff0 fix(remote): retry once on a proxy 502/503/504 page and keep server errors from ending a relicense 2026-10-17 18:13:25 -06:00
imSp4rky 35871f3a52 feat(hybrid): generate dolby vision from hdr10+ with --generate-dv
Builds per-scene L1 in unshackle (PQ mean, letterbox-aware) with a generate_dv_mode config (v29/v40/legacy); a failed hybrid no longer exits 0 with no video.
2026-10-17 16:40:14 -06:00
imSp4rky 14bd2f2c7e feat(api): relay services from remote servers with pooled sessions and login prompts 2026-10-16 19:03:56 -06:00
imSp4rky 9f4625d971 fix(proxy): do not warn about requests to a configured remote CDM 2026-10-16 17:58:38 -06:00
imSp4rky bfda31ce4a fix(proxy): keep service traffic on --proxy and warn about requests that bypass it
--proxy now overrides HTTP(S)_PROXY and the Windows system proxy while keeping the env CA bundle. Core fallback sessions use the run's proxy, and a warn-only audit hook names service code that sends a request or opens a raw socket outside the proxy; a session with proxy_exempt = True opts out.
2026-10-16 16:12:42 -06:00
imSp4rky dc169f81e1 fix(vaults): stop querying sibling KIDs and skip unavailable vaults
The server CDM stub names only the manifest's KIDs; sibling keys stay content keys. API and HTTP vaults retry a 429, and a vault that is down or still rate limited costs one timeout per run.
2026-10-16 14:49:37 -06:00
imSp4rky ecb8296de8 fix(import): add decrypts_samples to ImportService 2026-10-16 09:12:02 -06:00
imSp4rky 71a0383258 fix(console): count spacing combining marks as one cell
Rich measures Indic marks like ि as zero width, so the --list panel border drifted on Hindi, Telugu and Tamil labels.
2026-10-15 17:36:04 -06:00
imSp4rky 614a8c5ae4 fix(subtitles): sort cues by start time when converting from SSA/ASS
Convert a time-sorted copy of the SSA/ASS source, so that SubtitleEdit and pysubs2 write SRT cues in order. SSA/ASS targets keep the file order.
2026-10-15 16:39:19 -06:00