Skip to main content

Generiert statische HTML-Bibliotheken aus Videodateien – archivierungsfähig, ohne Server, ohne Datenbank.

Project description

Mediathek Manager

Generiert statische HTML-Bibliotheken aus Videodateien — archivierungsfähig, ohne Server, ohne Datenbank.

Das Tool scannt Verzeichnisse mit Videodateien (M4V, MP4, MKV, MOV), extrahiert eingebettete Metadaten (Titel, Tags, Genre, Kapitel, Beschreibungen) und generiert eine navigierbare HTML-Bibliothek direkt neben den Videos. Eine einzige Bibliothek pro Aufruf — rekursiv über alle Unterverzeichnisse mit hierarchie-gespiegelter Struktur, Breadcrumb-Navigation, Tag- und Genre-Filtern sowie Detailseiten inkl. klickbaren Kapiteln.

Scope — was der Mediathek Manager nicht tut

Der Mediathek Manager erzeugt keine neuen Vorschaubilder aus dem Videoinhalt. Poster-Generierung (Frame-Extraktion, Resize, Tone-Mapping, Komposition) ist eine eigenständige Kompetenz und gehört in spezialisierte Tools (z. B. den kurmann-vorschaubild-manager, aufgerufen aus dem kurmann-mediaset-creator). Der Mediathek Manager konsumiert nur existierende Bildquellen nach folgender Prioritätenkette:

  1. Poster-Sidecar {stem}-poster.jpg (z. B. Urlaub-poster.jpg neben Urlaub.m4v) wird direkt als Thumbnail für Grid-Cards verwendet.
  2. Eingebettetes Cover-Atom im Video-Header (iTunes-covr bzw. disposition.attached_pic in ffprobe-Sprech). Liegt kein Sidecar neben dem Video, aber trägt die Datei bereits ein Cover-Atom, wird es verlustfrei (ffmpeg -c copy) nach mediathek/embedded-poster/<layout>.jpg extrahiert und als Thumbnail genutzt. Wichtig: Das Tool liest damit nur, was im Datei-Header bereits existiert — kein Bildinhalt wird neu berechnet, kein Frame extrahiert.
  3. Platzhalter-Card mit zentriertem Titel. Sie ist weiterhin voll klickbar und führt zur Detailseite.

Zusätzlich wird Fanart ({stem}-fanart.jpg, typisch landscape 16:9) — wenn vorhanden — auf der Detailseite als <video poster="…"> eingesetzt, damit sich der Player harmonisch füllt, bevor man auf Play klickt. Fehlt das Fanart, dient das Poster (Sidecar oder extrahiertes Cover) als Fallback.

Dadurch bleibt der Mediathek Manager fokussiert auf Scannen, Metadaten und HTML — der einzige ffmpeg-Einsatzzweck ist ein narrow-scoped Atom-Copy, kein Bildverarbeitungs-Pipeline.

Medienset-Verzeichnisse (Infuse-Konvention)

Bibliotheken nach Infuse-Konvention organisieren jeden Einzelfilm in einem eigenen Ordner, dessen Name dem Video entspricht und in dem auch die Sidecars liegen:

Familienfilme/
└── 2026/
    └── 2026-03-22-Geburtstag-Dennis-2026/          ← Medienset-Ordner
        ├── 2026-03-22 Geburtstag Dennis 2026.mov
        ├── 2026-03-22 Geburtstag Dennis 2026-poster.jpg
        ├── 2026-03-22 Geburtstag Dennis 2026-fanart.jpg
        └── 2026-03-22 Geburtstag Dennis 2026.nfo

Der Mediathek Manager erkennt solche Ordner automatisch und rendert sie nicht als Zwischen-Ordner. Das Video erscheint stattdessen direkt in der Eltern-Ebene (im Beispiel: unter 2026) als Video-Card. Klick führt direkt zur Detailseite — ein Klick weniger als zuvor.

Erkennungsregel: Das Verzeichnis enthält genau ein Video, und dessen Dateiname (ohne Erweiterung) entspricht nach Normalisierung dem Ordnernamen (Leerzeichen und Bindestriche werden gleichgesetzt, Groß-/Kleinschreibung ignoriert). Enthält der Ordner zwei oder mehr Videos, bleibt er ein normales Unterverzeichnis.

Metadaten-Quellen (Reihenfolge)

