Skip to main content

CLI-Tool und Python-Bibliothek zur Veröffentlichung von Familienfilmen: Medienset-Erstellung, Infuse-Deployment, Webserver-Deployment und Archivierung.

Project description

familienfilm-manager

CLI-Tool und Python-Bibliothek zur Veröffentlichung von selbst geschnittenen Familienfilmen. Orchestriert den gesamten Workflow: Metadaten extrahieren, Medienset erstellen (via mediaset-creator), Infuse-/Webserver-Deployment und Archivierung.


Voraussetzungen


Installation

uv pip install kurmann-familienfilm-manager

Im Entwicklungsmodus:

uv sync

Verwendung (CLI)

Gesamtworkflow

familienfilm-manager publish /pfad/zu/video.m4v \
  --title "Wanderung auf den Napf" \
  --category "Familie Kurmann-Glück" \
  --date "2025-03-24" \
  -v

Das Tool:

  1. Extrahiert Metadaten (QuickTime-Tags oder Dateiname)
  2. Erstellt ein Medienset via mediaset-creator mit separaten Profilen (Infuse/Web)
  3. Deployt zu Infuse sofort bei Fertigstellung (direkt via rclone, kein ZIP-Entpacken)
  4. Deployt zum Webserver nach Fertigstellung der Web-Komprimierung (rclone)
  5. Archiviert Original + Sidecars als TAR (Python tarfile → rclone move)

Einzeloperationen

# Nur Infuse-Deployment eines Verzeichnisses mit Infuse-Dateien
familienfilm-manager deploy-infuse /pfad/zum/infuse-verzeichnis/

# Nur Web-Deployment eines Web-ID-Verzeichnisses
familienfilm-manager deploy-web /pfad/zum/01JNXYZ.../

# Nur Archivierung
familienfilm-manager archive /pfad/zu/video.m4v --date 2025-03-24

Optionen (publish)

Option Beschreibung
--title TEXT Video-Titel (überschreibt extrahierte Metadaten)
--description TEXT Beschreibung des Videos
--category TEXT Kategorie (z.B. «Familie Kurmann-Glück»)
--date TEXT Aufnahmedatum im ISO-Format (YYYY-MM-DD)
--output-dir PATH Basisverzeichnis für die Web-Medienset-Ausgabe
--poster-frame INT Frame-Nummer für Vorschaubild (überspringt KI-Auswahl)
--poster-at FLOAT Zeitpunkt in Sekunden für Vorschaubild (z.B. 90 oder 1.5)
--poster-crop TEXT Bildausschnitt (left/center-left/center/center-right/right)
--web-id TEXT Web-ID für Web-Medienset (12 Zeichen, a-z 0-9; überschreibt Sidecar-Wert)
--max-luminance INT Peak-Leuchtdichte in nits für HDR-Metadaten (Default: 1000)
--no-sidecar Sidecar-Datei nicht lesen/schreiben
--no-infuse Infuse-Deployment überspringen
--no-web Web-Deployment überspringen
--no-archive Archivierung überspringen
--force Neuerstellung erzwingen
--verbose, -v Zusätzliche Ablaufinformationen auf stderr

Ausgabe

stdout enthält den Pfad zum erstellten Verzeichnis (Web-ID-Verzeichnis oder Infuse-Verzeichnis):

/pfad/zum/output/01JNXYZ.../

Verzeichnis-Publikation (Batch)

Mit publish-dir werden alle qualifizierten Videos in einem Verzeichnis sequenziell publiziert (älteste zuerst). Ideal für Watch-Folder-Workflows.

# Trockenlauf: zeige welche Videos publiziert würden
familienfilm-manager publish-dir /Movies/LumaFusion-Export/ --dry-run

# Alle qualifizierten Videos publizieren
familienfilm-manager publish-dir /Movies/LumaFusion-Export/

# Auch bereits publizierte Videos neu publizieren
familienfilm-manager publish-dir /Movies/LumaFusion-Export/ --force

Filter-Kriterien

Nur Dateien werden publiziert, die alle Bedingungen erfüllen:

  • Bekannte Video-Endung: .mov, .mp4, .m4v, .mkv
  • Dateiname matcht das Muster <YYYY-MM-DD> <titel>.<ext> (mindestens Datum-Präfix)
  • Kein Hidden-File (kein . am Anfang)
  • Keine Verzeichnisse

