Compare commits

..

No commits in common. "dev" and "main" have entirely different histories.
dev ... main

2 changed files with 28 additions and 47 deletions

View File

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

23
Run.sh
View File

@ -1,23 +0,0 @@
#!/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