Pro Feld wird die jeweils zuverlässigste verfügbare Quelle verwendet. NFO ersetzt nicht alles — fehlt ein NFO-Feld, wird die nächste Quelle geprüft:

Feld Reihenfolge
Titel NFO <title> → ffprobe tags.title → Dateiname-Stem ohne ISO-Präfix
Datum NFO <published> → Dateiname-Präfix YYYY-MM-DD<sep>… → ffprobe tags.date / content_create_date
Genre NFO erstes <genre> → ffprobe tags.genre
Quelle/Autor NFO erstes <author> → ffprobe tags.artisttags.album_artist
Beschreibung ffprobe tags.description
Langbeschreibung NFO <plot> → ffprobe tags.synopsistags.long_description

NFO-Dateien folgen der Infuse-Konvention (<media type="Other"> mit <title>, <published>, <genres>, <authors>, optional <plot>). NFO-Werte haben Vorrang vor YAML-Sidecars.

Was nicht als Datumsquelle verwendet wird: Das Feld creation_time (QuickTime/MP4 mvhd-Header-Timestamp) ist bei den meisten Workflows der Encoder- oder Kopierzeitpunkt und nicht das echte Aufnahmedatum — vor allem bei Apple-Memories-Renderings wie *.mov. Verlässlich ist hingegen das eingebettete date-Atom (iTunes-/M4V-Atom ©day, exiftool: "Content Create Date"), das User-Tools beim Kodieren explizit setzen.

Eine optionale YAML-Sidecar-Datei ({stem}.yaml neben dem Video) wird weiterhin unterstützt — sie liegt in der Reihenfolge zwischen ffprobe und NFO und eignet sich als schneller Ad-hoc-Override für Bibliotheken ohne vollständige NFO-Pflege.

Voraussetzungen

  • Python >= 3.11
  • ffprobe (für Metadaten-Extraktion aus eingebetteten Tags und Kapiteln)
  • ffmpeg (optional — nur nötig, wenn eingebettete Cover-Atome als Poster-Fallback verlustfrei kopiert werden sollen; fehlt ffmpeg, bleibt es bei der Platzhalter-Card für Videos ohne -poster.jpg-Sidecar) Der Mediathek Manager arbeitet ausschließlich mit lokal erreichbaren Pfaden — das schliesst SMB-/NFS-/FUSE-Mounts ein. Remote-Speicher wie Synology-NAS werden typischerweise als SMB-Share gemountet (z. B. /Volumes/Familienfilme). rclone-Remotes werden seit v0.4.0 nicht mehr unterstützt.

Installation

# Via PyPI
pip install kurmann-mediathek-manager

# Lokale Entwicklung
uv sync

Verwendung

# Bibliothek lokal generieren
mediathek-manager generate /pfad/zum/videoverzeichnis

# Mit eigenem Titel (sonst wird der Ordnername verwendet)
mediathek-manager generate /pfad/zum/Familienfilme --title "Familienfilme"

# Ohne Rekursion: nur Videos im Root-Verzeichnis
mediathek-manager generate /pfad/zum/videoverzeichnis --no-recursive

# Mit ausführlicher Ausgabe
mediathek-manager generate /pfad/zum/videoverzeichnis --verbose

# Nur scannen (zeigt gefundene Videos und Metadaten)
mediathek-manager scan /pfad/zum/videoverzeichnis

# HTML an einem separaten Ort generieren (Quellverzeichnis bleibt unberührt)
mediathek-manager generate /pfad/zum/videoverzeichnis --output ~/Mediathek-HTML

# Mediathek über lokalen Webserver im Browser öffnen
mediathek-manager serve ~/Mediathek-HTML

# Dateinamen auf SMB/URL/APFS-Kompatibilität prüfen (Read-only-Diagnose)
mediathek-manager check-names /pfad/zum/videoverzeichnis

# Konfiguration
mediathek-manager config list
mediathek-manager config set tools.ffprobe_path /usr/local/bin/ffprobe

Erzeugte Struktur