Alles andere wird stillschweigend ignoriert.

Idempotenz

Nach erfolgreicher Publikation wird ins Sidecar (<video>.settings.toml) geschrieben:

  • Pro aktivem Deploy-Kanal ein published_at-Zeitstempel: [web].published_at, [local].published_at, [archive].published_at
  • source.size_bytes – Dateigrösse der Quelle zu diesem Zeitpunkt
  • source.head_sha1 – SHA1 der ersten 1 MB der Quelldatei (Fingerprint)

Beim nächsten publish-dir-Lauf wird ein Video übersprungen, wenn alle aktiven Kanäle einen published_at-Zeitstempel haben UND der Fingerprint der Quelldatei mit dem gespeicherten übereinstimmt (gleiche Grösse UND gleicher Hash der ersten 1 MB).

„Aktiv" heisst: ohne --no-web/--no-infuse/--no-archive-Flag. Wenn ein Kanal deaktiviert ist, wird sein published_at für den Skip-Check nicht verlangt.

Warum Fingerprint statt Timestamps?

Die frühere Logik verglich published_at mit der mtime von Video und Sidecar. Auf SMB-/NAS-Mounts (typisch für LumaFusion-Export auf ein NAS) ist das nicht zuverlässig:

  • mtime-Auflösung schwankt je nach Backend (teilweise 2-Sekunden-Raster, SMB-Metadaten-Caching)
  • Clock-Drift zwischen lokaler Uhr (datetime.now()) und NAS-Filesystem
  • Drittsoftware verändert Timestamps (Spotlight-Indexierung, Time Machine, Finder-Copy, Backup-Tools)

Resultat: Videos wurden zuverlässig neu publiziert, obwohl sie klar publiziert waren. Der Fingerprint (Grösse + Kopf-Hash) ist unabhängig von Timestamps und funktioniert identisch auf lokalem APFS und SMB.

Der Hash deckt nur die ersten 1 MB ab — ein pragmatischer Kompromiss aus Scan-Geschwindigkeit (~100 ms auf SMB pro Video) und Kollisionssicherheit. Ein Neu-Export ändert in aller Regel sofort Header-Bytes (Metadaten, Container-Stream) und wird erkannt.

Republish-Trigger

  • Andere Dateigrösse → Video wurde neu exportiert
  • Gleiche Grösse, anderer Kopf-Hash → Header/Metadaten verändert
  • Altes Sidecar ohne Fingerprint (aus Version ≤ 0.5.0) → einmaliger Republish erfasst den Fingerprint; ab dann idempotent

Mit --force werden alle Videos unabhängig vom Status neu publiziert.

Hinweis: Beim Einzeldatei-publish greift der Skip-Check nicht — der explizite Aufruf publiziert immer.

Optionen (publish-dir)

Option Beschreibung
--category TEXT Kategorie für alle Videos im Verzeichnis (überschreibt defaults.category aus Config)
--no-infuse Infuse-Deployment für alle Videos überspringen
--no-web Web-Deployment für alle Videos überspringen
--no-archive Archivierung für alle Videos überspringen
--force Auch bereits publizierte Videos neu publizieren
--dry-run Nur anzeigen welche Videos publiziert würden, ohne zu publizieren
--recursive, -r Unterverzeichnisse mit einbeziehen (siehe Verzeichnis-Settings)
--work-dir PATH Arbeitsverzeichnis für temporäre Dateien (überschreibt paths.work_dir Config)
--verbose, -v Zusätzliche Ablaufinformationen pro Video auf stderr

Verhalten bei Fehlern

Ein Fehler bei einem Video stoppt den Batch-Lauf nicht — die Verarbeitung läuft mit dem nächsten Video weiter. Am Schluss wird eine Zusammenfassung mit Erfolgen, übersprungenen und fehlgeschlagenen Videos ausgegeben. Exit-Code 1 wenn mindestens ein Video fehlschlug.

Robustes Deployment

