mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-06-10 03:02:09 +00:00
feat(tracks): configurable audio codec priority for tie-breaking
Adds optional `audio.codec_priority` list in unshackle.yaml to define preferred audio codec order when tracks share the same bitrate and language. Listed codecs rank in the order given; unlisted codecs retain bitrate-based order and fall after the listed group (soft priority - nothing dropped). Atmos and descriptive rules still apply last.
This commit is contained in:
@@ -168,6 +168,41 @@ dl:
|
||||
|
||||
---
|
||||
|
||||
## audio (dict)
|
||||
|
||||
Configuration for audio track selection.
|
||||
|
||||
- `codec_priority`
|
||||
Optional list of audio codec names defining the preferred order when multiple audio
|
||||
tracks share the same bitrate and language. Listed codecs are ranked in the order given.
|
||||
Codecs not in the list retain their bitrate-based ordering and are placed after all
|
||||
listed codecs (i.e. soft priority — nothing is dropped).
|
||||
|
||||
Atmos tracks still take precedence over codec priority, and audio description tracks
|
||||
are still moved to the end.
|
||||
|
||||
Valid codec names: `AAC`, `AC3`, `EC3`, `AC4`, `OPUS`, `OGG`, `DTS`, `ALAC`, `FLAC`.
|
||||
|
||||
For example,
|
||||
|
||||
```yaml
|
||||
audio:
|
||||
codec_priority: [FLAC, ALAC, AC4, EC3, DTS, AC3, OPUS, AAC, OGG]
|
||||
```
|
||||
|
||||
Or to only prefer a subset (e.g. surround codecs first, everything else falls back to
|
||||
bitrate order):
|
||||
|
||||
```yaml
|
||||
audio:
|
||||
codec_priority: [EC3, DTS, AC3, AAC]
|
||||
```
|
||||
|
||||
When unset, audio tracks are sorted by bitrate alone (with Atmos/descriptive rules still
|
||||
applied).
|
||||
|
||||
---
|
||||
|
||||
## subtitle (dict)
|
||||
|
||||
Configuration for subtitle processing and conversion.
|
||||
|
||||
@@ -1562,7 +1562,10 @@ class dl:
|
||||
processed_audio_sort_lang.append(language)
|
||||
|
||||
title.tracks.sort_videos(by_language=processed_video_sort_lang)
|
||||
title.tracks.sort_audio(by_language=processed_audio_sort_lang)
|
||||
title.tracks.sort_audio(
|
||||
by_language=processed_audio_sort_lang,
|
||||
codec_priority=config.audio.get("codec_priority"),
|
||||
)
|
||||
title.tracks.sort_subtitles(by_language=s_lang)
|
||||
|
||||
if list_:
|
||||
|
||||
@@ -71,6 +71,7 @@ class Config:
|
||||
for name, filename in (kwargs.get("filenames") or {}).items():
|
||||
setattr(self.filenames, name, filename)
|
||||
|
||||
self.audio: dict = kwargs.get("audio") or {}
|
||||
self.headers: dict = kwargs.get("headers") or {}
|
||||
self.key_vaults: list[dict[str, Any]] = kwargs.get("key_vaults", [])
|
||||
self.muxing: dict = kwargs.get("muxing") or {}
|
||||
|
||||
@@ -249,12 +249,21 @@ class Tracks:
|
||||
self.videos.sort(key=lambda x: str(x.language))
|
||||
self.videos.sort(key=lambda x: not is_close_match(language, [x.language]))
|
||||
|
||||
def sort_audio(self, by_language: Optional[Sequence[Union[str, Language]]] = None) -> None:
|
||||
"""Sort audio tracks by bitrate, Atmos, descriptive, and optionally language."""
|
||||
def sort_audio(
|
||||
self,
|
||||
by_language: Optional[Sequence[Union[str, Language]]] = None,
|
||||
codec_priority: Optional[Sequence[str]] = None,
|
||||
) -> None:
|
||||
"""Sort audio tracks by bitrate, codec priority, Atmos, descriptive, and optionally language."""
|
||||
if not self.audio:
|
||||
return
|
||||
# bitrate (highest first)
|
||||
self.audio.sort(key=lambda x: float(x.bitrate or 0.0), reverse=True)
|
||||
# codec priority (listed codecs ranked in order; unlisted fall to end with bitrate order preserved)
|
||||
if codec_priority:
|
||||
rank = {str(c).upper(): i for i, c in enumerate(codec_priority)}
|
||||
default_rank = len(rank)
|
||||
self.audio.sort(key=lambda x: rank.get(x.codec.name if x.codec else "", default_rank))
|
||||
# Atmos tracks first (prioritize over higher bitrate non-Atmos)
|
||||
self.audio.sort(key=lambda x: not x.atmos)
|
||||
# descriptive tracks last
|
||||
|
||||
@@ -422,6 +422,14 @@ curl_impersonate:
|
||||
browser: chrome120
|
||||
|
||||
# Pre-define default options and switches of the dl command
|
||||
# Audio track selection preferences
|
||||
audio:
|
||||
# Codec priority order used as a tiebreaker when multiple audio tracks share the same
|
||||
# bitrate and language. Listed codecs are ranked in the order given; codecs not in the
|
||||
# list keep their bitrate-based ordering and are placed after all listed codecs.
|
||||
# Atmos still trumps codec priority. Valid names: AAC, AC3, EC3, AC4, OPUS, OGG, DTS, ALAC, FLAC.
|
||||
# codec_priority: [FLAC, ALAC, AC4, EC3, DTS, AC3, OPUS, AAC, OGG]
|
||||
|
||||
dl:
|
||||
sub_format: srt
|
||||
downloads: 4
|
||||
|
||||
Reference in New Issue
Block a user