data/ was added to .gitignore only after its contents had already been committed, and an ignore rule never untracks existing files. The live SQLite database therefore showed up as modified on every commit, made accidental commits of user history likely, and bloated the repo with binary churn. Claude-Session: https://claude.ai/code/session_01QkiLqAtFamcbFXDnCtZSPm
Rezept0r
Self-hosted Rezept-Extraktor fuer Webseiten und Videos mit Import nach Tandoor Recipes.
Optimiert fuer den Betrieb auf einem Raspberry Pi 3 (512 MB Container-Limit, 1 Worker).
Features
- Website-Extraktion -- Rezepte von beliebigen Kochseiten (Chefkoch, Lecker, BBC Good Food, etc.)
- Video-Extraktion -- YouTube, TikTok, Instagram Reels, Vimeo, Reddit, Twitter/X
- 3-stufige Website-Analyse:
recipe-scrapers-> LD+JSON / Schema.org -> GPT-4o-mini Fallback - 4-stufige Video-Analyse: yt-dlp Metadaten -> Caption-Check -> Audio-Download -> Whisper-Transkription -> GPT-4o-mini
- Naehrwert-Berechnung: Bereits extrahiert -> USDA FoodData Central -> GPT-4o-mini Schaetzung
- Tandoor-Import per Klick (REST API + Bild-Upload)
- Rezept-Verlauf in lokaler SQLite-Datenbank
- Echtzeit-Fortschritt via Server-Sent Events (SSE)
Unterstuetzte Plattformen
| Typ | Quellen |
|---|---|
| Video | YouTube, TikTok, Instagram Reels, Vimeo, Twitch, Twitter/X, Facebook, Reddit |
| Website | Alle Seiten mit Rezept-Schema (Schema.org), sowie beliebige Artikel per KI-Extraktion |
Voraussetzungen
- Docker und Docker Compose
- OpenAI API-Key (fuer Whisper-Transkription und GPT-4o-mini)
- Optional: Tandoor-Instanz mit API-Token
- Optional: USDA FoodData Central API-Key
Installation
1. Repository klonen
git clone <repo-url>
cd Rezept0r
2. Umgebungsvariablen konfigurieren
.env-Datei im Projektroot erstellen:
OPENAI_API_KEY=sk-...
USDA_API_KEY=DEMO_KEY
TANDOOR_BASE_URL=http://tandoor:8080
TANDOOR_API_TOKEN=tda_...
| Variable | Pflicht | Beschreibung |
|---|---|---|
OPENAI_API_KEY |
Ja | OpenAI API-Key fuer Whisper + GPT-4o-mini |
USDA_API_KEY |
Nein | USDA FoodData Central Key (Standard: DEMO_KEY) |
TANDOOR_BASE_URL |
Nein | URL der Tandoor-Instanz |
TANDOOR_API_TOKEN |
Nein | Tandoor Bearer-Token |
TMP_DIR |
Nein | Verzeichnis fuer temporaere Audio-Dateien (Standard: tmp, also <Projekt>/tmp bzw. im Container /app/tmp) |
FFMPEG_LOCATION |
Nein | Pfad zu ffmpeg (nur fuer lokale Windows-Entwicklung) |
Bilder und Verlauf-DB liegen immer fest unter <Projekt>/data bzw. im Container unter /app/data:
- Bilder:
data/images - SQLite:
data/history.db
3. Starten
docker compose up -d --build
Die App ist unter http://localhost:88 erreichbar.
Logs anzeigen
docker compose logs -f
Lokale Entwicklung (ohne Docker)
python -m venv .venv
source .venv/Scripts/activate # Windows
# source .venv/bin/activate # Linux/Mac
pip install -r requirements.txt
uvicorn main:app --reload --host 0.0.0.0 --port 8000
Zusaetzlich muss yt-dlp und ffmpeg lokal installiert sein fuer Video-Extraktion.
Architektur
Browser
|
| GET /api/extract/stream?url=... (SSE)
v
FastAPI (uvicorn, 1 Worker)
|
+-- Plattform-Erkennung (URL-Regex)
| |
| +-- Website? --> recipe-scrapers -> LD+JSON -> GPT-4o-mini
| +-- Video? --> yt-dlp Metadaten -> Caption-Check -> Audio/Whisper -> GPT-4o-mini
|
+-- Naehrwert-Anreicherung (USDA / GPT-4o-mini)
+-- SQLite-Verlauf speichern
+-- ExtractResponse an Browser (SSE event: result)
|
| POST /api/import (nach Klick auf "Importieren")
v
Tandoor REST API
Dateistruktur
main.py FastAPI-App, Routen, Health-Check
app/
config.py Pydantic-Settings aus .env
models.py Alle Pydantic-Schemas (Recipe, Tandoor*, SSE-Events)
api/
extract.py GET /api/extract/stream (SSE-Endpoint)
tandoor.py POST /api/import
history.py GET /api/history, DELETE /api/history/{id}
extractors/
base.py URL-Plattformerkennung (Video vs. Website)
website.py 3-stufige Website-Extraktion
video.py 4-stufige Video-Extraktion (yt-dlp + Whisper)
services/
openai_service.py Whisper-Transkription + GPT-4o-mini Extraktion
nutrition.py 3-stufige Naehrwert-Berechnung
tandoor_service.py Tandoor REST-Client + Bild-Upload
history_service.py SQLite-Verlauf (CRUD)
static/
index.html SPA-Frontend
style.css Styling
app.js Frontend-Logik (SSE, UI)
API-Endpunkte
| Methode | Pfad | Beschreibung |
|---|---|---|
GET |
/ |
Frontend (SPA) |
GET |
/api/extract/stream?url=... |
Rezept extrahieren (SSE-Stream) |
POST |
/api/import |
Rezept nach Tandoor importieren |
GET |
/api/history |
Extraktions-Verlauf abrufen |
DELETE |
/api/history/{id} |
Verlaufseintrag loeschen |
GET |
/api/health |
Health-Check |
SSE-Events
Der Extraktions-Endpoint streamt drei Event-Typen:
status-- Fortschrittsupdates (stage,message,progress0-100)result-- Fertiges Rezept als JSON (ExtractResponse)error-- Fehlermeldung
Bekannte Probleme & Loesungen
TikTok: Verbindung verweigert im Docker-Container (Pi-hole)
Wenn Pi-hole als DNS-Server im Heimnetzwerk laeuft, kann der Docker-Container TikTok-Domains nicht aufloesen — Pi-hole gibt eine Sinkhole-IP zurueck, die Verbindung wird sofort verweigert. Ausserhalb des Containers funktioniert TikTok normal, weil der Pi-Host einen anderen DNS-Pfad nutzt.
Loesung: In docker-compose.yml einen oeffentlichen DNS-Server eintragen:
services:
rezeptor:
dns:
- 1.1.1.1
- 8.8.8.8
Danach docker compose up -d (kein Rebuild noetig).
Technische Hinweise
- yt-dlp wird immer als Subprocess aufgerufen (
subprocess.runvialoop.run_in_executor()), nie ueber die Python-API, um den Event-Loop nicht zu blockieren - Whisper hat ein Dateigroessen-Limit von 25 MB -- zu lange Videos fuehren zu einem Fehler
- recipe-scrapers laedt HTML selbststaendig -- es wird die URL uebergeben, nicht vorgeladenes HTML
- Bild-Upload nach Tandoor erfolgt per
PATCHmit Multipart -- derContent-Type-Header wird nicht manuell gesetzt - SSE-Header
X-Accel-Buffering: noist gesetzt fuer Nginx-Proxy-Kompatibilitaet - Container laeuft mit 512 MB Memory-Limit und ohne Swap (SD-Karten-Schutz)
Lizenz
Privates Projekt.