Die drei rclone-basierten Deployment-Schritte (Infuse, Web, Archive) sind gegen typische SMB/NAS-Flakeyness abgesichert:

  • Automatischer Retry mit exponentiellem Backoff (1 s → 3 s → 9 s, 3 Versuche nach dem ersten). Deckt flüchtige Netzwerk-Hiccups und Filesystem-Sync-Delays ab, ohne den gesamten Publish-Workflow (oft 20+ min ffmpeg-Arbeit) wiederholen zu müssen. Jeder Retry wird im Terminal gelb angezeigt.
  • Post-Deploy Health-Check: Nach erfolgreichem rclone-Lauf wird via rclone lsf geprüft, ob die erwarteten Dateien/Verzeichnisse wirklich im Ziel angekommen sind. Bei Mismatch: rot markierter Fehler statt silencieren.
  • Infuse-Medienset bleibt bei Deploy-Fehler erhalten (Temp-Verzeichnis wird nicht aufgeräumt). Nachholen ohne Neuerstellung:
    familienfilm-manager deploy-infuse /pfad/zum/temp-verzeichnis/
    
    Der genaue Pfad wird im roten Fehler-Hinweis mitgeliefert.
  • TAR-Datei bleibt bei Archive-Deploy-Fehler erhalten (neben dem Quellvideo). Nachholen:
    rclone move <pfad/zum/tar> <archive-target>
    

Verzeichnis-Überwachung (watch-dir)

Überwacht ein oder mehrere Verzeichnisse und publiziert neue Videos automatisch. Ein Tick ist verhaltensidentisch zu einem publish-dir-Lauf — gleiche Idempotenz, gleiche Filter-Regeln, gleiche Fehler-Isolation.

# Ein einziges Verzeichnis, Default-Intervall (24h):
familienfilm-manager watch-dir -d /Volumes/Videoschnitt/LumaFusion-Export

# Mehrere Verzeichnisse, alle 90 Minuten:
familienfilm-manager watch-dir -d /pfad/a -d /pfad/b --interval 90m

# Konfiguration in der Config hinterlegt, einfach starten:
familienfilm-manager config set watch.directories "/pfad/a,/pfad/b"
familienfilm-manager config set watch.interval_seconds "21600"   # 6h
familienfilm-manager watch-dir

# Einmaliger Durchlauf für launchd/cron:
familienfilm-manager watch-dir --once

Modi

Modus Beschreibung Typischer Einsatz
Daemon (Default) Endlosschleife: Tick → sleep(interval) → Tick → … Der erste Tick läuft sofort beim Start. Manuell im Terminal, oder launchd mit KeepAlive=true.
Single-shot (--once) Genau ein Tick, dann Exit 0. launchd mit StartInterval / StartCalendarInterval, oder cron.

Beide Modi führen einen Tick identisch aus — --once beendet danach nur die Schleife. Umstieg vom Daemon auf launchd+--once ändert das Verhalten eines einzelnen Laufs nicht.

Intervall-Notation

--interval akzeptiert nackte Sekunden oder Suffixe s / m / h / d:

--interval 600      # 600 Sekunden = 10 Minuten
--interval 90m      # 90 Minuten
--interval 24h      # 24 Stunden (Default)
--interval 2d       # 2 Tage

Default ist 24 Stunden — Familienfilme müssen nicht sofort publiziert werden, ein täglicher Durchlauf schont das NAS (der Scan liest pro Video 1 MB zum Fingerprint-Abgleich).

Im --once-Modus wird --interval ignoriert (mit Hinweis) — das Timing gehört dem externen Scheduler.

Stabilitätscheck für wachsende Dateien

LumaFusion-Exporte direkt auf SMB schreiben die Datei inkrementell. Würde der Watch-Tick genau dann zuschlagen, wenn der Export noch läuft, würde eine unvollständige Datei publiziert.

Mechanismus: Zu Beginn der Publish-Phase wird die Grösse aller Kandidaten gemessen, anschliessend --stability-window Sekunden gewartet und erneut gemessen. Dateien, deren Grösse sich geändert hat, werden als „wächst noch" markiert und beim nächsten Tick erneut geprüft. Die Wartezeit gilt einmalig für alle Kandidaten gemeinsam — bei 5 neuen Videos kostet das 60 s total, nicht 5×60 s.

Default: 60s. Mit --stability-window 0 abschaltbar (oder via Config watch.stability_window_seconds).

Wie beim Fingerprint-Check wird absichtlich die Dateigrösse geprüft, nicht die mtime — aus denselben Gründen (SMB-Unzuverlässigkeit).

