add projects/ - standalone scripts alongside the Docker stacks

Two real, working scripts: an Ansible playbook run-menu (the same
pattern used identically across both the fleet-config and infra-
provisioning repos), and cuesplit, a frame-accurate FLAC/.cue
splitting utility. Sanitized paths only, logic untouched.

README gets a new "Scripts & Tooling" section pointing at it, placed
right after "What's Running" alongside the other repo-structure
pointer.
This commit is contained in:
thesabear committed 2026-08-25 11:29:04 +03:00
1 parent b1807247e7
commit 63689c3fc0
7 files changed
+348

No files matched your search

+124
View File
@@ -0,0 +1,124 @@
#!/usr/bin/env python3
"""
cuesplit.py — split FLAC files using a .cue sheet, via ffmpeg.
Handles multi-FILE cues, frame-accurate (MM:SS:FF) timestamps, and uses
INDEX 01 (track start, skipping pregap) as the split point.
Usage:
python3 cuesplit.py "album.cue" [output_dir]
Output dir defaults to "split".
"""
import re
import subprocess
import sys
from pathlib import Path
def parse_cue(cue_path):
"""Returns list of (filename, [(track_num, index01_time_str), ...])"""
files = []
current_file = None
current_tracks = None
pending_track = None
with open(cue_path, encoding="utf-8", errors="replace") as f:
for line in f:
line = line.strip()
m = re.match(r'FILE\s+"([^"]+)"', line, re.IGNORECASE)
if m:
if current_file is not None:
files.append((current_file, current_tracks))
current_file = m.group(1)
current_tracks = []
continue
m = re.match(r'TRACK\s+(\d+)\s+AUDIO', line, re.IGNORECASE)
if m:
pending_track = int(m.group(1))
continue
m = re.match(r'INDEX\s+01\s+(\d+:\d+:\d+)', line, re.IGNORECASE)
if m and pending_track is not None:
current_tracks.append((pending_track, m.group(1)))
pending_track = None
continue
if current_file is not None:
files.append((current_file, current_tracks))
return files
def cue_time_to_seconds(t):
mm, ss, ff = map(int, t.split(":"))
return mm * 60 + ss + ff / 75.0
def seconds_to_ffmpeg_ts(total_seconds):
mm = int(total_seconds // 60)
ss = total_seconds - mm * 60
return f"{mm:02d}:{ss:06.3f}"
def main():
if len(sys.argv) < 2:
print("Usage: python3 cuesplit.py <cuefile> [output_dir]")
sys.exit(1)
cue_path = Path(sys.argv[1])
out_dir = Path(sys.argv[2]) if len(sys.argv) > 2 else Path("split")
out_dir.mkdir(parents=True, exist_ok=True)
if not cue_path.exists():
print(f"Cue file not found: {cue_path}")
sys.exit(1)
files = parse_cue(cue_path)
if not files:
print("No FILE/TRACK entries found in cue — check the cue format.")
sys.exit(1)
track_counter = 1
for flac_name, tracks in files:
flac_path = cue_path.parent / flac_name
if not flac_path.exists():
print(f"WARNING: referenced audio file not found: {flac_path}")
continue
if not tracks:
print(f"WARNING: no tracks found for {flac_name}")
continue
starts = [cue_time_to_seconds(t) for _, t in tracks]
for i, start in enumerate(starts):
out_file = out_dir / f"{track_counter:02d}.flac"
ss = seconds_to_ffmpeg_ts(start)
cmd = ["ffmpeg", "-y", "-i", str(flac_path), "-ss", ss]
if i + 1 < len(starts):
to = seconds_to_ffmpeg_ts(starts[i + 1])
cmd += ["-to", to]
cmd += [str(out_file)]
print(f"Track {track_counter}: {flac_name} [{ss}"
f"{' -> ' + to if i + 1 < len(starts) else ' -> end'}]")
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
print(f" FAILED: {result.stderr[-500:]}")
else:
print(f" OK -> {out_file}")
track_counter += 1
print(f"\nDone. {track_counter - 1} tracks written to {out_dir}/")
if __name__ == "__main__":
main()
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
# ~/Projects/cuesplit/run — task dispatcher (symlinked into ~/.local/bin)
# Usage: run split
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
CUESPLIT_PY="$SCRIPT_DIR/cuesplit.py"
cmd_split() {
# Find exactly one .cue file in the current directory
shopt -s nullglob
cues=(*.cue *.CUE)
shopt -u nullglob
if [ ${#cues[@]} -eq 0 ]; then
echo "No .cue file found in $(pwd)"
exit 1
fi
if [ ${#cues[@]} -gt 1 ]; then
echo "Multiple .cue files found, pick one:"
select cue in "${cues[@]}"; do
[ -n "$cue" ] && break
done
else
cue="${cues[0]}"
fi
echo "Using cue: $cue"
python3 "$CUESPLIT_PY" "$cue" split
echo "Opening split/ in Picard..."
picard "$(pwd)/split" >/dev/null 2>&1 &
disown
}
case "${1:-}" in
split)
cmd_split
;;
*)
echo "Usage: run <command>"
echo "Commands:"
echo " split - auto-find .cue in current dir and split the audio"
exit 1
;;
esac