|
|
||
|---|---|---|
| .bg-shell | ||
| app | ||
| data | ||
| plans | ||
| * | ||
| .codex | ||
| .env.example | ||
| .gitignore | ||
| .node-version | ||
| appctl.sh | ||
| CHANGES.md | ||
| copy_random.sh | ||
| docker-compose.yml | ||
| Dockerfile | ||
| jellyfin-vector-search-v1.1.tar.gz | ||
| jellyfin-vector-search-v1.2.tar.gz | ||
| Modelfile | ||
| openapi.yaml | ||
| README.md | ||
| requirements.txt | ||
🎬 Jellyfin Vector Search
Semantische Filmsuche für deine Jellyfin-Sammlung. Durchsuche deine Filme mit natürlicher Sprache – „ein netter Familienfilm mit Pferden" – und erhalte passende Ergebnisse mit direktem Jellyfin-Link.
Features
- Natürlichsprachliche Suche – beschreibe was du sehen willst
- Stimmungs-Filter – optional die gewünschte Stimmung angeben
- Benutzerprofile mit FSK – Kinder sehen nur altersgerechte Filme
- PIN-Schutz – für Profile mit höherer Altersfreigabe
- Ähnliche Filme – klicke einen Film an für Empfehlungen
- Jellyfin-Integration – direkter "In Jellyfin öffnen"-Link
- Dark Mode – schickes dunkles Design
- Responsive – funktioniert auf Handy, Tablet & Desktop
Architektur
ollama-net db-net
├── ollama-server:11434 ←→ ├── chromadb:8000
│ (LLM + Embeddings) │ (Vektordatenbank)
│ │
└── filmsuche:42000 ─────────────┘
(Python/FastAPI)
├── liest /media/filme/*.nfo
└── verlinkt auf Jellyfin (HTTPS)
Voraussetzungen
- Ollama läuft im Docker-Netzwerk
ollama-net - ChromaDB läuft im Docker-Netzwerk
db-net - Jellyfin ist via HTTPS erreichbar
- Embedding-Modell in Ollama geladen:
docker exec ollama-server ollama pull nomic-embed-text
ChromaDB (falls noch nicht vorhanden)
# chromadb/docker-compose.yml
version: "3.8"
services:
chromadb:
image: chromadb/chroma
container_name: chromadb
restart: unless-stopped
ports:
- "42010:8000"
volumes:
- CHANGE_TO_COMPOSE_DATA_PATH/42_chromadb/data:/chroma/chroma
networks:
- db-net
networks:
db-net:
external: true
Setup
1. docker-compose.yml anpassen
Drei Stellen in docker-compose.yml müssen angepasst werden:
volumes:
- CHANGE_TO_COMPOSE_DATA_PATH/42_filmsuche/data:/app/data
- /pfad/zu/jellyfin/filme:/media/filme:ro # ← Pfad zu deinen NFO-Dateien
environment:
- JELLYFIN_URL=https://dein-jellyfin.example.com # ← Deine Jellyfin-URL
- JELLYFIN_API_KEY=DEIN_API_KEY_HIER # ← Dein API-Key
2. Jellyfin API-Key erstellen
- Jellyfin → Dashboard → API-Schlüssel
- Neuen Schlüssel erstellen (Name: "Filmsuche")
- Den Key in
docker-compose.ymleintragen
3. Netzwerke erstellen (falls noch nicht vorhanden)
docker network create ollama-net
docker network create db-net
4. Starten
cd filmsuche
docker compose up -d --build
5. Filme indexieren
- Öffne
http://dein-server:42000 - Klicke unten auf ⚙️ Verwaltung
- Prüfe ob Ollama (🟢) und ChromaDB (🟢) verbunden sind
- Klicke 🔄 Filme neu indexieren
- Warte bis alle Filme verarbeitet sind (~2-5 Min. für 1500 Filme)
6. Suchen!
Wähle ein Profil, optional eine Stimmung, und beschreibe deinen Wunschfilm.
Umgebungsvariablen
Basis
| Variable | Standard | Beschreibung |
|---|---|---|
OLLAMA_URL |
http://ollama-server:11434 |
Ollama API |
CHROMA_URL |
http://chromadb:8000 |
ChromaDB API |
JELLYFIN_URL |
http://localhost:8096 |
Jellyfin URL (wie du sie im Browser öffnest) |
JELLYFIN_API_KEY |
– | Jellyfin API-Schlüssel |
COLLECTION_NAME |
filmsuche |
ChromaDB Collection-Name |
EMBEDDING_MODEL |
nomic-embed-text |
Ollama Embedding-Modell |
NFO_PATH |
/media/filme |
Pfad zu den NFO-Dateien im Container |
OIDC / Authentik (optional)
| Variable | Standard | Beschreibung |
|---|---|---|
OIDC_ISSUER |
– | Authentik OIDC-Issuer-URL |
OIDC_CLIENT_ID |
– | OAuth2 Client-ID |
OIDC_CLIENT_SECRET |
– | OAuth2 Client-Secret |
OIDC_REDIRECT_URI |
– | Callback-URL (z.B. https://filmsuche.example.com/auth/callback) |
OIDC_SCOPES |
openid profile email groups |
Angeforderte Scopes |
OIDC_LOGOUT_URL |
– | Optional: Logout-URL (sonst aus Discovery) |
OIDC_DEFAULT_FSK |
0 |
FSK wenn User keiner fsk-Gruppe zugeordnet |
OIDC_ADMIN_GROUP |
filmsuche-admin |
Authentik-Gruppe für Admin-Zugriff |
SECRET_KEY |
change-me... |
Unbedingt ändern! Signatur für Session-Cookies |
SESSION_MAX_AGE |
86400 |
Session-Dauer in Sekunden (24h) |
Wenn OIDC_ISSUER, OIDC_CLIENT_ID und OIDC_CLIENT_SECRET alle gesetzt sind, ist OIDC aktiv. Sonst werden lokale Profile verwendet.
Authentik einrichten
1. Application & Provider in Authentik erstellen
-
Authentik Admin → Applications → Providers → Create
- Typ: OAuth2/OpenID Provider
- Name:
Jellyfin Vector Search - Authorization flow:
default-provider-authorization-implicit-consent(oder mit Consent) - Client ID: wird automatisch generiert → kopieren
- Client Secret: wird automatisch generiert → kopieren
- Redirect URIs:
https://filmsuche.example.com/auth/callback - Scopes:
openid,profile,email,groups(Signing Key auswählen!)
-
Authentik Admin → Applications → Create
- Name:
Jellyfin Vector Search - Slug:
jellyfin-vector-search - Provider: den eben erstellten auswählen
- Name:
2. Gruppen für FSK anlegen
In Authentik unter Directory → Groups folgende Gruppen erstellen und Benutzer zuordnen:
| Gruppe | Wirkung |
|---|---|
fsk-0 |
Nur FSK 0 Filme |
fsk-6 |
Bis FSK 6 |
fsk-12 |
Bis FSK 12 |
fsk-16 |
Bis FSK 16 |
fsk-18 |
Alle Filme |
filmsuche-admin |
Darf indexieren und Profile verwalten |
Ein User bekommt die höchste FSK-Stufe aus allen seinen Gruppen. Ohne fsk-Gruppe → OIDC_DEFAULT_FSK (Standard: 0).
3. OIDC-Issuer-URL
Die Issuer-URL für Authentik hat das Format:
https://auth.example.com/application/o/jellyfin-vector-search/
(wobei jellyfin-vector-search der Slug der Application ist)
4. Umgebungsvariablen setzen
- OIDC_ISSUER=https://auth.example.com/application/o/jellyfin-vector-search/
- OIDC_CLIENT_ID=<deine-client-id>
- OIDC_CLIENT_SECRET=<dein-client-secret>
- OIDC_REDIRECT_URI=https://filmsuche.example.com/auth/callback
- SECRET_KEY=<openssl rand -hex 32>
Profile (lokal)
Lokale Profile sind der Fallback wenn OIDC nicht konfiguriert oder nicht erreichbar ist.
Beim ersten Start werden drei Standard-Profile erstellt:
| Profil | FSK | PIN |
|---|---|---|
| 👨👩👧👦 Familie | 6 | – |
| 🎓 Jugendliche | 12 | – |
| 🎬 Erwachsene | 18 | 1234 |
Profile können über die Verwaltung angepasst werden. Die Standard-PIN für "Erwachsene" sollte geändert werden.
Tipps
- Suchanfragen funktionieren am besten auf Deutsch (weil die NFO-Plots oft deutsch sind)
- Ähnliche Filme: Klicke auf eine Filmkarte, um ähnliche Filme zu finden
- Neu-Indexierung bei neuen Filmen – die alten bleiben erhalten (Upsert)
- Die ChromaDB-Collection
filmsuchekann unabhängig von anderen Projekten genutzt werden
API
Die Anwendung bietet eine REST-API für Programme und Skripte.
Endpoints
| Endpoint | Methode | Beschreibung |
|---|---|---|
/ |
GET | Startseite |
/login |
GET | Login-Seite |
/api/status |
GET | System-Status (Admin) |
/auth/login |
GET/POST | Login-Seite / Authentifizieren |
/auth/register |
POST | Benutzer registrieren |
/auth/logout |
GET | Ausloggen |
/auth/oidc/login |
GET | OIDC-Login starten |
/auth/callback |
GET | OIDC-Callback |
/auth/me |
GET | Aktueller Benutzerstatus |
/api/search |
GET | Filme suchen |
/api/similar/{movie_id} |
GET | Ähnliche Filme |
/api/index/status |
GET | Indexierungsstatus |
/api/index |
POST | Vollständige Indexierung |
/api/servers |
GET | Server auflisten |
/api/servers |
POST | Server hinzufügen |
/api/servers/{server_id} |
PUT | Server aktualisieren |
/api/servers/{server_id} |
DELETE | Server löschen |
/api/servers/sync |
POST | Server-Liste synchronisieren |
/api/servers/{server_id}/sync |
POST | Server synchronisieren |
/api/servers/{server_id}/index |
POST | Server indexieren |
/api/index-all |
POST | Alle Server indexieren |
/api/profiles |
GET | Profile auflisten |
/api/profiles |
POST | Profil hinzufügen |
/api/profiles/verify-pin |
POST | PIN verifizieren |
/api/profiles/{profile_id} |
PUT | Profil aktualisieren |
/api/profiles/{profile_id} |
DELETE | Profil löschen |
Authentifizierung
Geschützte Endpoints erfordern einen Bearer-Token:
Authorization: Bearer <JWT-Token>
OpenAPI-Spezifikation
Eine vollständige OpenAPI-Spezifikation ist verfügbar unter plans/openapi.md.
Beispiel-Anfrage
# Suche nach Filmen
curl "http://localhost:42000/api/search?query=Sci-Fi&limit=10"
# Server auflisten
curl -H "Authorization: Bearer <token>" "http://localhost:42000/api/servers"
# Film suchen mit Stimmung
curl "http://localhost:42000/api/search?query=romantisch&limit=5"