HTML-Benachrichtigung mit Live-Status

Ist notification.file konfiguriert, wird bei Publikationsbeginn ein „wird publiziert…"-Eintrag geschrieben und beim Abschluss durch den finalen Zustand ersetzt:

  • wird publiziert… — orange, während der Publikation
  • publiziert — mit Link zur Web-URL
  • fehlgeschlagen — rot, mit Fehlermeldung
  • abgebrochen — grau (wird beim Watch-Start gesetzt, falls vom letzten Lauf noch pending-Einträge liegenblieben, z.B. nach einem Crash)

Jeder Eintrag hat eine stabile data-video-id (aus dem absoluten Pfad abgeleitet) — ein Republish überschreibt denselben Eintrag statt Duplikate anzuhängen.

Fehler-Isolation

Fehler in einem Verzeichnis (fehlend, nicht lesbar, Exception) stoppen den Watch-Lauf nicht. Andere Verzeichnisse werden weiter verarbeitet, beim nächsten Tick wird erneut versucht. Fehler auf Video-Ebene (einzelne Publikation schlägt fehl) werden wie bei publish-dir pro Video geloggt und der Tick macht mit dem nächsten Video weiter.

Beenden

SIGTERM und SIGINT (Ctrl+C) beenden den Daemon sauber nach dem laufenden Tick — nicht mittendrin. Kompatibel mit launchctl stop und Docker-ähnlichen Graceful-Shutdown-Mechanismen.

launchd-Beispiel (macOS)

Variante A — Daemon mit KeepAlive:

<plist>
  <dict>
    <key>Label</key><string>ch.kurmann.familienfilm-manager</string>
    <key>Program</key><string>/usr/local/bin/familienfilm-manager</string>
    <key>ProgramArguments</key>
    <array>
      <string>familienfilm-manager</string>
      <string>watch-dir</string>
    </array>
    <key>KeepAlive</key><true/>
    <key>StandardErrorPath</key><string>/tmp/familienfilm-manager.err</string>
  </dict>
</plist>

Variante B — --once mit Kalender-Trigger (täglich 03:00 Uhr):

<key>ProgramArguments</key>
<array>
  <string>familienfilm-manager</string>
  <string>watch-dir</string>
  <string>--once</string>
</array>
<key>StartCalendarInterval</key>
<dict><key>Hour</key><integer>3</integer></dict>

Optionen (watch-dir)

Option Beschreibung
-d / --directory PATH Zu überwachendes Verzeichnis (mehrfach angebbar). Überschreibt watch.directories.
--interval TEXT Intervall zwischen Ticks (24h, 90m, 600). Default: Config (24h). Im --once-Modus ignoriert.
--once Genau ein Tick, dann Exit 0.
--stability-window TEXT Wartezeit zur Erkennung wachsender Dateien. Default: Config (60s). 0 deaktiviert.
--category TEXT Kategorie für alle Videos in allen überwachten Verzeichnissen (überschreibt defaults.category aus Config).
--recursive, -r Unterverzeichnisse mit einbeziehen (siehe Verzeichnis-Settings)
--no-infuse / --no-web / --no-archive Profile überspringen (wie bei publish-dir).
--force Auch bereits publizierte Videos neu publizieren.
--work-dir PATH Arbeitsverzeichnis (überschreibt paths.work_dir).
--verbose, -v Zusätzliche Ablaufinformationen auf stderr.

Metadaten-Extraktion

Metadaten werden in folgender Priorität ermittelt:

Aufnahmedatum

  1. CLI-Parameter (--date) – überschreibt alles
  2. QuickTime-Tag (com.apple.quicktime.creationdate) – bewusst in Final Cut Pro gesetztes Datum
  3. Dateiname – ISO-Datum am Anfang des Dateinamens (z.B. 2019-12-22 Twannbachschlucht.mov)
  4. Generische Tags (creation_time, date) – oft das Datei-Änderungsdatum, nicht das Aufnahmedatum

Der Dateiname hat bewusst höhere Priorität als generische Tags (creation_time), weil der Videoschnitt selten am gleichen Tag wie die Aufnahme stattfindet. So kann das korrekte Aufnahmedatum über den Dateinamen bestimmt werden.

