Commit Graph

463 Commits

Author SHA1 Message Date
Andy
ec2ecfe7b4 fix(ism): prevent duplicate track IDs for audio tracks with same lang/codec/bitrate
Include StreamIndex Name and Url attributes in the track ID hash to disambiguate tracks that share the same codec, language, bitrate, and QualityLevel index.
2026-03-07 13:01:36 -07:00
Andy
15acaea208 feat(dl): extract closed captions from HLS manifests and improve CC extraction
- Parse CLOSED-CAPTIONS entries from HLS manifests and attach CC metadata (language, name, instream_id) to video tracks
- Move CC extraction to run after decryption instead of before, fixing extraction failures on encrypted streams
- Extract CCs even when other subtitle tracks exist, using manifest CC language info instead of guessing
- Try ccextractor on the original file before repacking to preserve container-level CC data (e.g. c608 boxes) that ffmpeg remux strips
- Display deduplicated closed captions in --list output and download progress, positioned after subtitles
- Add closed_captions field to Video track class
2026-03-05 15:57:29 -07:00
Sp5rky
7dd6323be5 Merge pull request #87 from CodeName393/add-HDR-Vivid-TAG
fix(title): Add HDR Vivid Format HDR Tag
2026-03-04 15:38:03 -07:00
CodeName393
d68bb28a66 fix(title): Add HDR Vivid Format HDR Tag
The existing HDR Vivid format HDR tag processing is missing due to the feature of the title map.
2026-03-04 23:17:18 +09:00
Andy
d1e6d0812c fix(dash): pass period_filter to n_m3u8dl_re via filtered MPD file
The period_filter in DASH.to_tracks() only affected track listing but had no effect on n_m3u8dl_re downloads, which re-parsed the raw MPD and downloaded all periods including ads/pre-rolls. This caused DRM decryption failures and corrupted video output.
When periods are filtered during to_tracks(), write a filtered MPD (with rejected periods removed) to a temp file and pass it to n_m3u8dl_re via track.from_file.

Closes #51
2026-03-01 13:18:27 -07:00
Andy
2f7a3d6d1d feat(dl): add skip messages for --no-audio and --no-chapters flags 2026-02-28 14:19:06 -07:00
Andy
572a894620 feat(dl): add --animeapi and --enrich options for anime metadata and tagging
Add AnimeAPI integration to resolve anime database IDs (MAL, AniList, Kitsu, etc.) to TMDB/IMDB/TVDB for MKV tagging. The --enrich flag overrides show title and fills in year when missing from the service.

