Managing music
The upload folder
Section titled “The upload folder”The media-service watches uploads/ in your music folder. You can copy with any tool:
a Samba share, scp, rsync or a file manager. Copied files need write access for the group
hifi (GID 10001), so bitwerk can move them into the library; the installer prepares the folder for this
(permissions). A library that bitwerk only reads (read-only or NAS,
MUSIC_READ_ONLY=true) has no uploads.
- It only processes a file once it has been unchanged for 2.5 seconds and its size no longer
changes (
UPLOAD_DEBOUNCE_MS). Half-copied files are therefore never touched. - Temporary files from rsync (
.name.XXXX), browsers (*.crdownload) or WinSCP (*.filepart) are ignored. - You can push in whole folders at once. The service cleans up empty folders afterwards.
Uploading in the browser
Section titled “Uploading in the browser”In the web UI, Settings → Library → Upload music takes files and whole folders: drop them on the box or use
Choose files or Choose folder. Folders keep their structure, so cue sheets and cover images stay with their
album. The files are collected first and only reach uploads/ once all of them have arrived, then they are sorted
like anything else you copy in; the results appear under Recent uploads. Hidden files (.DS_Store) and system
files (Thumbs.db, desktop.ini, the macOS folder icon) are left out. A file may be up to 4 GB
(UPLOAD_MAX_FILE_MB); bigger ones you copy into uploads/ as before.
The upload keeps running while you look at other tabs, and the Library tab shows its progress again when you come
back. Closing or reloading the page while it runs asks first. An upload you abandon (page closed, network lost) is
removed from the server after a day (UPLOAD_STAGING_TTL_HOURS).
Samba share
Section titled “Samba share”To drop albums from Windows or macOS (Finder: Go → Connect to Server, smb://<server>/bitwerk-uploads), share
uploads/ with Samba on the server:
sudo apt install sambaAdd a share to /etc/samba/smb.conf; force group and the masks make every file writable for the group hifi,
so bitwerk can sort it:
[bitwerk-uploads] path = /srv/bitwerk/music/uploads valid users = @hifi read only = no force group = hifi create mask = 0664 force create mode = 0664 directory mask = 2775 force directory mode = 2775Give your user (a member of hifi, the installer adds the one that ran it) a Samba password and reload:
sudo smbpasswd -a "$USER"sudo systemctl reload smbdShare only uploads/: library/ is where bitwerk sorts to. Windows and macOS write temporary and hidden files
(.DS_Store, ._*); bitwerk ignores hidden
files.
Where files end up
Section titled “Where files end up”library/└── Pink Floyd/ └── The Dark Side of the Moon/ ├── 01 - Speak to Me.flac ├── 02 - Breathe.flac └── cover.jpgThe rules for this:
- Artist folder: album artist, otherwise artist. This keeps compilations together.
- Without an album tag: folder “Unknown Album”.
- Without a track number: no prefix. From disc 2 the prefix is
D-NN, for example2-01. - Invalid characters (
/ \ : * ? " < > |) are replaced. - Name collision: append
(2). Nothing is ever overwritten.
Required tags are title and artist. If one of them is missing, the file is unreadable or the format
unknown, it ends up in uploads/_unsorted/. The list under Settings → Uploads shows the
reason. It is best to fix tags beforehand with MusicBrainz Picard and then
put the file into uploads/ again.
Entering tags by hand
Section titled “Entering tags by hand”In the web UI, Settings → Library → Unsorted files lists what waits in uploads/_unsorted/. Enter tags
opens a form that starts from the tags the file has; fill in at least the title and the artist and choose
Import. bitwerk sorts the file into the library with these tags and keeps them on every rescan, but it never
changes the audio file itself, so other programs still see its original tags.
Supported formats
Section titled “Supported formats”FLAC, ALAC/AAC (.m4a), WAV, AIFF, MP3, Ogg Vorbis, Opus, WavPack, APE and DSD (.dsf). The following
is captured:
- codec and container,
- sample rate and bit depth (incl. float),
- channel layout and duration.
From this the quality badge is built, for example “24-bit / 96 kHz FLAC” or “DSD128 (5.6 MHz)”.
Cover art
Section titled “Cover art”- Embedded image: the front cover takes priority.
- Image in the album folder:
cover,folder,front,albumoralbumartwith the extension.jpg,.pngor.webp.
Folder images in an upload wait until the audio files of the folder are imported, and then go into the album with them. Covers are cached once per content (SHA-256).
Loudness (ReplayGain / EBU R128)
Section titled “Loudness (ReplayGain / EBU R128)”- Existing tags are taken over:
REPLAYGAIN_*, for OpusR128_*. - If they are missing, the media-service measures the loudness according to EBU R128 (integrated loudness, true peak) and computes ReplayGain 2.0 with −18 LUFS as the reference.
- The album gain is derived from all tracks of the album.
- In the background: a scan makes new tracks browsable and playable right after their tags are read; the loudness and file quality are measured afterwards at the lowest CPU priority, one core left free. A track that is about to play is measured first. Until then a player uses the ReplayGain tags where the file has them.
- Settings: in the web UI’s server settings an admin switches the loudness and the quality analysis on or off
and sets how many CPU cores the analysis uses (
auto: all but one). A change applies within seconds, without a restart.
Whether matching is applied (off, track, album) is set per player under Settings → Player.
File quality
Section titled “File quality”The scan also checks what each file really holds: lossy files and their bitrate, lossless files made from an MP3 or
a CD (“fake hi-res”), 24-bit files that carry only 16 bits, clipping, very compressed masters and files that do not
decode cleanly (broken frames, cut off, FLAC checksum errors). The first scan after an update analyzes the existing
library once; SKIP_QUALITY_ANALYSIS=true turns it off.
Cue sheets
Section titled “Cue sheets”An album as a single file with a cue sheet appears in the library as individual tracks:
Album.flacwithAlbum.cuenext to it (UTF-8 or Windows-1252),- or an embedded cuesheet (FLAC
CUESHEETblock, Vorbis commentCUESHEET).
The file stays unchanged, so checksums and AccurateRip logs remain valid. The tracks play sample-accurately and run into each other gaplessly. A faulty cue sheet leads to a warning, and the file is imported as a single track.
DSF files are imported with their ID3 tags. How they are played depends on the DAC:
- native:
HIFI_DSD=native - as DoP:
HIFI_DSD=dop - as PCM: DSD→PCM conversion if the DAC cannot do DSD
Library scan
Section titled “Library scan”On start the media-service reconciles library/ with the catalog. The scan runs in the background: web UI,
playback and uploads work normally in the meantime.
- New and changed files are read and measured. If tags are missing, the values come from the folder structure.
- Unchanged files (same size and modification time) are not even opened. A restart with a large library therefore takes only seconds.
- New cover art or a changed cue sheet in a folder: that folder is read again.
- Deleted files disappear from the catalog.
You can see the progress in the web UI under Settings → Uploads: status, “x of y files”, how many are unchanged or newly indexed, and the files with errors.
The media-service also looks again every 10 minutes (RESCAN_INTERVAL_SECS, 0 turns it off), and Rescan in
Settings → Library of the web UI starts a rescan right away. A rescan picks up uploads the watcher missed (a NAS
or network share that sends no file events), files copied into or deleted from library/ and fixed permissions.
When it finds something while the Library tab is open, a notice says what.
Large libraries
Section titled “Large libraries”The initial import measures the loudness of every file without ReplayGain tags, which is the expensive part. For this the scan processes
as many files in parallel as the server has CPU cores. You set this with SCAN_CONCURRENCY, for example
lower on a NAS with a slow hard drive or when the server has other tasks on the side:
SCAN_CONCURRENCY=2 # e.g. in /opt/bitwerk/.env, then: sudo docker compose up -dIf you want to re-read all files regardless of modification time, start once with FULL_LIBRARY_SCAN=true.
Measurements of unchanged files are kept.
If library/ is completely empty, for example because the disk is not mounted, nothing is deleted.
Files you copy directly into library/ appear after a restart of the media-service:
cd /opt/bitwerk && sudo docker compose restart media-service