Titel

  1. CLI-Parameter (--title) – überschreibt alles
  2. QuickTime-Tags (via ffprobe) – aus Final Cut Pro exportierte Metadaten
  3. Dateiname – Titel nach dem Datumspräfix:
    • 2025-03-24 Wanderung auf den Napf.m4v → «Wanderung auf den Napf»
    • 2025-03-24 - Wanderung auf den Napf.m4v → «Wanderung auf den Napf»

Poster-Zeitpunkt aus dem Dateinamen

Der Zeitpunkt für das Vorschaubild kann direkt im Dateinamen mitgegeben werden – ideal für Videoschnitt-Programme wie LumaFusion, die keine Sidecar-Dateien beim Export erstellen.

Format: poster-<zeit> am Ende des Dateinamens (Leerzeichen davor). Minuten-Marker: min (vollständig) oder m (Kurzform, ffmpeg-Stil).

Suffix Bedeutung
poster-2min / poster-2m 2 Minuten = 120 Sek.
poster-3min12 / poster-3m12 3 Min 12 Sek = 192 Sek.
poster-3min11s / poster-3m11s 3 Min 11 Sek (mit trailing s als Sekunden-Marker)
poster-1min30s500 / poster-1m30s500 1 Min 30.5 Sek (Sub-Sekunden)
poster-30s 30 Sek.
poster-30s500 30.5 Sek.

Beispiel:

2026-04-16 HDR-Test poster-1min30.mov

→ Datum: 2026-04-16, Titel: «HDR-Test», Poster-Zeitpunkt: 90 Sek.

Der Suffix wird beim Parsen vom Titel entfernt (landet nicht im Output-Dateinamen) und automatisch in die Sidecar-Datei (.settings.toml) geschrieben. Bei einem späteren publish ohne Suffix im Dateinamen wird der Wert aus der Sidecar-Datei gelesen.

Priorität: CLI (--poster-at) > Filename-Suffix > Sidecar.

Wichtig: Ein Aufnahmedatum ist zwingend erforderlich. Ohne Datum wird die Verarbeitung abgebrochen.


Settings-Sidecar-Datei

Wenn Poster-Einstellungen via CLI angegeben werden (--poster-frame, --poster-at, --poster-crop), speichert der Familienfilm Manager diese automatisch in einer .settings.toml-Datei neben dem Video:

2025-03-24 Wanderung auf den Napf.m4v
2025-03-24 Wanderung auf den Napf.settings.toml   ← automatisch erstellt

Inhalt:

[poster]
timestamp_seconds = 42.5
crop_position = "center-right"

[web]
web_id = "a3xk9mn2pqrw"
published_at = "2026-04-18T10:23:45"

[local]
published_at = "2026-04-18T10:24:12"

[archive]
published_at = "2026-04-18T10:26:58"

[source]
size_bytes = 4521830394
head_sha1 = "a3f4c9b2..."

[metadata]
category = "Familie Kurmann-Glück"
  • [poster] — Poster-Einstellungen (bei erneutem Publish wiederverwendet)
  • [web] — Web-ID, Luminance, Publish-Zeitpunkt der Web-Publikation (Hostpoint o.ä.)
  • [local] — Publish-Zeitpunkt der Infuse-/LAN-Medienserver-Publikation. Heißt [local] (nicht [infuse]), weil der Kanal einen lokalen Medienserver beliefert — Infuse ist nur eine mögliche Consumer-App
  • [archive] — Publish-Zeitpunkt der Archivierung (TAR im Langzeit-Archiv)
  • [source] — Fingerprint für die publish-dir-Idempotenz (siehe Idempotenz)
  • [metadata] — Effektive Metadaten zum Publish-Zeitpunkt. Macht das Archiv selbsttragend: wenn ein Video später aus dem Archiv extrahiert und mit publish neu veröffentlicht wird, kennt es seine ursprüngliche Kategorie — unabhängig von Config-Defaults auf dem aktuellen System.

Archiv-Layout ab v0.6.0

Im Archiv-Ziel liegen pro Video zwei Dateien nebeneinander:

nas:/Archiv/2026/Videoschnitt/
  2026-04-15-Mika-Socken-waschen.tar           ← Video + evtl. .fcpxml/.lfpackage
  2026-04-15-Mika-Socken-waschen.settings.toml ← Management-Metadaten