videoverzeichnis/                  ← CLI-Input (Root der Bibliothek)
├── index.html                     ← Einstiegspunkt (einzige HTML im Root)
├── Film1.m4v
├── Film1-poster.jpg               ← optionales Sidecar (nicht vom Tool erzeugt)
├── Ferien/
│   ├── Urlaub.m4v
│   └── Urlaub-poster.jpg
└── mediathek/                     ← alle weiteren Artefakte
    ├── style.css
    ├── browse/                    ← Unterverzeichnis-Indexe (Hierarchie gespiegelt)
    │   └── Ferien/
    │       └── index.html
    ├── detail/                    ← Detailseiten (Hierarchie gespiegelt)
    │   ├── Film1.html
    │   └── Ferien/
    │       └── Urlaub.html
    ├── embedded-poster/           ← extrahierte Cover-Atome (nur bei Bedarf)
    │   └── Ferien/
    │       └── Urlaub.jpg
    ├── tag/                       ← Tag-Filterseiten (über gesamte Bibliothek)
    │   └── weltraum.html
    └── genre/                     ← Genre-Filterseiten
        └── dokumentation.html

Poster werden direkt vom {stem}-poster.jpg-Sidecar neben dem Video referenziert. Fehlt das Sidecar, prüft der Generator, ob das Video einen attached_pic-Stream im Header trägt, und kopiert ihn verlustfrei nach mediathek/embedded-poster/<layout>.jpg. Fehlt beides, zeigt die Card einen Platzhalter mit zentriertem Titel.

Safari-optimiert: Die Detailseiten nutzen native <video>-Tags, die in Safari via AVFoundation rendern — dieselbe Pipeline wie QuickTime. HDR10 / Dolby Vision / Rec.2020 PQ wird korrekt tone-mapped. Safari ist daher der empfohlene Browser.

Suche: Die Bibliothek nutzt keine JavaScript-Suche — die Browser-interne Textsuche (⌘+F bzw. Strg+F) funktioniert bestens auf der langen Videoliste.

Card-Layout

Grid-Cards zeigen per Default das Poster, darunter Jahr links und Laufzeit rechts — keinen zusätzlichen Titel-Text, weil das Poster den Titel typischerweise bereits trägt (YouTube-Thumbnails, gestaltete Mediaset-Poster). Bei Videos ohne Poster-Sidecar und ohne eingebettetes Cover-Atom erscheint der Titel zentriert in der Platzhalter-Box.

Wer den Titel-Text zusätzlich unter jeder Card rendern will (z. B. bei Bibliotheken mit rein fotografischen Postern, die keinen Titel enthalten), nutzt:

mediathek-manager generate /pfad --show-card-titles

Die Tag- und Genre-Listen auf der Startseite sind als Stichwort-Index nach Buchsatz-Vorbild gesetzt — enge Zeilen, rechtsbündige Zählungen im Tabular-Numerics-Stil, ruhiger Rhythmus.

Metadaten-Cache

Ab v0.4.0 speichert der Mediathek Manager die extrahierten Metadaten (ffprobe-Ergebnisse, Sidecar-Daten, Filename-Heuristiken) in mediathek/.metadata-cache.json. Beim nächsten generate-Lauf wird ffprobe nur für geänderte oder neue Videos aufgerufen — unveränderte Videos werden direkt aus dem Cache geladen. Das beschleunigt wiederholte Läufe auf grossen Bibliotheken erheblich, besonders über SMB-Mounts.

Der Cache-Key pro Video besteht aus mtime + size der Videodatei sowie den mtimes aller Sidecars (.yaml, .nfo, -poster.jpg, -fanart.jpg). Ändert sich eines dieser Attribute, wird das Video neu extrahiert. Der Cache ist ein Hilfsmittel — er kann jederzeit gelöscht werden, die HTML-Dateien sind das archivierungswürdige Artefakt.

Bei Abbruch (Ctrl+C, Verbindungsabbruch) bleibt die alte Cache-Datei intakt. Der nächste Lauf profitiert von allen bisherigen Einträgen des vorherigen Laufs und extrahiert nur die fehlenden Videos nach.

Separater Ausgabepfad

Die HTML-Bibliothek kann optional an einem separaten Ort generiert werden (z. B. auf einem schnellen lokalen Laufwerk statt auf dem NAS):

mediathek-manager generate /Volumes/Familienfilme/Final --output ~/Mediathek-HTML --title "Familienfilme"

Das Quellverzeichnis bleibt vollständig unberührt — es erfolgt keinerlei Schreibzugriff darauf. Im Output-Verzeichnis wird automatisch ein Symlink _videos → <Quellverzeichnis> erstellt — alle Video- und Sidecar-Referenzen in den HTML-Seiten gehen über _videos/….

