Compare commits
4 Commits
1f83bb8517
...
dev
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f7ee691b4d | ||
![]() |
a701e3f97a | ||
![]() |
189645254b | ||
![]() |
a46d810d0a |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -182,3 +182,4 @@ cython_debug/
|
||||
|
||||
# ed1337x
|
||||
config.ini
|
||||
Run.ps1
|
||||
|
@@ -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,9 +37,11 @@ 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[0])))
|
||||
return int(round(float(tempo)))
|
||||
except Exception as e:
|
||||
print(f"Error analyzing BPM for {file_path.name}: {e}")
|
||||
return None
|
||||
@@ -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,13 +84,9 @@ 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)
|
||||
|
||||
parent = source_media_path.parent
|
||||
folder_name = source_media_path.name
|
||||
dest_media_path = parent / f"[CDs-{run_date}]{folder_name}"
|
||||
dest_media_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
all_tracks = []
|
||||
for file in source_media_path.rglob("*.mp3"):
|
||||
bpm = get_bpm(file)
|
||||
@@ -108,37 +103,37 @@ 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)
|
||||
|
||||
total_size = sum(t["size"] for t in all_tracks)
|
||||
num_cds = max(1, (total_size + CD_SIZE - 1) // CD_SIZE)
|
||||
parent = source_media_path.parent
|
||||
folder_name = source_media_path.name
|
||||
dest_media_path = parent / f"[CDs-{run_date}]{folder_name}"
|
||||
dest_media_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
print(f"Total size: {total_size / 1024**2:.2f} MB, splitting into {num_cds} CDs")
|
||||
all_tracks.sort(key=lambda x: -x["size"]) # Sort by size descending for better packing
|
||||
|
||||
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()
|
25
Run.cmd
Normal file
25
Run.cmd
Normal file
@@ -0,0 +1,25 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
REM Define paths
|
||||
set VENV_DIR=venv
|
||||
set APP_DIR=Program
|
||||
set PYTHON=%VENV_DIR%\Scripts\python.exe
|
||||
|
||||
REM Check for venv
|
||||
if not exist %VENV_DIR% (
|
||||
echo Creating virtual environment...
|
||||
python -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.
|
||||
)
|
||||
|
||||
REM Run the app
|
||||
cd /d %~dp0%APP_DIR%
|
||||
..\%VENV_DIR%\Scripts\python.exe app.py
|
||||
|
||||
endlocal
|
||||
|
23
Run.sh
Normal file
23
Run.sh
Normal 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
|
||||
|
BIN
requirements.txt
Normal file
BIN
requirements.txt
Normal file
Binary file not shown.
@@ -1,13 +0,0 @@
|
||||
@echo off
|
||||
REM Create Python virtual environment named "venv"
|
||||
python -m venv venv
|
||||
|
||||
REM Activate the virtual environment
|
||||
call venv\Scripts\activate.bat
|
||||
|
||||
REM Upgrade pip
|
||||
python -m pip install --upgrade pip
|
||||
|
||||
REM Install dependencies
|
||||
pip install mutagen
|
||||
|
@@ -1,12 +0,0 @@
|
||||
# Create Python virtual environment named "venv"
|
||||
python -m venv venv
|
||||
|
||||
# Activate the virtual environment
|
||||
& .\venv\Scripts\Activate.ps1
|
||||
|
||||
# Upgrade pip
|
||||
python -m pip install --upgrade pip
|
||||
|
||||
# Install dependencies
|
||||
pip install mutagen
|
||||
|
Reference in New Issue
Block a user