Damit sind Archiv-Metadaten direkt per rclone ls / Finder sichtbar — z.B. welche Kategorie, wann publiziert, welche Web-ID. Ohne das TAR entpacken zu müssen.

Das TAR selbst enthält nur Video + Produktions-Nebenmaterialien (wie .fcpxml, .lfpackage, Fanart-Dateien, NFO). Der Management-State (.settings.toml) bleibt ausserhalb — semantisch sauber entkoppelt (der [archive].published_at-Zeitstempel würde sonst zirkulär im Archiv liegen, das er beschreibt).

TAR-Erstellung: Das TAR wird im konfigurierten paths.work_dir erstellt, nicht mehr im Quellverzeichnis. Bei SMB-/NAS-Quellen spart das 1–7 GB Netzwerk-Schreibvorgang pro Video und vermeidet SMB-Sync-Delays vor dem finalen rclone move. Ohne paths.work_dir bleibt das Fallback auf das Quellverzeichnis (rückwärtskompatibel).

Per-Kanal published_at und Partial-Failure-Schutz

Die drei published_at-Felder werden unabhängig voneinander gesetzt — ein Feld erscheint erst, wenn der zugehörige rclone-Deploy erfolgreich war. Beispiel einer typischen „Web ok, NAS war im Sleep"-Situation:

[web]
web_id = "a3xk9mn2pqrw"
published_at = "2026-04-18T10:23:45"   # Hostpoint erfolgreich

# [local] und [archive] fehlen komplett — NAS war offline

Beim nächsten publish-dir-Lauf erkennt der Skip-Check, dass Local und Archive noch nicht publiziert sind, und baut das Video komplett neu auf (inkl. erneuter Web-Publikation — --force auf Kanal-Ebene folgt in einer späteren Version). Vorher wurde nur ein einziges published_at geschrieben, und der Skip-Check interpretierte das als „fertig" → Infuse und Archive wurden nie nachgeholt.

Category-Auflösung

Die Kategorie wird beim Publish in folgender Reihenfolge aufgelöst (erste Quelle mit Wert gewinnt):

  1. CLI --category — expliziter Wille, überschreibt alles
  2. Video-Sidecar [metadata].category — für aus dem Archiv extrahierte Videos
  3. familienfilm.toml — Verzeichnis-Settings, nächstgelegenes Verzeichnis gewinnt (siehe unten)
  4. Config defaults.category — globaler Fallback
  5. ffprobe-Metadata — QuickTime-Tag (LumaFusion-Exports liefern das typischerweise nicht)

Sidecar hat bewusst Vorrang vor Config und Directory-Settings: Ein Video soll seine ursprüngliche Kategorie behalten, auch wenn der aktuelle Config-Default inzwischen auf etwas anderes zeigt, oder der Export-Ordner zwischendurch eine andere familienfilm.toml bekommen hat.


Verzeichnis-Settings (familienfilm.toml)

Eine Datei namens familienfilm.toml in einem Quellverzeichnis liefert Default-Werte für alle Videos darunter. Aktuell wird nur category gelesen — die Struktur ist so angelegt, dass weitere Felder (z.B. author) ohne Breaking Change ergänzt werden können.

Format

# /Movies/LumaFusion-Export/familienfilm.toml
category = "Familie Kurmann-Glück"

Keine hidden-Datei (kein führender Punkt) — absichtlich, damit sie beim Navigieren sichtbar bleibt.

Vererbung

Beim Publish jedes Videos wird die Verzeichniskette von der Quelldatei nach oben gelaufen. Die nächstgelegene familienfilm.toml mit einem gesetzten Feld gewinnt. Unterverzeichnisse überschreiben also Parents.

Beispiel:

/Movies/
  familienfilm.toml              ← category = "Familie Kurmann-Glück"
  2026-Frühjahr/
    2026-04-14 Ostern.mov        ← erbt "Familie Kurmann-Glück"
  Arbeit-Präsentationen/
    familienfilm.toml            ← category = "Firma XY"
    2026-04-15 Quartalsreport.mov ← "Firma XY" (Child-Override)

