Prune stems whose source song was removed or replaced
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5b7fadb7f7
commit
0fc35b13e8
7 files changed
+133
-3
No files matched your search
+29
-2
@@ -21,6 +21,9 @@ Settings (environment):
|
||||
DEVICE cuda cuda, cuda:N or cpu
|
||||
RESCAN_MIN 30 minutes between scans once caught up
|
||||
AUTO_SCAN 0 1 = scan the library on a timer; 0 = only separate Stem Now requests
|
||||
PRUNE 1 remove stems whose song left the library; 0 = off
|
||||
PRUNE_CHANGED 0 1 = also remove stems of songs replaced in place (redone by the next scan)
|
||||
PRUNE_MAX 0.2 skip a prune that would remove more than this share of the stems
|
||||
FP16 1 half precision on the GPU
|
||||
OVERLAP / SEGMENT / SHIFTS as in the desktop app's settings
|
||||
"""
|
||||
@@ -40,8 +43,8 @@ sys.path.insert(0, os.path.join(_ROOT, "desktop")) # in the image the package s
|
||||
sys.path.insert(0, _ROOT)
|
||||
|
||||
from stemify.catalog import MODELS_BY_ID # noqa: E402
|
||||
from stemify.library_core import (MARKER, MAX_SECONDS, SOURCE_RANK, duration, is_done, is_share_error, # noqa: E402
|
||||
iter_tracks, signature, write_track)
|
||||
from stemify.library_core import (MARKER, MAX_SECONDS, SOURCE_RANK, duration, find_stale, is_done, # noqa: E402
|
||||
is_share_error, iter_tracks, remove_stems, signature, write_track)
|
||||
|
||||
MUSIC_DIR = os.environ.get("MUSIC_DIR", "/music")
|
||||
STEMS_DIR = os.environ.get("STEMS_DIR", "/stems")
|
||||
@@ -51,6 +54,9 @@ MODEL = os.environ.get("MODEL", "roformer_bs_sw")
|
||||
DEVICE = os.environ.get("DEVICE", "cuda")
|
||||
RESCAN_S = float(os.environ.get("RESCAN_MIN", "30")) * 60
|
||||
AUTO_SCAN = os.environ.get("AUTO_SCAN", "0") in ("1", "true", "yes")
|
||||
PRUNE = os.environ.get("PRUNE", "1") not in ("0", "false", "no", "")
|
||||
PRUNE_CHANGED = os.environ.get("PRUNE_CHANGED", "0") in ("1", "true", "yes")
|
||||
PRUNE_MAX = float(os.environ.get("PRUNE_MAX", "0.2"))
|
||||
FP16 = os.environ.get("FP16", "1") not in ("0", "false", "no", "")
|
||||
OVERLAP = float(os.environ.get("OVERLAP", "0.25"))
|
||||
SEGMENT = float(os.environ.get("SEGMENT", "0"))
|
||||
@@ -331,6 +337,26 @@ def serve_queue(sep, failed):
|
||||
return used
|
||||
|
||||
|
||||
def prune():
|
||||
"""Remove stems whose song is gone from MUSIC_DIR (and optionally replaced ones)."""
|
||||
if not PRUNE:
|
||||
return
|
||||
orphans, changed = find_stale(MUSIC_DIR, STEMS_DIR)
|
||||
drop = orphans + (changed if PRUNE_CHANGED else [])
|
||||
if changed and not PRUNE_CHANGED:
|
||||
log(f"prune: {len(changed):,} stems are of a replaced song (PRUNE_CHANGED=1 removes them)")
|
||||
if not drop:
|
||||
return
|
||||
total = sum(1 for _ in iter_tracks(MUSIC_DIR, STEMS_DIR))
|
||||
kept = total - len(orphans)
|
||||
if kept <= 0 or len(drop) > PRUNE_MAX * (kept + len(drop)):
|
||||
log(f"prune: refusing to remove {len(drop):,} of {kept + len(drop):,} stems "
|
||||
f"(over PRUNE_MAX {PRUNE_MAX:.0%}, or the music share looks empty); run server/prune.py --apply to force")
|
||||
return
|
||||
remove_stems(STEMS_DIR, drop)
|
||||
log(f"prune: removed {len(drop):,} stems folders no longer in the library")
|
||||
|
||||
|
||||
def run_pass(sep, failed):
|
||||
"""Separate everything that needs it. Returns (tracks done, whether the GPU was used)."""
|
||||
t0 = time.monotonic()
|
||||
@@ -404,6 +430,7 @@ def main():
|
||||
log("AUTO_SCAN off: only Stem Now requests will be separated")
|
||||
while not stop.is_set():
|
||||
try:
|
||||
prune()
|
||||
if not AUTO_SCAN:
|
||||
idle(sep, failed, RESCAN_S)
|
||||
continue
|
||||
|
||||
Reference in new issue
Block a user