Download plus/plus_batch.py from Nokia123543/muscriptor-large-fork: direct link, hf CLI and curl.
- Browser
- Download file 4.53 kB
-
https://huggingface.co/Nokia123543/muscriptor-large-fork/resolve/main/plus/plus_batch.py
- Command line
-
hf download hf://Nokia123543/muscriptor-large-fork/plus/plus_batch.py
-
curl -L -o plus_batch.py https://huggingface.co/Nokia123543/muscriptor-large-fork/resolve/main/plus/plus_batch.py
4.53 kB
| """PLUS batch: обработка папки целиком, с возобновлением и CSV-сводкой. | |
| Для каждой пары «аудио + MIDI» прогоняет пайплайн, пишет результат рядом с | |
| исходником и собирает сводку. Уже обработанные файлы пропускаются, поэтому | |
| прерванный прогон можно продолжить. | |
| CLI: | |
| python plus_batch.py --input-dir takes --out-dir takes_plus \ | |
| --stages cleanup,quantize,hands,pedal,dynamics,report --audio-ext .wav | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import csv | |
| import os | |
| import sys | |
| import time | |
| sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) | |
| from plus_core import dump_json, load_midi, save_midi, step # noqa: E402 | |
| from plus_transcribe import run_pipeline # noqa: E402 | |
| __version__ = "1.0" | |
| def find_pairs(folder: str, audio_ext: str) -> list[tuple[str, str | None]]: | |
| """MIDI и, если есть, одноимённое аудио рядом.""" | |
| pairs = [] | |
| for name in sorted(os.listdir(folder)): | |
| if not name.lower().endswith((".mid", ".midi")): | |
| continue | |
| midi_path = os.path.join(folder, name) | |
| base = os.path.splitext(midi_path)[0] | |
| audio = None | |
| for ext in audio_ext.split(","): | |
| candidate = base + ext.strip() | |
| if os.path.isfile(candidate): | |
| audio = candidate | |
| break | |
| pairs.append((midi_path, audio)) | |
| return pairs | |
| def main(argv: list[str] | None = None) -> int: | |
| parser = argparse.ArgumentParser(description="PLUS batch") | |
| parser.add_argument("--input-dir", required=True) | |
| parser.add_argument("--out-dir", required=True) | |
| parser.add_argument("--stages", default="cleanup,quantize,hands,pedal,dynamics,report") | |
| parser.add_argument("--audio-ext", default=".wav,.mp3,.flac,.m4a,.ogg") | |
| parser.add_argument("--force", action="store_true", help="перезаписывать готовое") | |
| args = parser.parse_args(argv) | |
| os.makedirs(args.out_dir, exist_ok=True) | |
| pairs = find_pairs(args.input_dir, args.audio_ext) | |
| if not pairs: | |
| raise SystemExit("в " + args.input_dir + " нет MIDI") | |
| stages = [s.strip() for s in args.stages.split(",") if s.strip()] | |
| csv_path = os.path.join(args.out_dir, "summary.csv") | |
| rows: list[dict] = [] | |
| if os.path.isfile(csv_path): | |
| with open(csv_path, newline="", encoding="utf-8") as handle: | |
| rows = list(csv.DictReader(handle)) | |
| by_file = {row["file"]: row for row in rows} | |
| started = time.time() | |
| for index, (midi_path, audio) in enumerate(pairs, 1): | |
| base = os.path.splitext(os.path.basename(midi_path))[0] | |
| out_midi = os.path.join(args.out_dir, base + "_plus.mid") | |
| out_json = os.path.join(args.out_dir, base + "_report.json") | |
| if os.path.isfile(out_midi) and os.path.isfile(out_json) and not args.force: | |
| step(index, len(pairs), "%s: уже готово, пропускаю" % base) | |
| continue | |
| step(index, len(pairs), "%s%s" % (base, " + аудио" if audio else " (без аудио)")) | |
| try: | |
| piece = load_midi(midi_path) | |
| options = {"audio": audio} | |
| report = run_pipeline(piece, stages, options) | |
| save_midi(piece, out_midi) | |
| dump_json(report, out_json) | |
| by_file[base] = {"file": base, | |
| "notes_in": report["stages"].get("report", {}).get( | |
| "notes", len(piece.notes)), | |
| "notes_out": len(piece.notes), "status": "ok"} | |
| except Exception as exc: # один битый файл не должен ронять пачку | |
| by_file[base] = {"file": base, "notes_in": "", "notes_out": "", | |
| "status": "%s: %s" % (type(exc).__name__, exc)} | |
| rows = sorted(by_file.values(), key=lambda row: row["file"]) | |
| with open(csv_path, "w", newline="", encoding="utf-8") as handle: | |
| writer = csv.DictWriter(handle, fieldnames=["file", "notes_in", "notes_out", "status"]) | |
| writer.writeheader() | |
| writer.writerows(rows) | |
| ok = sum(1 for row in rows if row["status"] == "ok") | |
| print("готово: %d из %d за %.1f с | сводка: %s" | |
| % (ok, len(pairs), time.time() - started, csv_path), flush=True) | |
| return 0 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |