-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture
TheMRX13 edited this page Jul 3, 2026
·
4 revisions
🌐 English · Deutsch
src/mediaforge/
├── __main__.py / entry.py # Entry point: always launches the WebUI
├── arguments.py # CLI flags (-wP, -wH, -wN, -d)
├── config.py # Global config, HTTP session, language/URL patterns
├── env.py # Legacy .env merge (only if the file exists)
├── logger.py # Logging setup
├── autodeps.py # Auto-download of dependencies (Chromium, mpv, …)
├── providers.py # Source registry (AniWorld, SerienStream, FilmPalast)
├── search.py # Search + browse lists (new/popular anime & series)
├── extractors/
│ └── provider/ # One module per video host (voe.py, vidoza.py, …)
├── models/
│ ├── aniworld_to/ # Series / Season / Episode for aniworld.to
│ ├── s_to/ # Series / Season / Episode for s.to
│ ├── filmpalast_to/ # Episode (movie) for filmpalast.to
│ └── common/ # Download logic: yt-dlp + FFmpeg, progress
├── playwright/
│ └── captcha.py # Captcha detection & interactive solving (Patchright Chromium)
├── anime4k/ # Upscaling (mpv/libplacebo) + bundled GLSL shaders
└── web/
├── app.py # Flask app: all routes, workers, create_app()
├── auth.py # Login, setup, OIDC, user management, rate limit
├── db.py # SQLite access, schema, settings (incl. encryption)
├── notifications.py # Web Push, Telegram, Discord, Pushover, ntfy, WhatsApp
├── transcoder.py # HLS live transcoding for the browser player
├── library_watcher.py # watchdog-based library monitoring
├── templates/ # Jinja2 templates (one file per page)
├── static/ # CSS/JS (one CSS/JS file per page) + PWA assets
└── translations/ # Flask-Babel (de)
-
mediaforge→entry.mediaforge(): terminal title,ensure_patchright_chromium()(downloads Chromium if needed), argument parsing. -
start_web_ui()→create_app():- Database initialisation (all tables, migrations)
- Setup token generation if no admin exists
- One-time
.env→ DB migration, then sync of all DB settings intoos.environ - DNS patch according to the stored setting
- Start of the background workers (see below)
- Production server: Waitress (16 threads) with clean signal handling (Ctrl+C kills running FFmpeg/Chromium subprocesses); Flask dev server in debug mode.
| Worker | Task | Cadence |
|---|---|---|
| Queue worker | Process downloads sequentially (with watchdog) | poll 3 s |
| AutoSync worker | Run due sync jobs | poll 10 s |
| Upscale worker | Process Anime4K jobs | poll 4 s |
| Browse prefetch | Warm browse lists, posters and TMDB data | every 15 min |
| Update checker | Check GitHub releases / models branch | every 24 h |
| MediaScan scheduler | Reload Plex/Jellyfin inventory | every 24 h |
| TMDB keyword sync | Download keyword export for advanced search | checked hourly |
| TMDB cache eviction | Delete expired cache entries | hourly |
| Calendar watcher | Cache TMDB schedule data for AutoSync/Seerr/Library titles (bilingual) into calendar_media/calendar_episodes
|
poll 10 s, 1 title/cycle |
| Library watcher | Filesystem events → targeted rescans | event-driven |
All workers are started idempotently via _ensure_* functions; in Flask debug mode only in the reloader child process (prevents duplicate downloads).
Three layers, merged by create_app() at startup:
-
DB (
app_settings) — the authoritative source, written by the UI (sensitive keys encrypted, see Database). -
os.environ— populated from the DB at startup (_sync_db_settings_to_env); lets older code useos.environ.get("MEDIAFORGE_*")everywhere. -
Legacy
.env— only imported once (_migrate_dotenv_to_db, guarded by theenv_migratedflag).
-
niquests with a thread-local session pool (
GLOBAL_SESSION), default DNS via DoH (Google), switchable per setting (rebuild_global_session). - curl_cffi (Chrome impersonation) as fallback/complement when resolving host redirects (Cloudflare bypass).
- Availability detection:
is_source_unavailable()recognises 404/410/451 plus typical "video removed" markers in the HTML.
- Auth decorator wrapping: all routes except auth/static/v1 API automatically get
login_required; a defined list (_admin_only) getsadmin_required. - CSRF: forms via Flask-WTF; JSON APIs are exempt but
Content-Type: application/jsonis enforced for POST/PUT/DELETE. - SSRF protection: user-configured server URLs (Jellyfin/Plex/Seerr) are validated against cloud metadata endpoints and link-local networks.
- Security headers incl. CSP on every response.
UI (/api/download) ──> download_queue (SQLite)
│ claim_next_queued()
▼
queue worker
│ resolve_provider(url) → episode class
▼
episode.download()
│ provider_data → extractor (e.g. VOE) → direct link
│ captcha if needed (playwright/captcha.py, interactive via UI)
▼
yt-dlp + FFmpeg → .mkv according to naming template
│
▼
status (completed/partial/failed) → notifications → Plex/Jellyfin refresh
→ optional upscale queue
🇬🇧 English
Users
- Installation
- Getting Started
- Migration from AniWorld
- Configuration
- Web UI
- Download System
- Download History
- AutoSync
- Calendar
- Library
- Authentication
- Notifications
- Integrations
- SyncPlay
- Anime4K Upscaling
- Encoding
- Docker
- Supported Sites
Developers