6.7 KiB
audio-library-manager
audio-library-manager maintains a music library in two forms:
- a source FLAC tree, optionally normalised so FLAC files do not exceed a configured sample rate; and
- a mirrored Opus tree, where FLAC files are converted to
.opusand non-FLAC sidecar files are copied unchanged.
The current entry point is audio-manager.rkt, exported as the function
audio-manager from main.rkt.
The implementation is intentionally simple. It is a command-line batch process: scan files, compare with the saved state, run a small ordered set of processing steps, write the state, send a report. It does not use places, channels, threads or a worker protocol.
Requirements
Racket packages:
racket-audiosimple-inisimple-lognet-lib
Native libraries are provided or loaded by racket-audio. For the current audio
path this normally means FLAC, Opus/Opusenc, TagLib and SoXR. FFmpeg is not part
of the intended FLAC-to-Opus path; it is only relevant for racket-audio features
that need FFmpeg-based decoding.
Usage
From a Racket REPL or a small wrapper script:
#lang racket/base
(require audio-library-manager)
(audio-manager "/mnt/music" "/mnt/music-opus")
The first argument is the source music tree. The second argument is the target Opus mirror tree.
The optional log level defaults to debug:
(audio-manager "/mnt/music" "/mnt/music-opus" #:log-level 'info)
Files created in the source tree
The manager stores its administration files in the source directory:
.audio-manager.ini— configuration, read withsimple-ini..audio-manager.db— serialized state hash, keyed by normalized relative paths..audio-manager.log— log file.
State keys are normalized relative paths from the source tree. Absolute mount
points are not stored, and path separators are normalized to /. This makes the
state less dependent on the local mount point used on a particular machine.
Configuration
The manager expects a configuration file at:
<source-tree>/.audio-manager.ini
Example:
[flac]
max-khz=48000
[opus]
kbps=224
[mail]
from=Audio Manager <audio@example.org>
to=Hans <hans@example.org>
server=smtp.example.org
port=25
user=
passwd=
The mail section is currently required. If the mail configuration is missing or incomplete, the manager fails at startup with a configuration error. This is intentional: a batch run should not silently skip reporting.
Processing model
The manager uses a file walker with an ordered processing pipeline. Each step receives:
base-path path info
and returns the same three values, with info possibly enriched. The info hash
contains the relative path, type, extension, state and any metadata discovered by
earlier steps.
The important file states are:
new— the relative path was not present in the saved state.changed— the path existed before, but type, size or modification time changed.unchanged— the path exists and its basic filesystem state is unchanged.deleted— the path existed in the saved state but no longer exists in the source tree.
For unchanged entries, the previous enriched info hash is reused. For changed
entries, the previous info hash is reused but marked as changed and updated
with the current type, size and modification time. Stages must therefore treat
changed as the signal to re-inspect content-dependent data.
The pipeline is grouped conceptually as:
- enrichment: normalize/identify known extensions, sniff audio files, detect FLAC-with-ID3, and read FLAC sample rate/bit depth when needed;
- conversion/actions: downsample FLAC files above the configured rate, embed a sidecar cover image when a FLAC has no embedded picture, convert FLAC to Opus, and copy non-FLAC sidecar files;
- cleanup/logging: remove target files for deleted source entries and log progress.
FLAC handling
FLAC files are detected by extension and confirmed by racket-audio sniffing.
A file with extension .flac but an ID3 prefix is reported as a FLAC-with-ID3
case. Such files are not treated as ordinary sidecar files.
For valid FLAC files:
- sample rate and bit depth are read through the FLAC decoder;
- files with a sample rate greater than
[flac] max-khzare converted in place throughracket-audio/audio-encoder; - conversion is synchronous and direct;
- if the file has no embedded picture,
cover.jpg,cover.jpeg,folder.jpg,folder.jpeg,cover.pngorfolder.pngin the same directory is embedded as a front-cover picture.
Temporary FLAC files produced by interrupted conversions should be ignored by the scanner. The implementation uses manager-specific temporary names for this purpose.
Opus mirror handling
For every processable FLAC source file, the manager writes a corresponding Opus file under the target tree:
source: album/track.flac
target: album/track.opus
The default bitrate is 224 kbps and can be changed with [opus] kbps.
Non-FLAC files are copied unchanged to the target tree when they are new, changed, or missing from the target. Hidden files are ignored. Typical copied sidecar files include cover images, PDFs, cue sheets and logs.
When a source entry is deleted, the corresponding target entry is removed. For a
deleted FLAC source, the target extension is changed from .flac to .opus.
Renames are deliberately represented as deleted plus new; no rename detection
is attempted.
Logging and report
The manager logs to:
<source-tree>/.audio-manager.log
The report contains sections for:
- FLAC files with ID3 tags;
- FLAC conversions and cover updates;
- Opus conversions;
- file counters for processed, new, changed, unchanged and deleted files;
- failed conversions and failed copies.
At the end of a successful scan the serialized state is written to
.audio-manager.db and the report is sent by mail.
API
(audio-manager music-path opus-path #:log-level [log-level 'debug])
Runs the complete batch process. music-path is the source tree and opus-path
is the target Opus mirror tree. The function returns 'done after a completed
run.
Design notes
The package intentionally keeps responsibilities separated:
audio-manager.rktorchestrates the batch run and owns the pipeline;private/file-walker.rktscans the filesystem and maintains the state model;private/flac-handling.rktcontains FLAC inspection and FLAC downsampling;private/opus-handling.rktcontains FLAC-to-Opus conversion;private/mail.rktsends reports;private/log.rktdefines the logger;private/util.rktcontains small path/date/cover helpers.
The manager does not implement an audio pipeline itself. Audio decoding,
encoding, metadata and resampling are delegated to racket-audio.