Wichtig: Bei file:// blockiert Safari den Cross-Origin-Zugriff auf Sub-Ressourcen auch über Symlinks hinweg. Videos in Detailseiten spielen daher bei unterschiedlichen Pfadbäumen (z. B. /Volumes/NAS vs. /Users/…) nicht ab. Die Lösung: mediathek-manager serve startet einen lokalen Webserver, der den Symlink transparent auflöst:

mediathek-manager generate /Volumes/Internetfilme-Patrick --output ~/Movies/Internetfilme --title "Internetfilme"
mediathek-manager serve ~/Movies/Internetfilme
# → http://127.0.0.1:8080/ öffnet sich — alle Videos spielen ab

Auch ohne --output ist serve nützlich: es umgeht sämtliche file://-Probleme mit NFD-Unicode, URL-reservierten Zeichen und Browser-Sicherheitsrestriktionen.

Dateinamen: NFC vs. NFD und file://-Kompatibilität

Wer die generierte Bibliothek im SMB-gemounteten Finder per Doppelklick auf index.html öffnet, bewegt sich im file://-Schema und stößt schnell auf drei Fallen, die im Browser keine Fehlermeldung erzeugen:

NFC vs. NFD — die macOS-Unicode-Falle

macOS speichert Dateinamen mit Umlauten historisch in NFD (Normalization Form Decomposed): Das ä in Bäbibett liegt nicht als ein einzelnes Codepoint U+00E4 vor, sondern als a (U+0061) + Combining Diaeresis (U+0308). Dieselbe Datei, erzeugt unter Linux/Windows oder über git, liegt in NFC (Normalization Form Composed) als ein einzelnes U+00E4 vor.

Der Finder und Safari zeigen beide Formen identisch an. Aber:

  • Beim URL-Encoding eines NFD-Namens für einen file://-Link erzeugt der Browser zwei Escape-Sequenzen (%CC%88 für das Combining-Zeichen nach dem a), statt einem einzigen %C3%A4. Manche Player und Downloader (z. B. einige Browser-Plugins, ältere Video-Tools) lösen diese Kaskade nicht auf und finden die Datei nicht.
  • SMB-Shares auf Windows-Servern speichern intern NFC und können NFD-kodierte Pfade vom macOS-Client als „nicht existent" melden, obwohl das Finder-Listing die Datei zeigt.
  • Sortierungen und Vergleiche über Dateisystem-Grenzen hinweg schlagen fehl, wenn eine Seite NFC und die andere NFD liefert.

Zielformat: NFC für alles. Das ist der Default überall außer auf macOS-HFS+/APFS, wenn der Name ursprünglich im Finder getippt wurde. Konvertierung nachträglich z. B. mit convmv:

brew install convmv
convmv -f utf-8 -t utf-8 --nfc --notest /pfad/zur/bibliothek -r

URL-reservierte Zeichen

file://-Links in Browsern interpretieren folgende Zeichen besonders, egal wie der Name intern kodiert ist:

Zeichen Folge
# Terminiert die URL als Fragment-Anker — alles danach wird abgeschnitten
? Startet den Query-String — alles danach wird abgeschnitten
& Trennt Query-Parameter
+ Wird zum Leerzeichen interpretiert
% Leitet eine Escape-Sequenz ein

Dateinamen wie Urlaub#2024.m4v oder Doku & Film.m4v führen deshalb zu stumm kaputten Links. Der Browser lädt nichts, zeigt aber auch keinen Fehler.

Windows/SMB-verbotene Zeichen

< > : " | ? * sind unter Windows/SMB in Dateinamen komplett verboten. Wer die Bibliothek später auf eine Windows-Freigabe oder OneDrive legt, verliert diese Dateien still (Invalid name beim Kopieren).

Der check-names-Befehl

Zur Read-only-Diagnose der eigenen Bibliothek liefert der Mediathek Manager einen dedizierten Subcommand:

mediathek-manager check-names /pfad/zum/videoverzeichnis

Der Befehl scannt alle Videos und Unterverzeichnisse und meldet sieben Klassen von Auffälligkeiten:

