Monitor ARD Mediathek series for new episodes and download them via yt-dlp
Project description
MediathekWatch
A Python CLI tool to monitor ARD Mediathek, ARTE.tv, and ZDF Mediathek series for new episodes and automatically download them using yt-dlp. State is tracked in a local DuckDB database.
Requirements
Installation
# Clone or navigate to the project
cd /path/to/mediathekwatch
# Install with uv
uv sync
# Or install as editable
uv pip install -e .
Usage
The tool is installed as mediathekwatch command:
Add a series to monitor
mediathekwatch add "https://www.ardmediathek.de/serie/feuer-und-flamme/staffel-11/Y3JpZDovL3dkci5kZS9mZXVlcnVuZGZsYW1tZQ/11" --name "Feuer und Flamme"
ZDF Mediathek URLs are also supported:
mediathekwatch add "https://www.zdf.de/serien/die-anstalt" --name "Die Anstalt"
Assign to a group (see Groups):
mediathekwatch add "https://www.ardmediathek.de/serie/..." --name "My Show" --group "TVShows"
List monitored series
mediathekwatch list
Check for new episodes (intended for cron)
mediathekwatch check --target /mnt/media/TVShows
# Silent mode (suppress all output)
mediathekwatch check --target /mnt/media/TVShows --silent
When groups are configured, each group downloads to its own target folder and --target is not allowed:
mediathekwatch check --silent
Force redownload of a specific episode
# By series ID
mediathekwatch redownload 1 11 5 --target /mnt/media/TVShows
# By series name
mediathekwatch redownload "Feuer und Flamme" 11 5 --target /mnt/media/TVShows
If --target is omitted, the episode downloads to the series' group folder.
Download all episodes from a series URL
mediathekwatch download "https://www.ardmediathek.de/serie/feuer-und-flamme/staffel-11/Y3JpZDovL3dkci5kZS9mZXVlcnVuZGZsYW1tZQ/11" --target /mnt/media/TVShows
Works with ZDF Mediathek too:
mediathekwatch download "https://www.zdf.de/serien/die-anstalt" --target /mnt/media/TVShows
Remove a series
# By ID
mediathekwatch remove 1
# By name
mediathekwatch remove "Feuer und Flamme"
Groups
Groups let you organize series into separate download destinations. Each group has its own target folder. When any non-default group exists, check uses group folders instead of --target.
Create a group
mediathekwatch group create "TVShows" --target /mnt/media/TVShows
List groups
mediathekwatch group list
Update a group
mediathekwatch group update "TVShows" --name "TV Shows" --target /mnt/media/TV
Delete a group
mediathekwatch group delete "TVShows"
Move a series to a group
mediathekwatch set-group "Feuer und Flamme" "TVShows"
Global Options
--db PATH— Path to DuckDB database (default:~/.config/mediathekwatch/mediathekwatch.db)--target PATH— Target folder for downloads (default: current directory)
Cron Setup
Add to your crontab (e.g., every 6 hours):
0 */6 * * * /path/to/uv run mediathekwatch check --target /mnt/media/TVShows
Or if installed globally:
0 */6 * * * /home/user/.local/bin/mediathekwatch check --target /mnt/media/TVShows
Filename Format
Downloaded episodes are organized as:
<Target Folder>/<Series Name>/S<Season>/<Series> - S<season>E<episode> - <episode name>.mkv
Example:
/mnt/media/TVShows/Feuer und Flamme/S11/Feuer und Flamme - S11E05 - Der neue Fall.mkv
Database Schema
Three tables are maintained in DuckDB:
groups— download groups with target foldersmonitored_series— series being trackeddownloaded_episodes— episodes already downloaded
Project Structure
src/mediathekwatch/
├── __init__.py # Package init
├── main.py # CLI entry point
├── cli.py # Command handlers
├── models.py # Episode/Series dataclasses
├── database.py # DuckDB interface
├── api/ # API clients (ARD, ARTE, ZDF)
└── download.py # yt-dlp wrapper & filename utils
Notes
- The tool queries ARD Mediathek, ARTE.tv EMAC, and ZDF GraphQL APIs to discover episodes.
- yt-dlp is invoked with flags for embedding thumbnails, subtitles, metadata, chapters, and info-json.
- Episodes are skipped if they already exist in the
downloaded_episodestable; useredownloadto override.
Acknowledgments
- Thanks to the MediathekView project for providing valuable insights into the structure of German public media APIs.
Development
# Run tests
uv run pytest
# Type check
uv run pyright
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mediathekwatch-0.1.1.tar.gz.
File metadata
- Download URL: mediathekwatch-0.1.1.tar.gz
- Upload date:
- Size: 76.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a367d51968daeb9bdc1ee3ca230cfdbd1d5a4874e6153d7c8d502aab74257435
|
|
| MD5 |
a6731ab1254b68e9ddab343bdd901f9a
|
|
| BLAKE2b-256 |
c78e651522810bda74cd39be878dc104167b190331d012c0a5ed607d7fe15c25
|
File details
Details for the file mediathekwatch-0.1.1-py3-none-any.whl.
File metadata
- Download URL: mediathekwatch-0.1.1-py3-none-any.whl
- Upload date:
- Size: 24.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e50074e2852c115ec6fad30379754a7cdb75c6924575014230285327c600d418
|
|
| MD5 |
027d8f729f67a6abc325326b35b6effe
|
|
| BLAKE2b-256 |
cbf2589a25d695de965c412dc16d95d02e1deccdf8e36a1aee2b3186748423a2
|