mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-11-11 19:45:06 +00:00
docs: cleanup and correct documentation
This commit is contained in:
@@ -36,18 +36,18 @@ unshackle --help
|
||||
|
||||
### Requirements
|
||||
|
||||
External tools on your `PATH` (recommended versions):
|
||||
External tools. (recommended versions):
|
||||
|
||||
- [Python](https://www.python.org/) - 3.11 - 3.14
|
||||
- [uv](https://docs.astral.sh/uv/) - ≥ 0.5
|
||||
- [FFmpeg](https://ffmpeg.org/) - ≥ 6.0
|
||||
- [MKVToolNix](https://mkvtoolnix.download/) - ≥ 80
|
||||
- [shaka-packager](https://github.com/shaka-project/shaka-packager/releases/tag/v2.6.1) - 2.6.1
|
||||
- [Bento4](https://github.com/axiomatic-systems/Bento4) - ≥ 1.6.0-639
|
||||
- [dovi_tool](https://github.com/quietvoid/dovi_tool) - ≥ 2.1
|
||||
|
||||
Optional:
|
||||
|
||||
- [Bento4](https://github.com/axiomatic-systems/Bento4) - ≥ 1.6.0-639
|
||||
- [dovi_tool](https://github.com/quietvoid/dovi_tool) - ≥ 2.1
|
||||
- [SubtitleEdit](https://github.com/SubtitleEdit/subtitleedit/releases) - ≥ 5.0 (`SeConv` CLI)
|
||||
|
||||
## License
|
||||
|
||||
@@ -105,7 +105,7 @@ turned into underscores (`--best-available` → `best_available`).
|
||||
dl:
|
||||
lang: [en] # -l en
|
||||
quality: [1080] # -q 1080
|
||||
vcodec: [H265] # -v H265
|
||||
vcodec: [H.265] # -v H.265
|
||||
sub_format: srt # convert subtitles to SRT
|
||||
downloads: 2 # two tracks at once
|
||||
```
|
||||
@@ -159,7 +159,7 @@ The directories unshackle uses:
|
||||
| `fonts` | Bundled fonts | Yes |
|
||||
|
||||
!!! note "Some directories cannot be moved"
|
||||
A handful of internal locations are protected: the package root, the core directory, the user-config directory, and the data base. If you list them under `directories`, unshackle silently ignores the override. This is intentional; those paths are tied to where the package is installed.
|
||||
unshackle protects five internal entries: `app_dirs`, `core_dir`, `namespace_dir`, `user_configs`, and `data`. If you list any of them under `directories`, unshackle ignores the override. This is intentional; those paths are tied to where the package is installed.
|
||||
|
||||
### The `services` directory is special
|
||||
|
||||
@@ -168,12 +168,12 @@ Unlike the other entries, `services` is a **list**, and each entry can be either
|
||||
```yaml title="unshackle.yaml"
|
||||
directories:
|
||||
services:
|
||||
- unshackle-dl/services # a GitHub owner/repo shorthand
|
||||
- https://github.com/me/my-services.git
|
||||
- you/your-services # a GitHub owner/repo shorthand
|
||||
- https://example.com/private-services.git
|
||||
- ~/code/local-services # a local folder
|
||||
```
|
||||
|
||||
Entries are searched in the order listed, and **the first source to define a given service tag wins**, so put local folders last if you want them to act as fallbacks rather than overrides. Remote repositories are cloned and periodically updated for you. See [Services](../dev/creating-a-service.md) for the full details on how service discovery and repositories work.
|
||||
unshackle searches entries in the order listed, and **the first source to define a given service tag wins**, so put local folders last if you want them to act as fallbacks rather than overrides. unshackle clones remote repositories on first use and refreshes them at most once a day. See [Creating a Service](../dev/creating-a-service.md) for how service discovery and repositories work.
|
||||
|
||||
## The `filenames` key
|
||||
|
||||
@@ -197,10 +197,10 @@ $ unshackle cfg tag MYGRP
|
||||
$ unshackle cfg cdm.default my_device_l3
|
||||
```
|
||||
|
||||
Values are parsed as Python literals where possible, so numbers, booleans, and lists work naturally, while bare text is treated as a string:
|
||||
unshackle parses the value as a Python literal, so write booleans as `True`/`False` and quote the strings inside a list (`"['en']"`). Anything that is not valid Python literal syntax is stored as a plain string:
|
||||
|
||||
```console
|
||||
$ unshackle cfg update_checks false
|
||||
$ unshackle cfg update_checks False
|
||||
$ unshackle cfg vault_timeout 30
|
||||
```
|
||||
|
||||
@@ -216,7 +216,7 @@ $ unshackle cfg cdm.default --unset
|
||||
$ unshackle cfg --list
|
||||
```
|
||||
|
||||
When it writes, `unshackle cfg` targets the config file that was loaded. If none exists yet, it creates `unshackle.yaml` in your OS user-config directory.
|
||||
When it writes, `unshackle cfg` targets the config file that was loaded. If none exists yet, it creates `unshackle.yaml` inside the `unshackle` package folder (search location 1), not your OS user-config directory. To keep the config outside the package, create the file at the user-config path yourself first, then `unshackle cfg` writes to it.
|
||||
|
||||
!!! warning "Editing with `cfg` strips comments"
|
||||
Because `unshackle cfg` rewrites the whole file when it saves, any comments in `unshackle.yaml` are removed by a write. If you keep important notes as comments, edit the file by hand instead, or keep those notes elsewhere.
|
||||
@@ -225,4 +225,4 @@ When it writes, `unshackle cfg` targets the config file that was loaded. If none
|
||||
|
||||
- Browse the [Configuration Reference](../reference/configuration.md) for every key and default.
|
||||
- Set up your first download in [Downloading](../guide/downloading.md).
|
||||
- Learn how services are discovered and updated in [Services](../dev/creating-a-service.md).
|
||||
- Learn how services are discovered and updated in [Creating a Service](../dev/creating-a-service.md).
|
||||
|
||||
@@ -88,8 +88,8 @@ uv run unshackle env check
|
||||
## External tools on your PATH
|
||||
|
||||
unshackle shells out to a number of external command-line programs for media
|
||||
processing and DRM work. It looks for each one first in a `binaries/` folder
|
||||
next to the installed package, and then falls back to your system `PATH`, so
|
||||
processing and DRM work. It looks for each one first in the `binaries/` folder
|
||||
inside the installed package, and then falls back to your system `PATH`, so
|
||||
installing these tools system-wide (or dropping them into that folder) both
|
||||
work.
|
||||
|
||||
@@ -108,7 +108,7 @@ These must be present for core downloading, decryption, and muxing to work:
|
||||
!!! warning "shaka-packager is the default decryptor"
|
||||
unshackle decrypts with shaka-packager unless you explicitly configure a
|
||||
different decryptor. If it is missing, protected downloads will fail at the
|
||||
decryption step. See the [configuration reference](configuration-file.md) for the
|
||||
decryption step. See the [configuration reference](../reference/configuration.md#decryption) for the
|
||||
`decryption` key if you want to switch to `mp4decrypt`.
|
||||
|
||||
### Recommended and optional tools
|
||||
@@ -147,7 +147,7 @@ it depends on.
|
||||
unshackle --help
|
||||
```
|
||||
|
||||
This prints the banner and the list of available commands (`dl`, `env`, `kv`,
|
||||
This prints the list of available commands (`dl`, `env`, `kv`,
|
||||
`serve`, `wvd`, `prd`, `search`, `util`, `cfg`, `import`). If your shell reports
|
||||
that `unshackle` is not found, the `uv tool` bin directory is probably not on
|
||||
your `PATH`. Run `uv tool update-shell` and open a new terminal.
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
# Quick Start
|
||||
|
||||
This page takes you from a fresh install to your first downloaded file. You will
|
||||
create the one piece of configuration unshackle insists on, add a streaming
|
||||
service and a CDM so it can actually fetch and decrypt media, run a basic
|
||||
`unshackle dl` command, and learn where the finished file lands.
|
||||
create the one piece of configuration unshackle insists on, supply the service
|
||||
module and CDM it needs to fetch and decrypt media, run a basic `unshackle dl`
|
||||
command, and learn where the finished file lands.
|
||||
|
||||
!!! note "Before you start"
|
||||
This guide assumes unshackle is already installed and on your `PATH`. If
|
||||
`unshackle --help` does not print a help screen, work through
|
||||
[Installation](installation.md) first.
|
||||
|
||||
!!! warning "unshackle includes no services"
|
||||
unshackle handles manifests, DRM, downloading, and muxing. It does not include a
|
||||
module for any streaming platform, so you write that part yourself
|
||||
([step 3](#3-write-a-service)). `EXAMPLE` in this guide stands in for the tag you
|
||||
give yours.
|
||||
|
||||
## 1. Check your environment
|
||||
|
||||
unshackle drives several external tools (FFmpeg, MKVToolNix, shaka-packager, and
|
||||
@@ -58,12 +64,12 @@ Everything else has a sensible default. A minimal, working config looks like thi
|
||||
```yaml title="unshackle.yaml"
|
||||
output_template:
|
||||
movies: "{title} ({year}) {quality} {source}"
|
||||
series: "{title} S{season}E{episode} {episode_name} {quality} {source}"
|
||||
series: "{title} {season_episode} {episode_name?} {quality} {source}"
|
||||
```
|
||||
|
||||
Each `{variable}` is filled in from the title and the tracks you downloaded. The
|
||||
full set of valid variables, including `resolution`, `video`, `audio`, `hdr`,
|
||||
`edition`, `tag`, and more, is documented in [Configuration](configuration-file.md).
|
||||
`edition`, `tag`, and more, is documented in [Output and Naming](../guide/output-and-naming.md).
|
||||
|
||||
!!! note "Spaces or dots?"
|
||||
unshackle auto-detects your naming style from the template: if the separators
|
||||
@@ -77,51 +83,15 @@ full set of valid variables, including `resolution`, `video`, `audio`, `hdr`,
|
||||
rewrites the file and **removes any comments** it contained. If you keep notes
|
||||
in your config, edit the file by hand instead.
|
||||
|
||||
## 3. Add a service
|
||||
## 3. Write a service
|
||||
|
||||
The service tag you pass to `dl` (like `EXAMPLE`) maps to a **service module**, a small
|
||||
plugin that knows how to talk to one streaming platform. unshackle ships without
|
||||
any bundled services, so you add the one(s) you want.
|
||||
The service tag you pass to `dl` (like `EXAMPLE`) maps to a **service module**, the
|
||||
plugin that talks to one streaming platform. unshackle includes none, so you write
|
||||
the one you need. [Creating a Service](../dev/creating-a-service.md) covers how.
|
||||
|
||||
Services live under the `directories.services` path (run `unshackle env info` to
|
||||
see where that is). unshackle discovers them by looking for `*/__init__.py`: the
|
||||
folder name becomes the **service tag**, and the folder must contain a class with
|
||||
that exact same name.
|
||||
|
||||
=== "Local folder"
|
||||
|
||||
Drop a service folder into your services directory. A service tagged `EXAMPLE`
|
||||
lives at:
|
||||
|
||||
```
|
||||
<services>/EXAMPLE/__init__.py # defines a class named EXAMPLE
|
||||
```
|
||||
|
||||
Once the folder is in place, the tag `EXAMPLE` is immediately available to `dl`,
|
||||
`search`, and the other service-aware commands.
|
||||
|
||||
=== "Git repository"
|
||||
|
||||
`directories.services` may also list git repositories. unshackle clones them
|
||||
on first use and keeps them up to date:
|
||||
|
||||
```yaml title="unshackle.yaml"
|
||||
directories:
|
||||
services:
|
||||
- owner/unshackle-services # a GitHub owner/repo shorthand
|
||||
- /path/to/local/services # local folders still work too
|
||||
```
|
||||
|
||||
Force a refresh of every configured service repo at any time with:
|
||||
|
||||
```shell
|
||||
unshackle util refresh-services
|
||||
```
|
||||
|
||||
!!! info "Where to get services"
|
||||
Service modules are kept separate from the core project. Ask in the community
|
||||
[Discord](https://discord.gg/mHYyPaCbFK) for where to find the service you
|
||||
need. The core repository deliberately does not host them.
|
||||
Put the finished module in your `directories.services` folder (`unshackle env info`
|
||||
shows the path). The tag then works with `dl`, `search`, and the other service
|
||||
commands.
|
||||
|
||||
## 4. Add a CDM for DRM
|
||||
|
||||
@@ -144,7 +114,7 @@ cdm:
|
||||
```
|
||||
|
||||
PlayReady works the same way with `.prd` files created and managed by the
|
||||
[`prd`](configuration-file.md) command. If a title is DRM-free, no CDM is needed.
|
||||
[`prd`](../guide/cli-reference.md#prd) command. If a title is DRM-free, no CDM is needed.
|
||||
|
||||
!!! tip
|
||||
Run `unshackle wvd parse my_device` to inspect a device's security level and
|
||||
@@ -199,7 +169,7 @@ unshackle dl <FLAGS> <SERVICE-TAG> <TITLE>
|
||||
- **`<SERVICE-TAG>`** picks which service to talk to (e.g. `EXAMPLE`).
|
||||
- **`<TITLE>`** is the URL, ID, or slug the service understands.
|
||||
|
||||
A good first command asks for 1080p with English audio and subtitles:
|
||||
A good first command asks for 1080p with English audio:
|
||||
|
||||
```shell title="Your first download"
|
||||
unshackle dl -q 1080 -l en EXAMPLE 81234567
|
||||
@@ -213,7 +183,7 @@ keys through your CDM (and any key vaults), then decrypt, mux, and tag the resul
|
||||
| Flag | Meaning |
|
||||
|---|---|
|
||||
| `-q`, `--quality` | Target resolution(s), e.g. `-q 1080` or `-q 1080,720`. Defaults to best available. |
|
||||
| `-l`, `--lang` | Language(s) for video and audio, e.g. `-l en` or `-l orig,en`. `orig` = the title's original language. |
|
||||
| `-l`, `--lang` | Language(s) for video and audio, e.g. `-l en` or `-l orig,en`. `orig` = the title's original language. Defaults to `orig`. |
|
||||
| `-sl`, `--s-lang` | Subtitle language(s); defaults to `all`. |
|
||||
| `-v`, `--vcodec` | Video codec, e.g. `-v H.265`. Defaults to any. |
|
||||
| `-r`, `--range` | Dynamic range, e.g. `-r HDR10` or `-r DV`. Defaults to `SDR`. |
|
||||
@@ -238,18 +208,18 @@ codec, bitrate, channel-layout, and track-type selection.
|
||||
|
||||
## 8. Where the output lands
|
||||
|
||||
By default, finished files are written to the `downloads` directory
|
||||
By default, unshackle writes finished files to the `downloads` directory
|
||||
(`unshackle env info` shows its exact path; the built-in default is a `downloads`
|
||||
folder alongside the project). Override it per run with `-o`:
|
||||
folder one level above the installed `unshackle` package). Override it per run with `-o`:
|
||||
|
||||
```shell
|
||||
unshackle dl -q 1080 -o /mnt/media/incoming EXAMPLE 81234567
|
||||
```
|
||||
|
||||
- **Movies** are written as a single `.mkv` file named from your `movies` template.
|
||||
- unshackle writes **movies** as a single `.mkv` file named from your `movies` template.
|
||||
- **TV episodes** are grouped into a per-show / per-season folder (from your
|
||||
`series` template) unless you pass `--no-folder`.
|
||||
- The filename is built from your `output_template`, and IMDb/TMDB IDs are added to
|
||||
- unshackle builds the filename from your `output_template` and adds IMDb/TMDB IDs to
|
||||
the file's metadata tags when available.
|
||||
|
||||
To change the default output location permanently, set it in your config:
|
||||
@@ -270,5 +240,5 @@ directories:
|
||||
|
||||
!!! tip "You are never far from help"
|
||||
`unshackle --help`, `unshackle dl --help`, and `unshackle <command> --help`
|
||||
list every option with its default. When in doubt, add `--list` to a `dl`
|
||||
list every option. When in doubt, add `--list` to a `dl`
|
||||
command to preview what it would do before it downloads anything.
|
||||
|
||||
+22
-18
@@ -4,7 +4,7 @@
|
||||
streaming service, selects exactly the tracks you asked for, acquires and applies
|
||||
decryption keys, and muxes everything into a finished Matroska file. The flags below
|
||||
cover quality and codec selection, language and subtitle handling, episode ranges, and
|
||||
the download flow itself, with examples throughout.
|
||||
the download flow itself.
|
||||
|
||||
!!! note "Where the full flag list lives"
|
||||
This page covers the flags you will use most and explains how they interact. It is
|
||||
@@ -64,8 +64,9 @@ helps explain why, for example, `--list` stops early and why keys are fetched ev
|
||||
9. **Post-process**: extract closed captions, convert subtitles, repack, mux with
|
||||
`mkvmerge`, and move the finished file to your downloads directory.
|
||||
|
||||
`--list` and `--list-titles` stop after selection/filtering and print what *would* be
|
||||
downloaded. `--skip-dl` runs the license step but skips the actual segment download.
|
||||
`--list` prints the tracks a title exposes and stops before selection. `--list-titles`
|
||||
prints every title the service returned and stops before `--wanted`/`--latest-episode`
|
||||
filtering. `--skip-dl` runs the license step but skips the actual segment download.
|
||||
|
||||
## Choosing quality
|
||||
|
||||
@@ -141,9 +142,11 @@ unshackle dl -q 2160 -r HDR10,DV EXAMPLE '...'
|
||||
|
||||
!!! warning "HYBRID requires dovi_tool"
|
||||
`-r HYBRID` produces a single hybrid stream by injecting the Dolby Vision RPU
|
||||
metadata onto an HDR10/HDR10+ base layer using **dovi_tool**. It requires the
|
||||
`dovi_tool` binary on your PATH and needs both an HDR10(+) *and* a DV track to be
|
||||
available, otherwise the title fails (unless `--best-available` lets it fall back).
|
||||
metadata onto an HDR10/HDR10+ base layer using **dovi_tool**.
|
||||
It requires the `dovi_tool` binary, resolved from unshackle's `binaries/` folder or
|
||||
your `PATH`. The normal case is a DV track plus an HDR10 or HDR10+ base. With HDR10+
|
||||
and no DV, unshackle converts the HDR10+ metadata to DV instead, which also needs
|
||||
`hdr10plus_tool`. With no DV and no HDR10+, the title fails.
|
||||
When HDR10+ is present it is preferred over HDR10 as the base layer.
|
||||
|
||||
To keep an HDR10+ deliverable *alongside* the hybrid, request both ranges:
|
||||
@@ -171,8 +174,8 @@ Manifest-declared bitrates are sometimes rounded or wrong. Services often advert
|
||||
**peak** or **nominal** bandwidth that is far from the stream's real average. This matters
|
||||
because a track's bitrate drives the track listing, the sort order, *and* the
|
||||
`--vbitrate`/`--vbitrate-range` selection above. A bogus declared value therefore makes
|
||||
unshackle pick the wrong track. These flags remove that risk by probing the actual media
|
||||
size to compute a true bitrate for the top renditions, overriding the manifest value:
|
||||
unshackle pick the wrong track. These flags probe the actual media size to compute a true
|
||||
bitrate for the top renditions, overriding the manifest value:
|
||||
|
||||
- `-rvb` / `--real-video-bitrate`: probe real video bitrates (per codec/range).
|
||||
- `-rab` / `--real-audio-bitrate`: probe real audio bitrates (per codec/channels/
|
||||
@@ -186,12 +189,13 @@ size to compute a true bitrate for the top renditions, overriding the manifest v
|
||||
That is the real *delivered* size, not an over-report or a bug.
|
||||
|
||||
!!! tip "Why not every rendition is probed"
|
||||
Probing does not touch every rendition. Only the top rendition of each quality tier is
|
||||
probed in parallel (video grouped by codec+range, audio by codec+channels+language),
|
||||
and the pass then reaches downward only as far as it must to keep the ranking correct.
|
||||
This keeps probing fast even when a service exposes dozens of renditions. Tracks whose
|
||||
duration can't be determined fall back to `ffprobe`, and a probe failure is non-fatal:
|
||||
the manifest value is simply left in place.
|
||||
Probing does not touch every rendition. Only the five highest declared-bitrate
|
||||
renditions of each quality tier are probed in parallel (video grouped by codec and
|
||||
range, audio by codec, channels, language, and descriptive flag), and unshackle
|
||||
extends a group downward while a lower unprobed rendition could still outrank a
|
||||
probed one. This keeps probing fast even when a service exposes dozens of renditions.
|
||||
Tracks whose duration can't be determined fall back to `ffprobe`, and a probe failure
|
||||
is non-fatal: the manifest value is simply left in place.
|
||||
|
||||
## Audio codec, channels, and Atmos
|
||||
|
||||
@@ -347,7 +351,7 @@ with `-` to exclude it.
|
||||
| --- | --- |
|
||||
| `--select-titles` | Interactively pick episodes from a list (Series only). **Cannot combine with `-w`.** |
|
||||
| `--latest-episode` | Download only the single most recent episode. |
|
||||
| `--list-titles` | List the titles that would be downloaded, then stop. |
|
||||
| `--list-titles` | List every title the service returned, then stop. `-w`/`--latest-episode` are not applied to this listing. |
|
||||
|
||||
```shell title="Grab just the newest episode"
|
||||
unshackle dl --latest-episode EXAMPLE 81234567
|
||||
@@ -398,8 +402,8 @@ Before committing to a long download, inspect what unshackle *would* do:
|
||||
|
||||
| Flag | Effect |
|
||||
| --- | --- |
|
||||
| `--list` | List the available tracks and which would be selected, then stop. No download. |
|
||||
| `--list-titles` | List the titles (episodes) that would be downloaded, then stop. |
|
||||
| `--list` | List the tracks the service exposes for each title, then stop. No selection, no download. |
|
||||
| `--list-titles` | List every title the service returned, then stop. `-w`/`--latest-episode` are not applied to this listing. |
|
||||
| `--skip-dl` | Skip downloading but still acquire the decryption keys. |
|
||||
|
||||
```shell title="See the track selection without downloading"
|
||||
@@ -428,7 +432,7 @@ flags change how the output is assembled:
|
||||
| --- | --- | --- |
|
||||
| `--no-mux` | Do not mux; keep the individual track files. | - |
|
||||
| `--split-audio` | Write a separate output file per audio codec instead of merging all audio. | config `muxing.merge_audio` (on) |
|
||||
| `--merge-video` | Mux all selected video tracks into one file. | config `muxing.merge_video` (off) |
|
||||
| `--merge-video` | Mux video tracks that share a height, range, and codec into one file, so only language varies inside a file. | config `muxing.merge_video` (off) |
|
||||
|
||||
### Naming tags
|
||||
|
||||
|
||||
+10
-8
@@ -5,18 +5,20 @@ media from streaming manifests, handles the DRM, and muxes everything into clean
|
||||
well-tagged files, all driven from a single command-line tool, or served over a
|
||||
REST API for automation.
|
||||
|
||||
It is a fork of [Devine](https://github.com/devine-dl/devine) with first-class
|
||||
DASH, HLS, and Smooth Streaming (ISM) parsing, both **Widevine** and **PlayReady**
|
||||
DRM support, and a built-in HTTP server.
|
||||
It is a fork of [Devine](https://github.com/devine-dl/devine) with DASH, HLS, and
|
||||
Smooth Streaming (ISM) parsing, both **Widevine** and **PlayReady** DRM support,
|
||||
and a built-in HTTP server.
|
||||
|
||||
!!! warning "Use responsibly"
|
||||
unshackle is licensed under [GPL-3.0](https://github.com/unshackle-dl/unshackle/blob/master/LICENSE).
|
||||
unshackle is licensed under [GPL-3.0](https://github.com/unshackle-dl/unshackle/blob/main/LICENSE).
|
||||
Do not use it for content you do not have the rights to. Keep the core free and
|
||||
open, keep service code private, and be kind.
|
||||
|
||||
## What it does
|
||||
|
||||
Point unshackle at a title on a streaming service and it will:
|
||||
unshackle does everything except talk to the streaming platform. You write that part
|
||||
as a service module ([Creating a Service](dev/creating-a-service.md)). Point unshackle
|
||||
at a title and it will:
|
||||
|
||||
- Fetch the title metadata (movies, full series, seasons, episodes, albums, tracks).
|
||||
- Parse the streaming manifest: **DASH**, **HLS**, or **Smooth Streaming (ISM)**.
|
||||
@@ -40,7 +42,7 @@ Point unshackle at a title on a streaming service and it will:
|
||||
| Subtitles | SRT, WebVTT, ASS/SSA, TTML and more, with optional SDH stripping and format conversion |
|
||||
| Key vaults | SQLite, MySQL, and HTTP/API vaults to store and share content keys |
|
||||
| Proxies | Basic proxies plus NordVPN, ProtonVPN, Surfshark, Windscribe, ExpressVPN, Gluetun, and Hola providers |
|
||||
| Services | Pluggable service modules, loadable from local folders or git repositories |
|
||||
| Services | A plugin API for the service modules you write. unshackle includes none |
|
||||
| Automation | A REST API with a job queue, live progress, history, and remote-download sessions |
|
||||
|
||||
## Installation at a glance
|
||||
@@ -70,7 +72,7 @@ Point unshackle at a title on a streaming service and it will:
|
||||
Every download is three parts: the `dl` command, a **service tag**, and the
|
||||
service's title argument (a URL, ID, or slug).
|
||||
|
||||
```shell title="Download a 1080p title with English audio and subtitles"
|
||||
```shell title="Download a 1080p title with English audio"
|
||||
unshackle dl -q 1080 -l en EXAMPLE 81234567
|
||||
```
|
||||
|
||||
@@ -84,7 +86,7 @@ install to your first file.
|
||||
- **[Installation](getting-started/installation.md)**. Install unshackle and the external tools it depends on.
|
||||
- **[Quickstart](getting-started/quickstart.md)**. Configure `unshackle.yaml` and run your first download.
|
||||
- **[Downloading](guide/downloading.md)**. The full `dl` command guide: quality, codecs, languages, track selection, and output.
|
||||
- **[Configuration](getting-started/configuration-file.md)**. Every `unshackle.yaml` key, directories, vaults, proxies, and naming templates.
|
||||
- **[Configuration](getting-started/configuration-file.md)**. Where `unshackle.yaml` lives, the directory layout, and how to edit values. Full key list in the [Configuration Reference](reference/configuration.md).
|
||||
- **[REST API](dev/rest-api/index.md)**. Run the `serve` HTTP server and drive downloads programmatically.
|
||||
|
||||
!!! tip "Getting help"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Configuration Reference
|
||||
|
||||
This page is the exhaustive, authoritative reference for **every** key you can set in
|
||||
This page documents every key you can set in
|
||||
`unshackle.yaml`. For each key you will find its name, expected type, default value, and
|
||||
what it does. Keys are grouped by area so you can jump straight to the part of unshackle
|
||||
you are configuring.
|
||||
@@ -10,10 +10,12 @@ edit it), start with [The Configuration File](../getting-started/configuration-f
|
||||
This page assumes you already know the basics and want precise details.
|
||||
|
||||
!!! info "How defaults work"
|
||||
Every key is optional. If you omit a key, unshackle uses the built-in default listed
|
||||
here. There is **no schema validation**: unknown keys are silently ignored (they never
|
||||
become settings), and the file is parsed with `yaml.safe_load`. An empty or missing
|
||||
file means *all* defaults apply.
|
||||
Every key is optional except [`output_template`](#output-naming), which `dl` requires.
|
||||
Without it, `dl` aborts with an error. If you omit any other key, unshackle uses
|
||||
the built-in default listed here. There is **no schema validation**: unknown keys are
|
||||
silently ignored (they never become settings), and the file is parsed with
|
||||
`yaml.safe_load`. An empty or missing file means every other key falls back to its
|
||||
default.
|
||||
|
||||
!!! warning "Two keys behave specially on load"
|
||||
- `curl_impersonate` is a **deprecated** alias of [`network`](#network-proxy) and emits a
|
||||
@@ -32,7 +34,7 @@ This page assumes you already know the basics and want precise details.
|
||||
|------|------|
|
||||
| [Directories](#directories) | `directories`, `filenames` |
|
||||
| [Services & authentication](#services-auth) | `services`, `credentials`, `firefox_cookies`, `remote_services`, `serve` |
|
||||
| [Download & processing](#download-processing) | `dl`, `subtitle`, `audio`, `muxing`, `language_tags` |
|
||||
| [Download & processing](#download-processing) | `dl`, `subtitle`, `audio`, `muxing`, `language_tags`, `dual_multi_mode` |
|
||||
| [Output & naming](#output-naming) | `output_template`, `tag`, `tag_group_name`, `tag_imdb_tmdb`, `chapter_fallback_name`, `unicode_filenames` |
|
||||
| [DRM & CDM](#drm-cdm) | `cdm`, `remote_cdm`, `decryption` |
|
||||
| [Network & proxy](#network-proxy) | `network`, `headers`, `proxy_providers` |
|
||||
@@ -91,7 +93,7 @@ directories:
|
||||
```yaml
|
||||
directories:
|
||||
services:
|
||||
- unshackle-dl/community-services # cloned from GitHub
|
||||
- you/your-services # cloned from GitHub
|
||||
- https://example.com/private.git@stable
|
||||
- ~/my-services # local, lowest priority
|
||||
```
|
||||
@@ -238,7 +240,7 @@ is the [REST API](../dev/rest-api/index.md) section; these are the config keys.
|
||||
| `api_secret` | str | *(unset)* | Master secret accepted in the `X-Secret-Key` header. |
|
||||
| `users` | dict | `{}` | Per-user API keys and their allowlists (see below). |
|
||||
| `services` | list | *(unset)* | Global service allowlist. Omit to allow all. |
|
||||
| `remote_only` | bool | `false` | Run without a local `output_template` (CORS/Cloudflare-friendly). |
|
||||
| `remote_only` | bool | `false` | Expose only the remote service session endpoints (health, services, search, session) and disable the rest of the REST API. |
|
||||
| `session_ttl` | int (s) | `300` | Lifetime of an interactive auth session. |
|
||||
| `max_sessions` | int | `100` | Maximum concurrent sessions. |
|
||||
| `history_limit` | int | `100` | How many finished jobs to retain in history. |
|
||||
@@ -247,7 +249,6 @@ is the [REST API](../dev/rest-api/index.md) section; these are the config keys.
|
||||
| `allow_job_credentials` | bool | `false` | Permit clients to supply credentials per job. |
|
||||
| `devices` | list | *(auto)* | Widevine devices offered; auto-filled from `directories.wvds`. |
|
||||
| `playready_devices` | list | *(auto)* | PlayReady devices; auto-filled from `directories.prds`. |
|
||||
| `country` / `locations` | str / dict | *(unset)* | Advertised region metadata. |
|
||||
|
||||
Each entry under `users` is keyed by that user's API key and may set its own `services`,
|
||||
`devices`, and `playready_devices` allowlists, narrowing the global ones.
|
||||
@@ -266,9 +267,10 @@ serve:
|
||||
```
|
||||
|
||||
!!! tip "Declaring `dl` defaults under `serve`"
|
||||
You can set any [`dl`](#dl) flag key (`downloads`, `workers`, `best_available`, and so on)
|
||||
directly inside `serve`. The point is to raise concurrency and behaviour defaults
|
||||
**server-wide** (every request the server handles picks them up) without having to change
|
||||
You can set most [`dl`](#dl) flag keys (`downloads`, `workers`, `best_available`, and so on)
|
||||
directly inside `serve`; the server recognises a fixed subset of download parameters, so a
|
||||
few CLI-only flags are ignored here. This raises concurrency and behaviour defaults
|
||||
**server-wide** (every request the server handles picks them up) without changing
|
||||
each client call individually.
|
||||
|
||||
---
|
||||
@@ -299,7 +301,7 @@ after the flag's internal destination rather than its visible name; set these ex
|
||||
| `-o` / `--output` | `output_dir` |
|
||||
| `--cdm-only` / `--vaults-only` | `cdm_only` |
|
||||
|
||||
**Precedence** (highest first): an explicit CLI flag or environment variable → a per-service
|
||||
**Precedence** (highest first): an explicit CLI flag → a per-service
|
||||
[`services.<TAG>.dl`](#services-auth) override → this global `dl:` block → the built-in
|
||||
default. In other words, config only fills in options you did not set on the command line.
|
||||
|
||||
@@ -369,7 +371,7 @@ written as sidecar files. See [Subtitles](../guide/subtitles.md) for the full gu
|
||||
| `convert_before_strip` | bool | `true` | Convert to the working format before stripping SDH. |
|
||||
| `conversion_method` | str | `"auto"` | Subtitle conversion backend. |
|
||||
| `preferred_conversion_method` | str | *(unset)* | Preferred converter when several are available. |
|
||||
| `output_mode` | str | `"mux"` | `mux` embeds subtitles in the MKV; `sidecar` writes separate files. |
|
||||
| `output_mode` | str | `"mux"` | `mux` embeds subtitles in the MKV; `sidecar` writes separate files; `both` writes sidecars and still muxes. |
|
||||
| `sidecar_format` | str | `"srt"` | Format for sidecar files when `output_mode: sidecar`. |
|
||||
| `type_priority` | list | *(unset)* | Ordered ranking of subtitle types (`forced`, `normal`, `sdh`; CC counts as SDH) that sorts the variants within each language. Types you leave out fall to the end. |
|
||||
|
||||
@@ -406,9 +408,9 @@ audio:
|
||||
```
|
||||
|
||||
!!! note "`codec_priority` is a soft priority: nothing is dropped"
|
||||
`codec_priority` only breaks ties **among tracks that share the same bitrate and language**.
|
||||
Codecs not in the list keep their normal bitrate-based ordering and are simply placed after
|
||||
all listed codecs, and none are ever removed. Two higher-level rules still override it: **Atmos
|
||||
`codec_priority` outranks bitrate: any listed codec sorts above every unlisted one, and among
|
||||
listed codecs the list order decides. Bitrate order survives only within a single codec rank.
|
||||
Nothing is ever removed. Two higher-level rules still override it: **Atmos
|
||||
tracks always take precedence over `codec_priority`**, and **audio-description tracks are
|
||||
always forced to the end** regardless of it. When `codec_priority` is unset, tracks sort by
|
||||
bitrate alone, with those same Atmos/descriptive rules still applied.
|
||||
@@ -424,7 +426,7 @@ Matroska (MKV) muxing options.
|
||||
| `set_title` | bool | `true` | Write a human-readable title into the MKV container. |
|
||||
| `default_language` | dict | `{}` | Force which language is flagged *default* per track type, e.g. `{audio: en, subtitle: en}`. |
|
||||
| `merge_audio` | bool | `true` | Merge all audio into one file. `--split-audio` on the CLI flips this off. |
|
||||
| `merge_video` | bool | `false` | Merge all video tracks into one file. `--merge-video` on the CLI flips this on. |
|
||||
| `merge_video` | bool | `false` | Merge video tracks that share height, range, and codec into one file, so only language varies inside a file. `--merge-video` on the CLI flips this on. |
|
||||
|
||||
```yaml
|
||||
muxing:
|
||||
@@ -451,9 +453,6 @@ A rule may test:
|
||||
```yaml
|
||||
language_tags:
|
||||
rules:
|
||||
- audio: [en]
|
||||
subs_contain_all: [en]
|
||||
tag: "" # native English release, no tag
|
||||
- audio: [ja]
|
||||
subs_contain: [en]
|
||||
tag: "SUBBED"
|
||||
@@ -498,7 +497,7 @@ For the full picture of how templates render, see
|
||||
|
||||
### `output_template`
|
||||
|
||||
- **Type:** `dict` · **Default:** `{}`
|
||||
- **Type:** `dict` · **Required** (no usable default; `dl` exits with an error if this is missing)
|
||||
|
||||
Filename templates keyed by media kind, using `{variable}` placeholders. Recognised kinds are
|
||||
`movies`, `series`, and `songs` (and `albums` for folder templates). A trailing `?` on a
|
||||
@@ -627,7 +626,7 @@ case-insensitively; `"mp4decrypt"` selects Bento4's mp4decrypt, and **anything e
|
||||
```yaml
|
||||
decryption:
|
||||
default: shaka
|
||||
SOMESERVICE: mp4decrypt
|
||||
EXAMPLE1: mp4decrypt
|
||||
```
|
||||
|
||||
---
|
||||
@@ -758,8 +757,9 @@ key_vaults:
|
||||
|
||||
!!! tip "Common per-entry options"
|
||||
- `no_push: true` makes a vault read-only (keys are fetched but never written to it).
|
||||
- A vault of `type: api` whose `name` contains `decrypt_labs` auto-fills its `token` from
|
||||
[`decrypt_labs_api_key`](#external-api-keys) when not set inline.
|
||||
- A vault of `type: API` whose `name` contains `decrypt_labs` auto-fills its `token` from
|
||||
[`decrypt_labs_api_key`](#external-api-keys) when not set inline. Vault `type` values are
|
||||
case-sensitive module names.
|
||||
- An all-zero content key (32 zeros) is treated as "no key" everywhere and is never
|
||||
stored.
|
||||
|
||||
@@ -786,9 +786,9 @@ All default to an empty string and enable optional metadata/geolocation features
|
||||
| `ipinfo_api_key` | str | `""` | ipinfo.io API key for IP/region lookups. |
|
||||
|
||||
!!! tip "SIMKL is a fallback for TMDB"
|
||||
SIMKL is positioned as an alternative metadata source, and it is most valuable precisely
|
||||
**when no `tmdb_api_key` is configured**. It improves title-matching and tagging
|
||||
reliability in that case rather than replacing TMDB where TMDB is available.
|
||||
SIMKL is an alternative metadata source. Use it when you have no `tmdb_api_key`
|
||||
configured; it improves title matching and tagging in that case rather than replacing
|
||||
TMDB.
|
||||
|
||||
!!! note "`ipinfo_api_key` never touches your service sessions"
|
||||
The token is only ever sent to `api.ipinfo.io` as a per-request `Authorization` header; it
|
||||
|
||||
Reference in New Issue
Block a user