Commit Graph
732 Commits
Author SHA1 Message Date
CodeName393 41106b0d24 fix(core): strip trailing spaces and dots in template formatting to prevent WinError 3
- Clean up redundant spaces and separators when conditional tags (e.g. {year?}) are omitted.
- Strip leading and trailing spaces and dots in sanitize_filename and TemplateFormatter.
- Prevent FileNotFoundError [WinError 3] caused by trailing spaces in Windows directory paths.
2026-07-26 18:16:36 +09:00
imSp4rky d60d8abf53 fix(ism): repair synthesized init and verify fragments decrypted
UNITY_MATRIX emitted 11 int32s instead of 9, oversizing mvhd/tkhd so pymp4 desynced and fTTML subtitles yielded no cues. Also rewrites PIFF senc to CENC so shaka can decrypt Smooth, labels HEV1 as hev1, and raises when a fragment survives decryption still carrying a sample-encryption box.
2026-07-25 15:55:31 -06:00
imSp4rky b7029c343e fix(ism): emit two stsd entries so sample_description_index 2 resolves
Smooth fragments set tfhd sample_description_index=2 against a server init carrying a second, identical sample entry. A lone entry left that dangling: mp4decrypt skipped every such fragment silently and demuxers stopped after the first, yielding a file that looked fine but was almost entirely encrypted.
2026-07-25 12:59:55 -06:00
imSp4rky 8cf1700684 fix(import): stop losing side-loaded subtitles and blaming the manifest URL
Only fall back to Title.language when the manifest labels nothing, and reject und as firmly as a missing tag. Exported direct-URL subtitles now replace the re-parsed set, and fetch failures stay distinct from parse failures.
2026-07-25 11:32:17 -06:00
imSp4rky 7c767bfd31 perf(pipeline): fix pool starvation, unlock vault writes, prep mux
Stop remounting adapters on shared sessions (restores dropped 429/5xx retries, ends 16-conn pool starvation, pool sized to 64); defer DRM vault write-backs off the global lock; add mux output_path groundwork for future parallelism.
2026-07-23 19:46:24 -06:00
imSp4rky ae9ffc7731 feat(drm): auto-repack tracks with a residual encrypted sample entry
Detect an encv/enca sample entry surviving decryption (moov-scoped 4CC scan) and force a repack so mkvmerge isn't first-FourCC-locked to a generic encrypted codec; warn if one persists after repacking.

