feat(tracks): add language_priority to sort preferred languages first

subtitle.language_priority and audio.language_priority prepend to the CLI
languages, so the named languages sort first and nothing is filtered.
--exact-lang now applies to the sorts too, through matching_languages, which
follows the same RFC 4647 rule as Tracks.by_language and ignores invalid tags.
This commit is contained in:
imSp4rky
2026-08-03 10:15:05 -06:00
parent 4e1ccf3230
commit a6997f6bca
10 changed files with 277 additions and 36 deletions
+7 -1
View File
@@ -97,9 +97,15 @@ unshackle dl [OPTIONS] SERVICE [SERVICE ARGS...]
| `--require-subs` | - | Required subtitle langs; keeps **all** subs only if these exist. **Cannot combine with `--s-lang`.** |
| `-fs`, `--forced-subs` | off | Include forced subtitle tracks. |
| `-fsl`, `--forced-s-lang` | none | Language(s) wanted for forced subtitles; implies `-fs`. |
| `--exact-lang` | off | Exact matching only: `-l es-419` matches `es-419`, not `es-ES`. |
| `--exact-lang` | off | Exact matching only: `-l es-419` matches `es-419`, not `es-ES`. Applies to selection and to sort order. |
| `--sub-format` | - | Output subtitle format (`SRT`/`srt`, `VTT`/`webvtt`, `ASS`/`ssa`, `TTML`, `SMI`, ...), or `original` to keep the source format. |
!!! tip "These flags select languages, they do not order them"
Naming languages with `-l` or `-sl` removes the others. To keep every language but put
your preferred ones first, use `audio.language_priority` and
[`subtitle.language_priority`](../reference/configuration.md#subtitle) in your
configuration file.
The special language tokens `orig`, `all`, and `best` are honoured everywhere a language is expected.
### Title & episode selection
+20
View File
@@ -254,6 +254,26 @@ it is used. You can override each stream type independently:
unshackle dl -al en EXAMPLE 81234567
```
### Sort order
`-l` and `-sl` **select** languages: naming some removes the rest. To keep every language
but decide which ones come first, set a priority list in your configuration file:
```yaml title="unshackle.yaml"
audio:
language_priority: [orig, en]
subtitle:
group_by: language
language_priority: [en, es, fr]
```
Subtitles then start with English, Spanish, and French. The languages you leave out follow
alphabetically, after the title's original language. Nothing is removed. Audio works the
same way, but the languages you leave out keep their bitrate and codec order instead of an
alphabetical one.
See [`subtitle.language_priority`](../reference/configuration.md#subtitle) for the details.
### Exact vs fuzzy matching
By default language matching is fuzzy: `-l en` also accepts `en-US`, `en-GB`, etc. (up
+2
View File
@@ -376,6 +376,8 @@ subtitle:
| `convert_before_strip` | `true` | `true` / `false` | Convert a subtitle to SRT before stripping SDH (for non-SubtitleEdit engines). |
| `output_mode` | `mux` | `mux`, `sidecar`, `both` | Whether subtitles are embedded, written as sidecars, or both. |
| `sidecar_format` | `srt` | a format name (e.g. `srt`, `vtt`) or `original` | Format used for sidecar files. |
| `group_by` | `type` | `type`, `language` | Whether all tracks of one type stay together, or each language stays next to its own variants. |
| `language_priority` | *(unset)* | a list of languages | Languages to sort to the top. The rest keep the default order. Nothing is removed. |
!!! tip "SubtitleEdit is optional but recommended"
Several high-fidelity paths (the best-quality conversions and the SubtitleEdit SDH