- Add animeapi-py dependency for cross-platform anime ID resolution
- Add --animeapi option (e.g. mal:12345, anilist:98765, defaults to MAL)
- Add --enrich flag to override title/year from external sources
- Remove --tmdb-name and --tmdb-year in favor of unified --enrich
- Update REST API params and docs to match
2026-02-28 12:51:14 -07:00
Andy
5bd03c67cf fix(api): resolve Sentinel serialization, missing params, and add search endpoint (#80)
Fix multiple issues with the REST API that caused downloads to fail:
- Filter Click Sentinel.UNSET enum values from service parameter defaults that caused "Object of type Sentinel is not JSON serializable" errors
- Add missing select_titles and no_video args to dl.result() call
- Fix wanted param unpacking for list-tracks SeasonRange.parse_tokens()
- Add enum conversion for vcodec, range, sub_format, and export params that were passed as strings but expected as enums by dl.result()
- Add missing dl command params: split_audio, repack, imdb_id, output_dir, no_cache, reset_cache to DEFAULT_DOWNLOAD_PARAMS and download worker
- Expand vcodec/acodec/sub_format validation to cover all supported values
- Add POST /api/search endpoint for searching services by query
- Update Swagger docs with all new params and correct type definitions
- Add comprehensive REST API documentation (docs/API.md)
- Update ADVANCED_CONFIG.md with serve CLI options and API reference
2026-02-27 19:17:15 -07:00
Andy
d8a362c853 fix(drm): update PlayReady KID extraction for pyplayready 0.8.3 compatibility
Replace removed `WrmHeader.read_attributes()` with `key_ids` property and add missing WRMHEADER v4.1-v4.3 XML paths (`DATA/PROTECTINFO/...`) to the base64 PSSH parser fallback.
2026-02-27 16:54:23 -07:00
Andy
08269bef60 feat: update unshackle version to 4.0.0 2026-02-26 22:39:25 -07:00
Andy
65ceb4ae51 chore(changelog): update changelog 2026-02-26 21:18:59 -07:00
Andy
c8883a5404 feat(templates): add configurable language tagging rule engine (#58) 2026-02-26 21:17:46 -07:00
Andy
13d7636d86 chore(changelog): update changelog for upcoming release and reorganize sections 2026-02-26 18:28:07 -07:00
Andy
6ce7b6c4d3 feat(templates)!: add customizable output filename templates (#12)
BREAKING CHANGE: The 'scene_naming' config option has been removed.
Users must configure 'output_template' in unshackle.yaml with movies, series, and songs templates. See unshackle-example.yaml for examples.
2026-02-26 18:23:18 -07:00
Andy
798ce95042 fix(dependencies): update pyplayready version to 0.8.3 and adjust dependencies 2026-02-26 14:12:38 -07:00
Andy
eeec4e1f1b feat(tracks): add edition tags to output filenames
Extend track.edition to support a list of tags (e.g., ["IMAX", "3D"]) that are inserted into the output filename before the resolution.
2026-02-26 11:11:00 -07:00
Sp5rky
6cdfd2828b Merge pull request #66 from CodeName393/Config-Filenames
Add option to include episode titles and fix video resolution bug
2026-02-26 10:30:07 -07:00
Andy
9dc56e63c4 fix: correct formatting and add missing newlines in selector and EXAMPLE service 2026-02-26 08:10:21 -07:00
Sp5rky
31f8532131 Merge pull request #83 from CodeName393/service.py
Improve service.py
2026-02-26 08:07:05 -07:00
Sp5rky
8d05a8ceb8 Merge pull request #79 from CodeName393/select-title-update
Select title update
2026-02-26 08:02:31 -07:00
CodeName393
c5ef13df5d Update selector.py 2026-02-26 15:25:09 +09:00
CodeName393
1611fcc971 Update dl.py 2026-02-26 15:18:41 +09:00
CodeName393
0f25b0ce52 Update selector.py 2026-02-26 15:18:21 +09:00
CodeName393
00b4f2cdd1 Update selector.py 2026-02-26 15:16:34 +09:00
CodeName393
65e6ae88d0 Update dl.py 2026-02-26 15:16:22 +09:00
Andy
820db5f179 refactor(providers): extract metadata providers into modular system
- Create `unshackle/core/providers/` package with abstract base class, IMDBApi (free, no key), SIMKL, and TMDB provider implementations
- Add consensus-based ID enrichment: cross-references IMDB IDs with TMDB and SIMKL, drops all data from providers that disagree on tmdb_id (likely resolved to wrong title)
- Cache enriched IDs alongside raw provider data so they survive cache round-trips
- Genericize TitleCacher with `cache_provider()`/`get_cached_provider()` replacing provider-specific methods; respect `--no-cache` flag
- Add `--imdb` CLI flag to dl command for direct IMDB ID lookup
2026-02-25 19:02:18 -07:00
Andy
42d6ef5765 fix(n_m3u8dl_re): disable segment count validation for duration-based DASH
N_m3u8DL-RE uses Math.Ceiling to calculate segment counts from SegmentTemplate @duration, which overshoots by 1 when the division has a small fractional remainder. This causes 404 on the phantom last segment and fails with "Segment count check not pass".

Upstream bug: nilaoda/N_m3u8DL-RE#108
2026-02-25 11:11:41 -07:00
CodeName393
30269b6c17 Fix 2026-02-26 02:07:06 +09:00
CodeName393
547e9f481c Merge branch 'dev' into Config-Filenames 2026-02-26 02:06:07 +09:00
CodeName393
bde1945f67 Fix 2026-02-26 02:05:40 +09:00
CodeName393
a4e1c6bb75 Fix 2026-02-26 02:01:45 +09:00
CodeName393
b26d47fd9b Update dl.py 2026-02-25 19:27:13 +09:00
CodeName393
772bacfc8f Update selector.py 2026-02-25 19:26:35 +09:00
CodeName393
d261b4715d Fix 2026-02-25 19:22:59 +09:00
CodeName393
05dc682a2d Merge branch 'dev' into service.py 2026-02-25 19:21:22 +09:00
CodeName393
86d464dc8e Fix 2026-02-25 19:19:56 +09:00
CodeName393
20bc7d2dba Fix 2026-02-25 19:18:01 +09:00
CodeName393
b1d28d3229 Fix 2026-02-25 19:17:11 +09:00
Andy
21f0186ebf feat(dl): add --output option to override download directory 2026-02-25 00:12:24 -07:00
Andy
86a7a95b6f docs: update and correct configuration documentation 2026-02-24 23:50:33 -07:00
Andy
d3fb0b6b24 refactor(example): migrate EXAMPLE service to track_request pattern 2026-02-24 13:29:10 -07:00
Andy
34f4d6bff7 fix(track): fallback to requests downloader from n_m3u8dl_re for unsupported track types 2026-02-24 12:57:46 -07:00
CodeName393
eefb6fcad7 Fix 2026-02-25 01:44:33 +09:00
CodeName393
c78a649170 Fix 2 2026-02-25 01:34:58 +09:00
CodeName393
c01e3993ce Fix 1 2026-02-25 01:34:24 +09:00
CodeName393
eba9f846b0 Improve service.py
Fix the issue of missing the get_playready_license service helper function on service.py
2026-02-25 00:44:04 +09:00
Andy
b11b23e529 chore(release): bump version to 3.1.0 2026-02-23 16:27:05 -07:00
Andy
19341e2569 refactor(dl): remove legacy multi-fetch loop for unmigrated services 2026-02-23 16:21:54 -07:00
Andy
d0341f6844 feat(core): add TrackRequest system for multi-codec/multi-range support
Add TrackRequest dataclass to Service base class that centralizes CLI vcodec/range/best_available params. Services read from self.track_request instead of accessing ctx.parent.params directly.

- Add TrackRequest dataclass with codecs, ranges, best_available fields
- Set self.track_request in Service.__init__() from CLI params
- Add _get_tracks_for_variants() helper for per-codec/range API calls
- Update dl.py to detect migrated vs legacy services automatically
- Handle HYBRID+other ranges (e.g. -r HYBRID,SDR) correctly in dl.py
- Support --best-available with multi-range/codec (skip unavailable)
2026-02-23 15:47:27 -07:00
Andy
983fd18d53 fix(session): reduce default max_retries from 10 to 5 for CurlSession
fix(service): reduce max_retries from 15 to 5 for HTTPAdapter
2026-02-23 12:59:07 -07:00