Grenze der Suche

  • Bei publish-dir und watch-dir ist der Scan-Root des Befehls die obere Grenze. Eine familienfilm.toml direkt im Scan-Root-Argument greift; darüber wird nicht gesucht.
  • Beim Einzel-publish läuft die Suche bis zum Filesystem-Root — praktisch heisst das: bis zu der Datei, die du tatsächlich irgendwo im Baum hinterlegt hast.

Rekursiver Scan (--recursive / -r)

publish-dir und watch-dir sind standardmässig flach (nur direkte Dateien des Verzeichnisses). Mit --recursive werden auch Unterverzeichnisse durchsucht:

# Ganzer Jahresbaum in einem Zug:
familienfilm-manager publish-dir /Movies/LumaFusion-Export --recursive

# Watch über verschachtelte Verzeichnisse:
familienfilm-manager watch-dir -d /Movies/LumaFusion-Export --recursive

Hidden-Verzeichnisse (.Trashes, .Spotlight-V100 etc.) werden übersprungen. Sortierung läuft über Verzeichnisgrenzen hinweg (älteste Videos zuerst, egal in welchem Unterverzeichnis).

Kombiniert mit familienfilm.toml: Du kannst einen Kategorien-Baum anlegen, jede Ebene ihre eigene Kategorie — und trotzdem mit einem einzigen publish-dir -r-Aufruf alles konsistent publizieren.

Bei einem erneuten publish werden die Werte automatisch aus der Sidecar-Datei gelesen – CLI-Parameter überschreiben gespeicherte Werte. Die Web-ID wird nach erfolgreicher Erstellung automatisch gespeichert, damit bei erneutem Publish die gleiche ID wiederverwendet wird (gleiche URL bleibt stabil).

Die Sidecar-Datei wird bei der Archivierung automatisch mit ins ISO aufgenommen.

Deaktivieren: --no-sidecar (pro Aufruf) oder familienfilm-manager config set sidecar.enabled false (global).


Konfiguration

Einstellungen werden in ~/.config/familienfilm-manager/config.toml gespeichert.

Befehle

# Wert speichern
familienfilm-manager config set <schlüssel> "<wert>"

# Einzelnen Wert lesen
familienfilm-manager config get <schlüssel>

# Alle gespeicherten Werte anzeigen
familienfilm-manager config list

Erlaubte Schlüssel

Schlüssel Beschreibung Standard
targets.infuse rclone-Ziel für Infuse (z.B. nas:/media/videos/) (leer)
targets.web rclone-Ziel für Webserver (z.B. azure:container/shares/) (leer)
targets.archive rclone-Ziel für Archiv (z.B. nas:/archive/familienfilme/) (leer)
infuse.group_by Gruppierung: year oder month year
defaults.category Standard-Kategorie für Videos (leer)
sidecar.enabled Sidecar-Dateien automatisch lesen/schreiben true
cleanup.web_workdir Temporäres Web-Arbeitsverzeichnis nach erfolgreichem Deployment löschen true
paths.work_dir Standard-Arbeitsverzeichnis für temporäre Dateien (lokaler SSD bei SMB-Quellen empfohlen) (leer)
watch.directories Zu überwachende Verzeichnisse (komma-separiert) — siehe watch-dir (leer)
watch.interval_seconds Intervall zwischen Watch-Ticks in Sekunden 86400 (24h)
watch.stability_window_seconds Wartezeit zur Erkennung wachsender Dateien (0 = aus) 60
mediaset.branding_base_url Stamm-URL für Web-Mediasets und OG-Tags (leer)
mediaset.branding_site_name Site-Name (sichtbar im Header + OG-Meta) (leer)
tools.ffmpeg Pfad zur ffmpeg-Binärdatei ffmpeg
tools.ffprobe Pfad zur ffprobe-Binärdatei ffprobe
tools.rclone Pfad zur rclone-Binärdatei rclone

Beispiel

familienfilm-manager config set targets.infuse "nas:/media/familienfilme/"
familienfilm-manager config set targets.web "azure:kurmann-glueck/shares/"
familienfilm-manager config set targets.archive "nas:/archive/familienfilme/"
familienfilm-manager config set defaults.category "Familie Kurmann-Glück"
familienfilm-manager config set mediaset.branding_base_url "https://kurmannmedia.blob.core.windows.net/kurmann-glueck/"

Arbeitsverzeichnis bei SMB-Quellen

