Compare commits

...

2 Commits
main ... dev

Author SHA1 Message Date
Roncero Blanco, Edgar
f7ee691b4d Better split algorithm 2025-05-26 20:17:05 +02:00
Roncero Blanco, Edgar
a701e3f97a POSIX compatible 2025-05-26 19:02:37 +02:00
2 changed files with 47 additions and 28 deletions

View File

@ -3,10 +3,10 @@ import shutil
from pathlib import Path
from mutagen.id3 import ID3, TBPM, ID3NoHeaderError
from datetime import datetime
from collections import defaultdict
import configparser
import sys
import librosa
import warnings
GROUP_SIZE = 5
@ -20,6 +20,7 @@ def load_config():
print("config.ini created from def_config.ini with default settings.")
else:
print("Error: def_config.ini not found! Please create it and rerun.")
input("Press Enter to exit...")
sys.exit(1)
default_config = configparser.ConfigParser()
@ -36,7 +37,9 @@ def load_config():
def analyze_bpm_librosa(file_path):
try:
y, sr = librosa.load(file_path, mono=True)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
y, sr = librosa.load(file_path, mono=True)
tempo, _ = librosa.beat.beat_track(y=y, sr=sr)
return int(round(float(tempo)))
except Exception as e:
@ -49,7 +52,6 @@ def write_bpm_tag(file_path, bpm):
tags = ID3(file_path)
except ID3NoHeaderError:
tags = ID3()
tags.delall("TBPM")
tags.add(TBPM(encoding=3, text=str(bpm)))
tags.save(file_path)
@ -67,14 +69,11 @@ def get_bpm(file_path):
pass
return None
def split_evenly(lst, n):
k, m = divmod(len(lst), n)
return [lst[i*k + min(i, m):(i+1)*k + min(i+1, m)] for i in range(n)]
def main():
config = load_config()
CD_SIZE = config.getint("Settings", "SplitFolderMB") * 1024 * 1024
SAFETY_MARGIN = 1024 * 1024 * 2 # 2 MB buffer
CD_SIZE = config.getint("Settings", "SplitFolderMB") * 1024 * 1024 - SAFETY_MARGIN
bWriteNonPresentBPM = config.getboolean("Settings", "bWriteNonPresentBPM")
bCheckAllTracksBPM = config.getboolean("Settings", "bCheckAllTracksBPM")
@ -85,6 +84,7 @@ def main():
if not source_media_path.exists() or not source_media_path.is_dir():
print(f"Error: {source_media_path} is not a valid directory.")
input("Press Enter to exit...")
sys.exit(1)
all_tracks = []
@ -103,14 +103,12 @@ def main():
write_bpm_tag(file, bpm)
size = file.stat().st_size
if bpm is None:
bpm_range = "[Unknown BPM]"
else:
bpm_range = f"{(bpm // GROUP_SIZE) * GROUP_SIZE}-to-{((bpm // GROUP_SIZE) * GROUP_SIZE) + GROUP_SIZE - 1}"
bpm_range = f"{(bpm // GROUP_SIZE) * GROUP_SIZE}-to-{((bpm // GROUP_SIZE) * GROUP_SIZE) + GROUP_SIZE - 1}" if bpm else "[Unknown BPM]"
all_tracks.append({"file": file, "size": size, "bpm_range": bpm_range})
if not all_tracks:
print("No MP3 files found.")
input("Press Enter to exit...")
sys.exit(0)
parent = source_media_path.parent
@ -118,27 +116,24 @@ def main():
dest_media_path = parent / f"[CDs-{run_date}]{folder_name}"
dest_media_path.mkdir(parents=True, exist_ok=True)
total_size = sum(t["size"] for t in all_tracks)
num_cds = max(1, (total_size + CD_SIZE - 1) // CD_SIZE)
all_tracks.sort(key=lambda x: -x["size"]) # Sort by size descending for better packing
print(f"Total size: {total_size / 1024**2:.2f} MB, splitting into {num_cds} CDs")
cd_contents = []
current_cd = []
current_size = 0
bpm_groups = defaultdict(list)
for track in all_tracks:
bpm_groups[track["bpm_range"]].append(track)
if current_size + track["size"] > CD_SIZE:
cd_contents.append(current_cd)
current_cd = []
current_size = 0
current_cd.append(track)
current_size += track["size"]
for bpm_range in bpm_groups:
bpm_groups[bpm_range].sort(key=lambda x: x["file"].name)
if current_cd:
cd_contents.append(current_cd)
bpm_chunks = {}
for bpm_range, tracks in bpm_groups.items():
bpm_chunks[bpm_range] = split_evenly(tracks, num_cds)
cd_contents = [[] for _ in range(num_cds)]
for bpm_range in bpm_chunks:
for i, chunk in enumerate(bpm_chunks[bpm_range]):
cd_contents[i].extend(chunk)
print(f"Total size: {sum(t['size'] for t in all_tracks) / 1024**2:.2f} MB, splitting into {len(cd_contents)} CDs")
for i, tracks in enumerate(cd_contents, start=1):
cd_folder = dest_media_path / f"CD-{i:02}"
@ -152,6 +147,7 @@ def main():
print(f"[WRITE] CD-{i:02}: {len(tracks)} tracks, approx {size_accum / 1024**2:.2f} MB")
print("\n✓ Done!")
input("Press Enter to exit...")
if __name__ == "__main__":
main()

23
Run.sh Normal file
View File

@ -0,0 +1,23 @@
#!/bin/bash
set -e # exit on error
VENV_DIR=venv
APP_DIR=Program
PYTHON=$VENV_DIR/bin/python
# Check if virtual environment exists
if [ ! -d "$VENV_DIR" ]; then
echo "Creating virtual environment..."
python3 -m venv "$VENV_DIR"
echo "Installing dependencies..."
"$PYTHON" -m pip install --upgrade pip
"$PYTHON" -m pip install -r requirements.txt
else
echo "Virtual environment found, assuming dependencies are satisfied."
fi
# Run the app
cd "$APP_DIR"
../"$PYTHON" app.py