foley.index.library#

The SoundLibrary façade — one searchable, license-aware sound library.

Composes the four injected storage concerns behind a stable interface (report 04 §6.1), so each swaps local->cloud with no change to retrieval logic:

SoundLibrary
├── sounds : Mapping[content_key -> bytes]   # audio blobs   (dol.Files -> S3)
├── meta   : Mapping[id -> SoundRecord]       # canonical SSOT (JSON -> S3/PG)
├── vindex : VectorIndex                      # CLAP 512-d    (LanceDB/sqlite/memory)
└── kindex : KeywordIndex (BM25)              # tags+caption  (same, or separate)

Progressive disclosure: SoundLibrary() works out of the box with sensible local defaults (all components lazily constructed), while every store, index, and the embedder is an optional keyword injection (open-closed). The library is a read-only Mapping of SoundRecord`s (``lib[sound_id]`); add() is the write path that stores bytes and updates both indexes.

search embeds the query, runs the vector KNN and the BM25 keyword search, and RRF-fuses them (foley.index.search) — nothing here changes between the in-memory, LanceDB, or sqlite backends, or between local and cloud storage.

Functions

default_library()

The process-wide default library (local stores + CLAP + best index).

Classes

SoundLibrary(*[, sounds, meta, vindex, ...])

A searchable, license-aware library of sounds (the foley INDEX façade).

class foley.index.library.SoundLibrary(*, sounds=None, meta=None, vindex=None, kindex=None, embedder=None, data_dir=None, candidate_k=50, rrf_k=60)[source]#

Bases: Mapping

A searchable, license-aware library of sounds (the foley INDEX façade).

Read it as a Mapping of SoundRecord`s; search it with :meth:`search (text) / search_clip() (a reference clip) / similar() (audio<->audio by id); browse it with filter(); grow it with add().

add(record, *, data=None, vector=None)[source]#

Store a sound and index it (the ingest write path).

Persists bytes via store_sound() (honouring the by-value/by-reference license gate), upserts the CLAP vector into the vector index, and indexes caption``+``tags into the keyword index.

A sound is retrieval-first, so it MUST carry an embedding: supply either data (bytes to embed — note a by-reference sound is embedded from its transient bytes even though they are not cached) or a precomputed vector. Adding with neither raises, rather than silently indexing a vectorless row (which the single-table LanceIndex cannot persist, producing backend-dependent search results).

Parameters:
  • record (SoundRecord) – The record to add (mutated by store_sound with resolved storage fields, and stamped with the embedding model/dim).

  • data (Optional[bytes]) – The archive bytes (required for by-value storage; also the source for computing vector when it is not supplied).

  • vector (Optional[ndarray]) – A precomputed CLAP embedding; when omitted and data is given, it is computed via the library’s embedder.

Return type:

SoundRecord

Returns:

The same (persisted, indexed) record.

Raises:

ValueError – If neither data nor vector is provided (no way to obtain an embedding).

array(sound_id, *, sr=None, mono=True)[source]#

Decode a sound to a working array (float32).

Parameters:
  • sound_id (str) – The record id.

  • sr (Optional[int]) – Target sample rate (default: the working rate, 48 kHz).

  • mono (bool) – Down-mix to mono (default True).

Return type:

ndarray

Returns:

The decoded working array.

audio(sound_id)[source]#

Return a sound’s archive bytes (by-value from the store, or from a local by-reference path).

Parameters:

sound_id (str) – The record id.

Return type:

bytes

Returns:

The raw archive bytes.

Raises:

LookupError – If the bytes are neither cached (by-value) nor readable from a local uri — a remote by-reference sound needs its source adapter (subtask #5) to fetch.

property data_dir: Path#

The data root for default stores/index.

property embedder#

The text<->audio embedder (CLAP by default).

filter(**facets)[source]#

Browse the library by metadata facets (no ranking).

Accepts the same facet keywords as search()’s filters (commercial_ok, ucs_category, min_snr, duration_range) plus any record_attr=value equality predicate.

Return type:

list[SoundRecord]

property kindex#

The keyword index.

property meta#

The metadata store (id -> SoundRecord).

search(query, *, k=10, filters=None, commercial_ok=None, ucs_category=None, min_snr=None, duration_range=None, rerank=False)[source]#

Hybrid (CLAP vector ⊕ BM25) search for a text query.

Parameters:
  • query (str) – The natural-language query.

  • k (int) – Number of results to return.

  • filters (Optional[dict]) – Extra {record_attr: value} equality predicates.

  • commercial_ok (Optional[bool]) – If True, keep only commercially-usable sounds.

  • ucs_category (Optional[str]) – Keep only sounds with this UCS CatID.

  • min_snr (Optional[float]) – Keep only sounds whose QC snr_db is at least this.

  • duration_range (Optional[tuple[float, float]]) – Keep only sounds whose duration_s is in (min, max).

  • rerank (bool) – Re-order the shortlist by direct query<->audio cosine (fills the CLAP score for keyword-only hits).

Return type:

list[Candidate]

Returns:

Up to k :class:`~foley.base.Candidate`s, best first.

search_clip(clip, *, sr=None, k=10)[source]#

Search by a reference audio clip (audio<->audio via CLAP).

Parameters:
Return type:

list[Candidate]

Returns:

Up to k :class:`~foley.base.Candidate`s, most-similar first.

similar(sound_id, *, k=10)[source]#

Return the k sounds most similar to sound_id (audio<->audio).

Uses the stored vector (no re-decoding); the query sound itself is excluded from the results.

Return type:

list[Candidate]

property sounds#

The content-addressed byte store.

update_record(record)[source]#

Rewrite a stored record’s metadata and re-index its keyword text.

For corrections that do not touch the audio (a re-stamped licence, a removed caption): the bytes and the CLAP vector stay as they are.

Raises:

KeyError – If record.id is not in the library.

Return type:

SoundRecord

property vindex#

The vector index.

foley.index.library.default_library()[source]#

The process-wide default library (local stores + CLAP + best index).

Return type:

SoundLibrary