Wenn die Quellvideos auf einem SMB-/NAS-Laufwerk liegen, sollte ein lokales Arbeitsverzeichnis konfiguriert werden, damit Komprimierung und temporäre Dateien nicht über das Netzwerk laufen:

familienfilm-manager config set paths.work_dir "~/Movies/.familienfilm-tmp"

Dann werden bei jeder Publikation:

  • Quellvideo gelesen vom SMB
  • Sidecar .settings.toml geschrieben auf SMB (klein)
  • Komprimierung, Thumbnails, Web-Output: lokal im Work-Dir
  • Web-Deployment: rclone push vom lokalen Work-Dir zum Webserver

Resolution: CLI --work-dir > Config paths.work_dir > Quellverzeichnis.


Verwendung (Python API)

from pathlib import Path
from familienfilm_manager.api import (
    PublishRequest,
    RuntimeOptions,
    publish,
)

request = PublishRequest(
    source_path=Path("/pfad/zu/video.m4v"),
    title="Wanderung auf den Napf",
    category="Familie Kurmann-Glück",
    recording_date="2025-03-24",
)

runtime = RuntimeOptions(
    infuse_target="nas:/media/familienfilme/",
    web_target="azure:kurmann-glueck/shares/",
    archive_target="nas:/archive/familienfilme/",
    branding_base_url="https://example.com/shares/",
)

result = publish(request, runtime)

if result.success:
    print(f"Infuse: {result.infuse_dir} (deployed: {result.infuse_deployed})")
    print(f"Web: {result.web_dir} (deployed: {result.web_deployed})")
    print(f"Archiv: {result.archived}")
else:
    print(f"Fehler: {result.error_message}")

Öffentliche API-Exporte

from familienfilm_manager.api import (
    publish,                 # Gesamtworkflow
    publish_directory,       # Batch über ein Verzeichnis
    watch_directories,       # Endlosschleife / Single-Shot über mehrere Verzeichnisse
    deploy_infuse,           # Nur Infuse-Deployment
    deploy_web,              # Nur Web-Deployment
    archive,                 # Nur Archivierung
    PublishRequest,          # Fachlicher Request
    PublishResult,           # Ergebnis
    DirectoryPublishResult,  # Batch-Ergebnis
    VideoStatus,             # Status eines Videos im Batch
    VideoStatusKind,         # PUBLISHED/SKIPPED/FAILED/PENDING/UNSTABLE
    WatchRequest,            # Watch-Request
    WatchResult,             # Watch-Gesamtergebnis
    WatchTickResult,         # Ergebnis eines einzelnen Ticks
    DeployRequest,           # Deploy-Request
    DeployResult,            # Deploy-Ergebnis
    ArchiveRequest,          # Archiv-Request
    ArchiveResult,           # Archiv-Ergebnis
    RuntimeOptions,          # Technische Optionen
    FamilienfilmEvent,       # Fortschritts-Event
    FamilienfilmStage,       # Stage-IDs
)

Lizenz

MIT

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_familienfilm_manager-0.6.0.tar.gz (78.2 kB view details)

Uploaded Source

Built Distribution

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

kurmann_familienfilm_manager-0.6.0-py3-none-any.whl (60.0 kB view details)

Uploaded Python 3

File details

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

File metadata

File hashes

Hashes for kurmann_familienfilm_manager-0.6.0.tar.gz
Algorithm Hash digest
SHA256 fa7a4188c192a19529ecd333ec48583cbf5f45efa13fc9ca5720b00d54f63b0e
MD5 e8b437b8af4e1f85273bb3e3eef6d067
BLAKE2b-256 9840a4b375cea5664a56bfc5d79f95a4861e338026da881ac6318e661384f0d9

See more details on using hashes here.

Provenance

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

Publisher: publish.yml on kurmann/familienfilm-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_familienfilm_manager-0.6.0-py3-none-any.whl.

File metadata

File hashes

Hashes for kurmann_familienfilm_manager-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bc97096e3e79e184c78155b7025889e3acee42d77e6af2de2613f2b8ecb6630b
MD5 fac166e1572ae4a83ea11c98986116af
BLAKE2b-256 0fb2e46f68295f1f1a2a59218eafdcd733b3d584c0dc90db5667ded7c24c07aa

See more details on using hashes here.

Provenance

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

Publisher: publish.yml on kurmann/familienfilm-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