Commit Graph
411 Commits
Author SHA1 Message Date
imSp4rky 7898ff6dd6 refactor(types): bring mypy to zero errors across unshackle
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.
2026-10-30 20:51:21 -06:00
imSp4rky b493c9cd52 fix(naming): tag HDR10+ from the track range when MediaInfo misses it 2026-10-30 17:28:50 -06:00
imSp4rky b0f96cdee9 fix(tracks): keep HDR colour metadata when muxing VP9
mkvmerge drops the MP4 vpcC/SmDm/CoLL boxes of VP9, so pass the colour codes and mastering display data from an ffprobe of the source.
2026-10-30 17:13:14 -06:00
imSp4rky e6a627118f feat(tracks): add a display-only note shown in --list and over --remote 2026-10-30 16:17:36 -06:00
imSp4rky 5206b3cab6 refactor(remote)!: send service options only in service_params
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.
2026-10-30 16:16:56 -06:00
imSp4rky 47f88b1b65 fix(subtitles): accept TTML2 rw/rh and vw/vh sizes in fTTML conversion
pycaption rejects these units on extent/origin/padding, which failed every STPP track that uses them; rewrite them to % before parsing.
2026-10-30 13:59:15 -06:00
imSp4rky 17d4905577 fix(titles): compare dub languages under their macrolanguage
A cmn track on a zh title no longer gets DUBBED, and nb and nn count as no; yue stays separate.
2026-10-29 21:23:45 -06:00
imSp4rky d4abcb51d9 feat(naming): add audio_contain_all language tag condition
An empty audio_contain_all or subs_contain_all list now never matches; before this, an empty subs_contain_all list matched every release.
2026-10-29 14:41:06 -06:00
imSp4rky bd64f3a8c4 fix(api): stop a service's sys.exit from killing the serve process
Catch SystemExit at service import, in the heartbeat task, the 5xx middleware, search, samples and chapters, and answer it as SERVICE_ERROR.
2026-10-29 11:23:53 -06:00
imSp4rky 7b927934e0 feat(remote)!: let server_cdm outrank a service's cdm entry and set it per service
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.
2026-10-29 10:18:15 -06:00
imSp4rky d12a943d96 fix(api): show filename codec and range labels in codec_display and range_display 2026-10-28 15:34:52 -06:00
imSp4rky b0c006d7f6 feat(naming): add codec_names to rename codec and HDR labels in filenames
A codec name that ends in a digit now gets a separator before the channels, so AC-4 2.0 gives AC-4.2.0 and no longer AC-42.0.
2026-10-28 14:19:23 -06:00
imSp4rky 2e75cc35a1 feat(kv): accept an sqlite vault file path and read plain-tag tables on copy
A kv vault argument can be the path to an SQLite vault file. With -s, kv copy reads the VAULT_TAG table and the plain-tag table into the VAULT_TAG table.
2026-10-27 13:58:14 -06:00
imSp4rky 9f86464826 fix(api): cache the health update check and fix a remote-session test fixture 2026-10-27 13:38:57 -06:00
imSp4rky 756c2ce2b5 feat(remote): reopen a lost remote session and resume at the current title 2026-10-27 13:24:31 -06:00
imSp4rky 9017ab95b7 feat(tracks): add Video.hdr10_base and forward s_lang over remote and REST
A DV track with an HDR10 base (profile 8.1) lists as DV+HDR10; dl_params now carry s_lang.
2026-10-27 13:06:48 -06:00
imSp4rky 0440f2ba54 fix(manifests): keep service drm, rebase carried vtt cues, ship single-track mpds
DASH no longer drops service-set DRM when the manifest has none, and the WebVTT rebase allows a cue that starts one segment early. --remote also sends single-track manifests matched by track id.
2026-10-27 11:38:47 -06:00
imSp4rky 84fd0a4bee feat(tracks): add Tracks.dedupe and match variant tracks by signature
get_tracks_for_variants skips a later manifest's track when a held track has the same signature, so a track whose ID changes per manifest is listed once.
2026-10-27 10:44:12 -06:00
imSp4rky 8454f40929 fix(tunnel): block local networks instead of allowing public ones for --local-proxy
A VPN's synthetic DNS answer (fake-IP 198.18.0.0/15, 192.0.0.69) now works for a host name. An IP from the server, in any numeric form, must be public; dials to the client itself are closed.
2026-10-27 10:07:23 -06:00
imSp4rky 06f87dafa3 feat(drm): add blowfish stripe cipher and mp3 audio codec
BlowfishStripe decrypts on the client after download, so a --remote client gets clear audio.
2026-10-26 18:59:42 -06:00
imSp4rky ffeb58f808 feat(manifests): add dts-hd, mpeg-h and lcevc codecs and a manifest corpus
Fix DASH SegmentTimeline negative @r and Pattern, TTML sidecar sets with no contentType, HLS CHANNELS identifiers and Dolby channel masks; test against 408 public DASH/HLS/ISM manifests.
2026-10-26 10:30:43 -06:00
imSp4rky af2ec8112c fix(dash): end segmentbase media range at the last byte of the file
The range ran one byte past the end, so a collapsed SegmentBase download gained a trailing zero byte. An unknown "*" total now sends an open-ended range.
2026-10-25 15:07:55 -06:00
imSp4rky 8151946ec0 fix(mp4): serialize pymp4 parses of bit-field boxes across threads 2026-10-25 13:43:39 -06:00
imSp4rky 0c58575a5b perf(dash): collapse single-file tracks that have a sidx gap 2026-10-25 13:23:53 -06:00
imSp4rky 43fcb030f8 fix(tracks): read sidx boxes with struct so concurrent tracks parse correctly 2026-10-25 13:22:08 -06:00
imSp4rky 2dc458f8b4 fix(subtitle): rebase live-clock dash webvtt cues by presentationTimeOffset
Live-to-VOD replays carry cue times on the live media clock, which overflowed the SRT conversion and dropped every cue.
2026-10-25 13:15:34 -06:00
imSp4rky cb2ffdb55a fix(tunnel): accept fake-ip dns answers for --local-proxy host names
A TUN-mode VPN with fake-IP DNS answers names from 198.18.0.0/15 or 2001:2::/48, which the LAN guard refused, so every dial failed. Refused hosts now warn once.
2026-10-25 12:22:28 -06:00
imSp4rky cc33600cc7 feat(tracks): add muxing.original_label to mark original-language tracks
Adds the label to audio, subtitle and embedded audio names unless the name already says it, and escapes track lines in the --list tree.
2026-10-24 22:51:35 -06:00
imSp4rky 80bda08f36 feat(tracks): add muxing.track_names none to leave unnamed tracks unnamed
A track the service gives no name keeps none (--list shows [VTT] | en); SDH, CC, Forced and Descriptive labels still apply.
2026-10-24 21:24:31 -06:00
imSp4rky d0f9307506 perf(proxy): test the remote CDM hosts only after the walk finds service code 2026-10-24 17:57:48 -06:00
imSp4rky fdb5369534 fix(proxy): match a reloaded service class by name and dedup warnings per run
A hot service reload made instance_of miss the new class, so a run with no proxy got a false bypass warning.
2026-10-24 17:29:02 -06:00
imSp4rky 34e8e37fdc fix(services): clear service-repo bytecode with git pathspecs before a pull
Delete untracked __pycache__ before each pull and drop the global dont_write_bytecode, so service bytecode is cached again
2026-10-24 15:57:08 -06:00
imSp4rky 866420ed67 fix(dash): treat a caption subtitle also marked SDH as SDH 2026-10-24 13:43:52 -06:00
imSp4rky 0de069f35a fix(console): count a virama conjunct as one cell
A Hindi conjunct such as न्द in हिन्दी drew the --list border one cell short.
2026-10-24 12:46:53 -06:00
imSp4rky bcef9ff87a fix(sample): stop a malformed sidx from hanging the download
pymp4 loops forever on a sidx that counts more references than it holds. Manifest errors in download threads now raise instead of sys.exit.
2026-10-24 12:46:19 -06:00
imSp4rky 1036528fa3 fix(mux): address embedded audio by the file's real mkvmerge track IDs
A TS file can hold its audio first, which put the audio name on the video.
2026-10-24 12:45:25 -06:00
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