Declare a library

A Library is one root directory on one volume, holding media of one kind. This guide declares one, reads what it reports, and describes what its namespace decides.

The declaration

A Library names a claim in its namespace, a directory inside it, and the kind that directory holds:

apiVersion: library.liken.sh/v1alpha1
kind: Library
metadata:
  name: movies
  namespace: media
spec:
  storage:
    claim: movies-pvc
    root: /media/movies
  kind: movies
  movies: {}

The block named by kind must be present, and the other kinds' blocks must not. An empty block is a complete one. The kinds are movies, series, and franchises. A series library holds one folder per series with a season folder inside. A franchises library is the one kind whose files are written by people, and Franchises covers it.

root defaults to / and must be absolute, so one volume can hold several libraries at different roots. The kind and the storage are immutable. A different volume, a different root, or a different kind is a different Library.

Library describes every field. The ones you are likely to set:

What it reports

The listing shows the counts and the phase:

$ kubectl -n media get libraries
NAME     KIND     TITLES   ITEMS   FILES   WAITING   STATUS   READY   AGE
movies   movies   128      128     560     1         Idle     True    12d

Titles is what the last walk cataloged. Items counts movies, or series and episodes together. Files counts the video files with their sidecars, art, subtitles, and trickplay directories. Waiting counts the titles a provider returned candidates for, which a person resolves by naming the right uniqueid in the .nfo. With -o wide the listing adds the claim and the Unidentified count, the folders the walk could not name, which are still browsable under their folder names.

Status is the phase. Pending means the storage, the catalog pod, or the schedule is not ready yet. Scanning and Enriching name the Job that runs. Idle is the state between them. Failed means the last scan Job failed and wrote no rows. Offline means the namespace’s reporter has left the bus. Departing means a deleted Library is still removing its rows from the catalog.

Four conditions report why the phase is what it is:

status.runs holds the last run of each worker: scan, rescan, enrich, and cleanup, with its Job, its times, and its failure if it had one. status.webhook is the address that rescans one folder; Webhooks gives it to Radarr, Sonarr, and Jellyfin.

The namespace is a boundary

Every Library in a namespace writes into that namespace’s one catalog, and every screen in the namespace shows that catalog. So a Library waits with the reason NoCatalog until the namespace holds a Catalog, and two Catalogs block both. Every catalog row is keyed by its library, so two libraries in one namespace never touch each other’s rows, even on the same relative path or the same provider id.

Put libraries that should show together in one namespace. Put libraries that should never meet on a screen in different namespaces.

How a title is played

When a person plays a title from the browser, the operator creates a Play for media-operator, and the media reference in it names the claim, never the volume behind it:

claim://movies-pvc//media/movies/Some Film (1999)/Some Film (1999).mkv

The claim is the one the screen already mounts read-only, so media-operator plays from the same claim, and no second claim is created. A path outside the library’s root is refused.