5eaae8e813
playlist_service: CRUD for the playlists table, playlists.json export,
regen.sh invocation, and a one-time seed_legacy() importing the 17-entry
legacy array. Creating/updating a playlist automatically re-renders confs
and re-patches credentials into any newly-generated .conf file.
credential_service: encrypted credential storage (via security/crypto.py)
and per-scope rendering to the exact files the pipeline scripts read --
every <playlist>.conf (spotify/soulseek), navidrome/admin.env,
bandcamp/config.env+cookies.txt, azuracast/api_key, qobuz/{token,app_id,region},
telegram/notify.env. set_credentials() batches multi-field saves so a render
never sees a half-populated scope.
Also fixes a real bug found via integration testing: regen.sh's embedded
python3 -c snippet used backslash-escaped quotes inside a single-quoted
bash string, which is invalid Python syntax (backslash passed through
literally) -- switched to double-quoted bash wrapper + single-quoted Python
strings.
Verified end-to-end: seeded 17 playlists, regenerated all 17 .conf files,
saved spotify/soulseek/navidrome credentials and confirmed correct
patching into rendered files (including bash-sourcing admin.env with
special characters in the password), and confirmed delete/create both
correctly add/remove .conf files with credentials pre-patched on create.
51 lines
1.7 KiB
Bash
Executable File
51 lines
1.7 KiB
Bash
Executable File
#!/bin/bash
|
|
# ${PIPELINE_DIR:-/app/pipeline}/lib/prep-audio.sh
|
|
#
|
|
# Shared helper sourced by run-playlist.sh and import-track.sh.
|
|
# Pre-tags newly-arrived audio with ReplayGain (loudgain, track-mode) and
|
|
# Liquidsoap autocue tags (cue_file from Moonbase59/autocue) before beets
|
|
# ingests them, so AzuraCast sees fully-prepped files the moment they land
|
|
# in /music.
|
|
#
|
|
# Usage: prep_audio <scan_dir> <log_file>
|
|
# Returns: number of files processed (via stdout)
|
|
|
|
prep_audio() {
|
|
local scan_dir="$1"
|
|
local log="$2"
|
|
|
|
local files=()
|
|
while IFS= read -r -d '' f; do
|
|
files+=("$f")
|
|
done < <(find "$scan_dir" -type f \
|
|
\( -iname "*.flac" -o -iname "*.mp3" -o -iname "*.m4a" \
|
|
-o -iname "*.ogg" -o -iname "*.opus" \) -print0)
|
|
|
|
if [[ ${#files[@]} -eq 0 ]]; then
|
|
echo 0
|
|
return 0
|
|
fi
|
|
|
|
echo "[prep-audio] loudgain (track-mode RG, clip-safe) on ${#files[@]} file(s)" >>"$log"
|
|
# -q quiet, -k lower track gain to avoid clipping >-1 dBFS,
|
|
# -s e write extended ReplayGain2 + R128 tags, -I 4 ID3v2.4 for MP3.
|
|
# No -a, so each file gets its own track gain (track-mode).
|
|
if ! loudgain -q -k -s e -I 4 "${files[@]}" >>"$log" 2>&1; then
|
|
echo "[prep-audio] loudgain returned non-zero (see log)" >>"$log"
|
|
fi
|
|
|
|
echo "[prep-audio] cue_file (autocue liq_* tags) on ${#files[@]} file(s)" >>"$log"
|
|
# -w write tags into file, -k true-peak clipping prevention.
|
|
# Skips files that already have liq_cue_file=true (use -f to force).
|
|
local failed=0
|
|
for f in "${files[@]}"; do
|
|
if ! cue_file -w -k "$f" >>"$log" 2>&1; then
|
|
echo "[prep-audio] cue_file failed on $f" >>"$log"
|
|
failed=$((failed + 1))
|
|
fi
|
|
done
|
|
[[ $failed -gt 0 ]] && echo "[prep-audio] cue_file errors: $failed" >>"$log"
|
|
|
|
echo "${#files[@]}"
|
|
}
|