Closes #142
2026-07-23 09:33:14 -06:00
imSp4rky c2f7fd87a3 feat(drm): detect revoked PlayReady devices from license responses
Add is_revocation()/REVOCATION_CODES and centrally raise DeviceRevoked when a license fault carries a device/cert revocation HRESULT, so any service surfaces it without its own decoding.
2026-07-23 08:48:51 -06:00
imSp4rky 51750a03b0 feat(drm): add PlayReady HRESULT decoder
Maps DRM_E_/DRM_S_ result codes to symbol + description so services can turn raw license HRESULTs (e.g. 0x8004C065) into readable errors.
2026-07-22 09:18:14 -06:00
imSp4rky 95a754fa6c fix: harden ClearKey/CENC decryption correctness 2026-07-19 10:49:45 -06:00
imSp4rky 446367f58d fix: skip decrypt on mislabeled-clear segments 2026-07-19 10:21:47 -06:00
imSp4rky 2c8a98f337 feat: original-language aware DUAL/MULTi tagging and new DUBBED variable
DUAL now requires the original language plus one dub (strict default);
dual_multi_mode: count restores the old pure-count behavior.
2026-07-18 11:02:02 -06:00
imSp4rky 094c598ef5 perf: little improvements here and there 2026-07-16 11:02:34 -06:00
imSp4rky 686d996346 ci: give the build job its own uv cache key
stops the 'unable to reserve cache' annotation when lint and build
race to save the same key
2026-07-15 15:00:49 -06:00
imSp4rky 46cf72062d ci: pin setup-uv and dependency-review to full versions
neither publishes a moving major tag anymore, so v8/v5 don't resolve
2026-07-15 14:56:37 -06:00
imSp4rky 0a6f1cbe07 ci: bump actions to node 24 versions and serialize docs deploys
checkout v7, setup-uv v8, setup-python v6, dependency-review v5; a
concurrency group queues docs deploys so parallel runs can't race the push.
2026-07-15 14:54:05 -06:00
imSp4rky e31e60a418 style: run ruff format over the codebase 2026-07-15 14:49:27 -06:00
imSp4rky d853ef9600 ci: add multi-os test, lint, and wheel build workflows
Also fixes the sdist leaving wheels empty, pins subby to its git
source in wheel metadata, and fixes docstrings that broke mkdocs --strict.
2026-07-15 14:49:19 -06:00
imSp4rky 59a7c76b2f feat(ism): harden Smooth parsing and derive fps/codec from spec fields
Regex-based UrlPattern substitution (handles {Bitrate}/{start_time} spellings), AudioTag/FourCC codec fallback, Width/Height fallbacks, integer fragment times, live-manifest and missing-language guards. Extract fps from the HEVC SPS VUI (HEVC-only; AVC timing untrusted).
2026-07-14 21:24:14 -06:00
imSp4rky 2ccae1a0ee feat(cdm): stamp remote CDM DRM type at load for reliable detection 2026-07-14 17:32:00 -06:00
imSp4rky c6ecdb605c fix(services): register modules in sys.modules so repo-cloned services can self-import and remove old benchmark that should have been deleted 2026-07-14 13:46:29 -06:00
imSp4rky b8ec9e2498 fix(tracks): keep regional language variants distinct in exact selection
by_language now applies RFC 4647 Lookup in exact mode, preferring the string-equal tag so --exact-lang separates base/regional pairs (ar/ar-EG, en/en-US) instead of collapsing them, and dedupes by id to prevent the duplicate-track-id crash. Adds a language-selection regression test.
2026-07-14 09:17:22 -06:00
imSp4rky 1cf9e5b487 docs: correct DRM, muxing, and proxy references (+ case-insensitive proxy prefix fix) 2026-07-13 09:09:46 -06:00
imSp4rky 2e14e30f2f build(mypy): enable explicit_package_bases 2026-07-12 20:26:05 -06:00
imSp4rky b32b301dcc fix(proxies): show ExpressVPN country/location counts at startup 2026-07-12 20:25:56 -06:00
imSp4rky a450184ab8 test(remote): isolate job history writes from the real api_history.jsonl 2026-07-12 10:30:30 -06:00
imSp4rky bd679d2571 docs(changelog): regenerate with git-cliff 2026-07-12 09:52:35 -06:00
imSp4rky d7a2bb6b8e fix(subs): stop segmented WebVTT merge from stripping formatting
Merge cues at the string level instead of round-tripping through
pycaption, which dropped inline tags and cue settings. STYLE and
REGION blocks are kept, duplicate boundary cues splice correctly,
and a bad timing line now skips the cue instead of crashing.

Also rank pysubs2 above SubtitleEdit for ASS to TTML/VTT since
SubtitleEdit flattens inline styling there. Documented the measured
backend fidelity table and added regression tests for the merge.
2026-07-12 09:39:39 -06:00
imSp4rky 6ef24661c8 style(dl): restore isort imports and drop dead pass 2026-07-12 08:55:01 -06:00
sp4rk.y 3326e9b72c Merge pull request #140 from CodeName393/prevent-missing-tracks-error-when-excluding-track-types
fix(dl): prevent missing tracks error when excluding track types
2026-07-12 08:50:28 -06:00
imSp4rky 6b168c774e fix(gitignore): add memory directory to .gitignore 2026-07-12 07:35:40 -06:00
imSp4rky 8769f678b1 fix(tags): point IMDbApi provider at api.tiffara.com (IMDxAPI)
Upstream migrated the free IMDxAPI from imdbapi.dev to api.tiffara.com.
Endpoints and JSON schema are unchanged, so only BASE_URL and the
user-facing docs/docstrings needed updating.
2026-07-12 07:34:47 -06:00
CodeName393 ccb2a19e7a fix(dl): prevent missing tracks error when excluding track types
- Define keep_* flags early in the track selection loop to accurately trace which track types (video, audio, subs, chapters) should be kept.
- Guard specific track filtering and validation blocks in dl.py using keep_* variables.
- Prevent fatal 'not found in video/audio/subtitle tracks' errors when using skip options like --no-video (-nv) or --no-subs (-ns).
- Simplify and clean up the trailing track cleanup logic to rely on the pre-determined keep_* flags.
2026-07-12 19:07:27 +09:00
imSp4rky f42af571a7 build(deps): cap pycaption below 2.2.27
2.2.27's WebVTT reader rewrite removes _decode and adds strict header
validation, breaking WebVTTReaderExt and HLS X-TIMESTAMP-MAP segments.
2026-07-11 18:47:35 -06:00
imSp4rky 6434fc2081 fix(dl): make audio/video track selection consistent and crash-safe
Share one best-audio selector across the episode and music paths so best/all works for songs, descriptive audio is capped to one track, and codec_priority is honored. Guard --channels and 16:9 canvas math against tracks missing channel/width metadata. Extend --best-available to video languages and full resolution misses in both normal and hybrid mode, and count only deliverable ranges when reporting missing resolutions. Rank video by resolution before bitrate, and trim group audio selections to one track per song with a warning.

