PR #38 refactored n_m3u8dl_re track selection to support DASH/ISM subtitle tracks, but this broke some subtitle downloads. Services that use direct URL downloads (Descriptor.URL) for subtitles, which n_m3u8dl_re does not support.
The track_selection function was using findall() to search for lang child elements, but in DASH manifests lang is an XML attribute on AdaptationSet. This caused language selection to fail for region-specific codes like es-419.
Apply the same partial cached keys fix from decrypt_labs_remote_cdm to custom_remote_cdm. When cached keys don't cover all required KIDs, store them in session["cached_keys"] instead of session["keys"] to allow parse_license() to properly combine vault_keys + cached_keys + license_keys.
When decrypt-labs returns cached keys that don't cover all required KIDs, the CDM now properly stores them in session["cached_keys"] instead of session["keys"]. This allows parse_license() to correctly combine vault_keys + cached_keys + license_keys, fixing downloads that previously failed when mixing cached and fresh licenses.
Add preserve_formatting config option to prevent automatic subtitle processing that strips formatting tags and styling. When enabled (default: true), WebVTT files skip pycaption read/write cycle to preserve tags like <i>, <b>, positioning, and other formatting.
Implements cross-platform font discovery and intelligent fallback system for ASS/SSA subtitle rendering on Linux/macOS systems.
Windows support has not been tested
Implement comprehensive per-service config override system that allows any configuration section (dl, n_m3u8dl_re, aria2c, subtitle, etc.) to be customized on a per-service basis.
Fixes#13
Fix off-by-one error in SegmentTemplate segment enumeration when startNumber is 0. Previously, the code would request one extra segment beyond what exists, causing 404 errors on the final segment.
The issue was that end_number was calculated as a segment count via math.ceil(), but then used incorrectly with range(start_number, end_number + 1), treating it as both a count and an inclusive endpoint.
Changed to explicitly calculate segment_count first, then derive end_number as: start_number + segment_count - 1
Example:
- Duration: 3540.996s, segment duration: 4s
- Before: segments 0-886 (887 segments) - segment 886 doesn't exist
- After: segments 0-885 (886 segments) - correct
HDR10/PQ detection now includes:
- PQ (most common)
- SMPTE ST 2084 (CICP value 16)
- BT.2100
- BT.2020-10
- smpte2084 (lowercase variant)
HLG detection now includes:
- HLG
- Hybrid Log-Gamma
- ARIB STD-B67 (CICP value 18)
- arib-std-b67 (lowercase variant)
Hybrid DV+HDR10 detection:
- Now checks full hdr_format field for both "Dolby Vision" AND
("HDR10" OR "SMPTE ST 2086")
- Properly generates filenames like "Movie.2160p.DV HDR H.265.mkv"
- MediaInfo reports: "Dolby Vision / SMPTE ST 2086, HDR10 compatible"
Also adds null safety for transfer characteristics to prevent errors when the field is None.
Add support for downloading audio description tracks via the --audio-description/-ad flag. Previously, descriptive audio tracks were always filtered out. Users can now optionally include them.
Fixes#33
Add validation to check that both HDR10 and DV tracks are available when HYBRID mode is requested. This prevents wasted downloads when the hybrid processing would fail due to missing tracks.