diff --git a/docs/dev/rest-api/endpoints.md b/docs/dev/rest-api/endpoints.md index 4a205505..206f7532 100644 --- a/docs/dev/rest-api/endpoints.md +++ b/docs/dev/rest-api/endpoints.md @@ -384,7 +384,8 @@ Create a download job. Requires `service` and `title_id`; every other field is a | `best_available` | boolean | `false` | Fall back to best available. | | `repack` | boolean | `false` | Add REPACK tag. | | `tag` | string | `null` | Release group tag. | -| `tmdb_id` / `imdb_id` / `animeapi_id` | - | `null` | External ID overrides for tagging. | +| `tmdb_id` / `imdb_id` / `tvdb_id` / `animeapi_id` | - | `null` | External ID overrides for tagging. | +| `tvdb_order` | `official`, `dvd`, `absolute`, `alternate`, `regional` | `null` | Renumber episodes to a TVDB season order. Falls back to the `tvdb_order` config option. | | `enrich` | boolean | `false` | Override title/year from external source. | | `output_dir` | string | `null` | Override output directory. | | `no_cache` / `reset_cache` | boolean | `false` | Title cache controls. | diff --git a/docs/getting-started/configuration-file.md b/docs/getting-started/configuration-file.md index 4111bb8e..6196aa80 100644 --- a/docs/getting-started/configuration-file.md +++ b/docs/getting-started/configuration-file.md @@ -85,7 +85,7 @@ The top-level keys group loosely into these areas: | Key vaults | `key_vaults`, `vault_timeout` | | Proxies & remote | `proxy_providers`, `remote_services`, `serve`, `services` | | Naming & tagging | `tag`, `output_template`, `chapter_fallback_name` | -| External API keys | `tmdb_api_key`, `simkl_client_id`, `ipinfo_api_key` | +| External API keys | `tmdb_api_key`, `tvdb_api_key`, `simkl_client_id`, `ipinfo_api_key`, `metadata_providers` | | Behavior & logging | `update_checks`, `redact_paths`, `debug`, `unicode_filenames` | | Paths | `directories`, `filenames` | @@ -125,7 +125,7 @@ services: !!! tip "A few keys are named after the flag's internal name" Most keys are obvious, but set these exact ones: `range` (`-r`), `list` (`--list`), - `tmdb_id` (`--tmdb`), `imdb_id` (`--imdb`), `no_atmos` (`--noatmos`), and `output_dir` + `tmdb_id` (`--tmdb`), `imdb_id` (`--imdb`), `tvdb_id` (`--tvdb`), `no_atmos` (`--noatmos`), and `output_dir` (`-o`). The [Configuration Reference](../reference/configuration.md#dl) has the full list and every available key. diff --git a/docs/getting-started/quickstart.md b/docs/getting-started/quickstart.md index f4b75cf9..c645eeec 100644 --- a/docs/getting-started/quickstart.md +++ b/docs/getting-started/quickstart.md @@ -219,7 +219,7 @@ unshackle dl -q 1080 -o /mnt/media/incoming EXAMPLE 81234567 - 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`. -- unshackle builds the filename from your `output_template` and adds IMDb/TMDB IDs to +- unshackle builds the filename from your `output_template` and adds IMDb/TMDB/TVDB IDs to the file's metadata tags when available. To change the default output location permanently, set it in your config: diff --git a/docs/guide/cli-reference.md b/docs/guide/cli-reference.md index c5c995af..a5d1daec 100644 --- a/docs/guide/cli-reference.md +++ b/docs/guide/cli-reference.md @@ -145,8 +145,22 @@ Keep only certain track types, or skip certain track types. Attachments are alwa |---|---| | `--tmdb` | TMDB ID (integer). | | `--imdb` | IMDb ID, e.g. `tt1375666`. | -| `--animeapi` | AnimeAPI ID, e.g. `mal:12345` or `anilist:98765` (defaults to MAL). Back-fills TMDB/IMDb. | +| `--tvdb` | TVDB ID (integer). Skips the series lookup that `--tvdb-order` would otherwise do. | +| `--animeapi` | AnimeAPI ID, e.g. `mal:12345` or `anilist:98765` (defaults to MAL). Back-fills TMDB/IMDb/TVDB. | | `--enrich` | Override show title/year from the external source. **Requires** one of `--tmdb`, `--imdb`, or `--animeapi`. | +| `--tvdb-order` | Renumber episodes to a TVDB season order: `official` (aired), `dvd`, `absolute`, `alternate`, or `regional`. Needs `tvdb_api_key`. | + +#### Episode ordering + +A service does not always number a series the way TVDB's aired order does. Some services list +Futurama in TVDB's `alternate` (Streaming) order, for example. `--tvdb-order` works out which +order the service used, then renumbers the episodes into the order you asked for. + +!!! note "Orders that do not cover the whole series" + An order can omit episodes the service carries; TVDB's `dvd` order for Futurama leaves out + the four movies. Those episodes keep their original numbering. If that would give two + episodes the same season/episode slot, and so the same filename, unshackle logs an error + and keeps the service's numbering unchanged. Pick an order that covers the whole series. ### DRM, keys & decryption diff --git a/docs/guide/downloading.md b/docs/guide/downloading.md index 6606a9a3..11d26828 100644 --- a/docs/guide/downloading.md +++ b/docs/guide/downloading.md @@ -519,13 +519,35 @@ tagging and naming: | --- | --- | --- | | `--tmdb` | `--tmdb 27205` | Use this TMDB ID instead of automatic lookup. | | `--imdb` | `--imdb tt1375666` | Use this IMDb ID. | +| `--tvdb` | `--tvdb 73871` | Use this TVDB ID instead of looking the series up. | | `--animeapi` | `--animeapi mal:12345` | Resolve via AnimeAPI (`mal:`/`anilist:` prefix; defaults to MAL). | | `--enrich` | - | Override the show title and year from an external source. **Requires** one of `--tmdb`, `--imdb`, or `--animeapi`. | +| `--tvdb-order` | `--tvdb-order dvd` | Renumber episodes to a TVDB season order. Needs `tvdb_api_key`. | ```shell title="Force the right IMDb match and enrich the title" unshackle dl --imdb tt1375666 --enrich EXAMPLE 81234567 ``` +### Episode ordering + +A service does not always number a series the way TVDB's aired order does. Some services list +Futurama in TVDB's `alternate` (Streaming) order, for example, while TVDB's `official` order +holds back four season-one episodes to the start of season two. `--tvdb-order` works out which +order the service used, then renumbers the episodes into the order you asked for: + +```shell title="Download Futurama in DVD order" +unshackle dl --tvdb-order dvd EXAMPLE 81234567 +``` + +Available orders are `official` (aired), `dvd`, `absolute`, `alternate`, and `regional`. Set +`tvdb_order` in your config to apply one by default. + +!!! warning "Orders that do not cover the whole series" + An order can leave out episodes the service carries. TVDB's `dvd` order does not list + Futurama's four movies. Those episodes keep their original numbering. If that would give + two episodes the same season/episode slot, and so the same filename, unshackle logs an + error and leaves the numbering untouched. Pick an order that covers the whole series. + ## Configuration defaults Every flag on this page can be set as a default in your configuration file so you don't @@ -571,4 +593,5 @@ authoritative list. | `--list` / `--list-titles` / `--skip-dl` | | Dry runs. | | `--cdm-only` / `--vaults-only` | | Key source control. | | `--export` | | Export track info and keys to JSON. | -| `--tmdb` / `--imdb` / `--animeapi` / `--enrich` | | Metadata overrides. | +| `--tmdb` / `--imdb` / `--tvdb` / `--animeapi` / `--enrich` | | Metadata overrides. | +| `--tvdb-order` | | Renumber episodes to a TVDB season order. | diff --git a/docs/guide/output-and-naming.md b/docs/guide/output-and-naming.md index 1019f124..5b8b1647 100644 --- a/docs/guide/output-and-naming.md +++ b/docs/guide/output-and-naming.md @@ -245,7 +245,11 @@ tag_imdb_tmdb: true |---|---|---|---| | `tag` | str | `""` | The release-group tag used for `{tag}`. | | `tag_group_name` | bool | `true` | Write the group name (`config.tag`) into the MKV `Group` metadata tag. | -| `tag_imdb_tmdb` | bool | `true` | Look up and embed IMDb / TMDB / TVDB external-ID tags in the MKV metadata (uses `tmdb_api_key` / `simkl_client_id` when available). | +| `tag_imdb_tmdb` | bool | `true` | Look up and embed IMDb / TMDB / TVDB external-ID tags in the MKV metadata (uses `tmdb_api_key` / `tvdb_api_key` / `simkl_client_id` when available). | + +The IDs are written as the Matroska `IMDB`, `TMDB`, and `TVDB2` tags. `TVDB2` values carry the +entity prefix the [Matroska tagging spec](https://www.matroska.org/technical/tagging.html) +requires: `series/73871` for a show, `movies/113` for a film. You can override the tag per run without editing config: diff --git a/docs/reference/configuration.md b/docs/reference/configuration.md index 45a00d26..4d9015f5 100644 --- a/docs/reference/configuration.md +++ b/docs/reference/configuration.md @@ -39,7 +39,7 @@ This page assumes you already know the basics and want precise details. | [DRM & CDM](#drm-cdm) | `cdm`, `remote_cdm`, `decryption` | | [Network & proxy](#network-proxy) | `network`, `headers`, `proxy_providers` | | [Key vaults](#key-vaults) | `key_vaults`, `vault_timeout` | -| [External API keys](#external-api-keys) | `imdb_api_enabled`, `omdb_api_key`, `tmdb_api_key`, `simkl_client_id`, `decrypt_labs_api_key`, `ipinfo_api_key` | +| [External API keys](#external-api-keys) | `imdb_api_enabled`, `omdb_api_key`, `tmdb_api_key`, `tvdb_api_key`, `tvdb_pin`, `tvdb_order`, `simkl_client_id`, `metadata_providers`, `decrypt_labs_api_key`, `ipinfo_api_key` | | [Caching & updates](#caching-updates) | `title_cache_enabled`, `title_cache_time`, `title_cache_max_retention`, `update_checks`, `update_check_interval` | | [Logging, privacy & debug](#logging-privacy-debug) | `redact_paths`, `debug`, `debug_keys`, `debug_requests`, `set_terminal_bg` | | [Deprecated & removed](#deprecated-removed-keys) | `curl_impersonate`, `downloader`, `scene_naming` | @@ -784,13 +784,31 @@ All default to an empty string and enable optional metadata/geolocation features | `omdb_api_key` | str | `""` | [OMDb](https://www.omdbapi.com/) API key for IMDb metadata lookups; a more reliable alternative to IMDxAPI. Free keys are available on the OMDb site. | | `tmdb_api_key` | str | `""` | TMDB API key for metadata enrichment and external-ID tags. | | `simkl_client_id` | str | `""` | SIMKL client ID for metadata lookups; an alternative/fallback source to TMDB. | +| `tvdb_api_key` | str | `""` | [TheTVDB v4](https://thetvdb.com/api-information) API key; a fallback source to TMDB, strongest on TV series. Free keys are available on the TVDB site. | +| `tvdb_pin` | str | `""` | Subscriber PIN, only needed for a user-supported TVDB key. Leave empty for a normal project key. | +| `tvdb_order` | str | `""` | Default for `--tvdb-order`: renumber episodes to a TVDB season order (`official`, `dvd`, `absolute`, `alternate`, `regional`). Empty keeps the numbering the service gives. | +| `metadata_providers` | list | *(see below)* | Metadata providers to use, in the order they are tried. | | `decrypt_labs_api_key` | str | `""` | Global Decrypt Labs API key (used by remote CDM / vault). | | `ipinfo_api_key` | str | `""` | ipinfo.io API key for IP/region lookups. | -!!! tip "SIMKL is a fallback for TMDB" - 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. +!!! tip "Choosing and ordering metadata providers" + A lookup goes to each provider in turn and stops at the first good match, so the order + decides which source wins. `metadata_providers` sets that order: + + ```yaml + metadata_providers: [tvdb, tmdb, simkl] + ``` + + Names not in the list are never used, so this both orders and filters. Unknown names are + ignored with a warning. Leave it unset for the default order: + + ```yaml + metadata_providers: [imdbapi, omdb, simkl, tmdb, tvdb] + ``` + + A provider is skipped when its API key is missing, whatever the order. Available names are + `imdbapi`, `omdb`, `simkl`, `tmdb`, and `tvdb`. Put `tvdb` first to make TheTVDB your + primary source; leave it last to use it only as a fallback for 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 @@ -907,6 +925,7 @@ proxy_providers: omdb_api_key: "your-omdb-key" tmdb_api_key: "your-tmdb-key" +tvdb_api_key: "your-tvdb-key" title_cache_time: 3600 redact_paths: true ```