Tag Bedeutung
NFD Dekomponierte Umlaute (macOS-Default), NFC erwartet
URL Zeichen, die file://-Links brechen: # ? & + %
WIN Unter Windows/SMB verbotene Zeichen: < > : " | ? *
LEN Pfadlänge > 240 Zeichen (Windows-MAX_PATH-Zone)
TRIM Führende/abschließende Leerzeichen oder trailing Punkte
RSVD Windows-Device-Name (CON, PRN, AUX, NUL, COM1LPT9)
CASE Groß-/Kleinschreibungs-Kollision mit anderem Pfad

Ausgabeformat:

[URL]                        Bäbibett & Co/film.m4v
[TRIM]                       ferien /urlaub.m4v
[NFD URL]                    2024/Bäbibett & Co/film.m4v

stdout enthält nur die maschinenlesbare [TAG] <pfad>-Liste (pipebar), stderr enthält Zusammenfassung und Details. Exit-Code 1 bei Fundstellen, sonst 0 — damit ist check-names scriptbar:

if ! mediathek-manager check-names /pfad/zur/bibliothek > /tmp/issues.txt; then
    echo "Bibliothek hat $(wc -l < /tmp/issues.txt) auffällige Pfade"
fi

Der Mediathek Manager benennt niemals um. Er ist ein reines Diagnose-Werkzeug — die Korrektur bleibt beim Nutzer (typisch convmv --nfc für NFD→NFC, manuell für den Rest).

Konfiguration

Persistente Konfiguration unter ~/.config/mediathek-manager/config.toml:

[tools]
ffprobe_path = "ffprobe"
ffmpeg_path = "ffmpeg"

Upgrade von 0.1.x auf 0.2.0

Version 0.2.0 ändert die Ausgabestruktur grundlegend. Alte .mediathek/-Ordner sind nicht kompatibel und sollten vor der erneuten Generierung gelöscht werden:

rm -rf /pfad/zum/videoverzeichnis/.mediathek
mediathek-manager generate /pfad/zum/videoverzeichnis --title "Deine Bibliothek"

Architektur und Hosting-Strategie

Für das Hosting der generierten Mediathek im Heimnetz und das übergreifende Architektur-Pattern für zukünftige Apps siehe das Fachdokument:

  • docs/static-hosting-architecture.md — beschreibt die Entscheidung für Synology Web Station als statischen HTTP-Backend, das Webserver-Mental-Model, Symlinks vs. URLs als Pfad-Indirection, HTTP-Range-Requests vs. SMB-Random-Access, mDNS-Hostnames, Apple TV via Infuse und AirPlay, Sicherheits-Setup und das übergreifende Pattern „NAS als Read-Only-Backend, Apps als HTTP-Clients".

Änderungsverlauf

Siehe CHANGELOG.md.

Lizenz

MIT — siehe LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kurmann_mediathek_manager-0.6.0.tar.gz (42.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kurmann_mediathek_manager-0.6.0-py3-none-any.whl (48.2 kB view details)

Uploaded Python 3

File details

Details for the file kurmann_mediathek_manager-0.6.0.tar.gz.

File metadata

File hashes

Hashes for kurmann_mediathek_manager-0.6.0.tar.gz
Algorithm Hash digest
SHA256 06ef9bb89a5ba2a5c182e7bff4df28974a9546d7b110ae406eb88e79a3f3b786
MD5 dae6f368fdc33c47c68c69c3d31c066c
BLAKE2b-256 84933a5746b4dc7137e4b1f0cd3cb4f28c0d15e4a2b9726bd4b8bc13c6fded38

See more details on using hashes here.

Provenance

The following attestation bundles were made for kurmann_mediathek_manager-0.6.0.tar.gz:

Publisher: publish.yml on kurmann/mediathek-manager

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file kurmann_mediathek_manager-0.6.0-py3-none-any.whl.

File metadata

File hashes

Hashes for kurmann_mediathek_manager-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 292c3087a94eec93b6f633ce1f3556cb7e629099588e231f9760b38a2a7499de
MD5 fd23a92408740d22eee2b82a89d770e2
BLAKE2b-256 3ef97c47874d67685e312281b7c8b33a13c3cdedce40a0706090e7a8f621dd71

See more details on using hashes here.

Provenance

The following attestation bundles were made for kurmann_mediathek_manager-0.6.0-py3-none-any.whl:

Publisher: publish.yml on kurmann/mediathek-manager

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page