BREAKING CHANGE: a missing resolution with -r HYBRID now errors without --best-available, matching non-hybrid behavior.
2026-07-11 18:41:41 -06:00
imSp4rky 575f453592 fix(dl): select only best descriptive audio track per language 2026-07-11 17:10:26 -06:00
imSp4rky c47aad6fa1 feat(tags): add OMDb metadata provider with omdb_api_key config 2026-07-11 11:46:58 -06:00
imSp4rky e7b716d79c fix(dl): restore real progress bars where progression is trackable 2026-07-11 10:51:39 -06:00
imSp4rky 20a4e6e2eb feat(tags): add imdb_api_enabled toggle, off by default 2026-07-11 09:42:52 -06:00
imSp4rky 459ed1a38e fix(downloader): release hedge loser file handles before merge sweep
superseded racers now exit on the next network arrival and the pool
waits for them on clean completion, so Windows can delete stray .!dev
files at merge time (WinError 32)
2026-07-10 13:16:30 -06:00
imSp4rky 457801d8d2 feat(dl): animate merge/decrypt/mux stages with gradient pulse bars 2026-07-10 11:28:41 -06:00
imSp4rky af46dd5fc9 fix(tracks): treat ccextractor signal-crash as non-fatal
A crash (negative return code, e.g. SIGABRT) during best-effort CC extraction now logs a warning instead of aborting a completed download.
2026-07-09 22:49:32 -06:00
imSp4rky 847696b301 feat(proxies)!: rewrite ExpressVPN provider to Android device login
Swap cookie/PKCE auth for the OAuth 2.0 device authorization grant with a cached rotating refresh token. Fix the connection-token key (`cat`) and move the cache to {cache}/vpn/ to match ProtonVPN.

BREAKING CHANGE: cookie-file auth removed; run once with `enable: true` to approve a device code.
2026-07-09 11:20:38 -06:00
imSp4rky 4ebe41fafd feat(tracks): add subtitle.type_priority config for variant ordering
Optional ranking of forced/normal/sdh per language, mirroring audio.codec_priority; first track gets the default flag, so this also picks the default subtitle. Unset = existing behavior.
2026-07-07 17:36:58 -06:00
imSp4rky 1dba4a8f82 fix(core): decode subprocess output as UTF-8 with replacement
Strict UTF-8 decode of external tool output (ffmpeg/shaka/mp4decrypt) crashed reader threads on non-English Windows (cp950/Big5).
2026-07-07 09:23:05 -06:00
imSp4rky 5cd50544a8 fix(remote): harden serve API access control and input handling
Bind sessions and download jobs to the API key (not source IP), reject path-traversal cache keys, bound decompression of peer-supplied blobs, gate the CDM device before the vault fallback, and compare API keys in constant time.
2026-07-06 23:54:05 -06:00
imSp4rky 84d9b92530 docs: expand config reference and genericize service names 2026-07-06 22:50:38 -06:00
CodeName393 774c1a4555 feat(core): add debug logging for rnet requests (#135)
- Implement request logging in RnetSession when debug_requests is enabled.
- Log requests with the actual HTTP version and size in urllib3 style.
2026-07-05 11:06:28 -06:00
imSp4rky 8bf5444ae9 refactor(core)!: bundle download_track args into DownloadContext
BREAKING CHANGE: HLS/DASH/ISM.download_track now take (track, ctx); external wrappers/monkeypatches must update to the new signature.
2026-07-04 11:38:19 -06:00
imSp4rky 52e04002e4 test(remote): add RemoteService method-contract tests 2026-07-03 21:26:47 -06:00
imSp4rky 878384b500 fix(remote): add missing get_clearkey_license to RemoteService 2026-07-03 20:50:21 -06:00