From ce99bb114ba0aa5b27cbc1847ba616852216ea87 Mon Sep 17 00:00:00 2001 From: clerie Date: Sun, 21 Sep 2025 17:06:36 +0200 Subject: [PATCH] pkgs/convert-flac-dir-to-mp3: Add script for coverting music libraries --- .../convert-flac-dir-to-mp3.py | 96 +++++++++++++++++++ pkgs/convert-flac-dir-to-mp3/default.nix | 8 ++ pkgs/overlay.nix | 1 + 3 files changed, 105 insertions(+) create mode 100644 pkgs/convert-flac-dir-to-mp3/convert-flac-dir-to-mp3.py create mode 100644 pkgs/convert-flac-dir-to-mp3/default.nix diff --git a/pkgs/convert-flac-dir-to-mp3/convert-flac-dir-to-mp3.py b/pkgs/convert-flac-dir-to-mp3/convert-flac-dir-to-mp3.py new file mode 100644 index 0000000..fd7cc5a --- /dev/null +++ b/pkgs/convert-flac-dir-to-mp3/convert-flac-dir-to-mp3.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python + +import argparse +from pathlib import Path +from progress.bar import Bar +import shutil +import subprocess + +def files_and_dirs_for_directory(path): + filepaths = [] + dirpaths = [] + + for dirpath, dirnames, filenames in path.walk(): + dirpaths.append(dirpath) + + for filename in filenames: + filepath = dirpath / filename + filepaths.append(filepath) + + return set(filepaths), set(dirpaths) + +def make_paths_relative(paths, relative_to_path): + return set(path.relative_to(relative_to_path) for path in paths) + +def replace_suffix(path, suffix): + return path.with_name(path.stem + suffix) + +def convert_filepath(path): + if path.suffix == ".flac": + return replace_suffix(path, ".mp3") + + return path + +def ffmpeg_flac_to_mp3(in_path, out_path): + print("") + subprocess.run(["ffmpeg", "-hide_banner", "-loglevel", "warning", "-stats", "-i", in_path, "-ab", "320k", "-map_metadata", "0", "-id3v2_version", "3", out_path], check=True) + print("") + +if __name__ == "__main__": + + parser = argparse.ArgumentParser(prog="convert-flac-dir-to-mp3") + parser.add_argument("from_dir", type=Path) + parser.add_argument("to_dir", type=Path) + + args = parser.parse_args() + + from_path = args.from_dir.absolute() + to_path = args.to_dir.absolute() + + if not from_path.exists(): + raise Exception("from_path does not exist") + + if not to_path.exists(): + raise Exception("to_path does not exist") + + if not from_path.is_dir(): + raise Exception("from_path is not a directory") + + if not to_path.is_dir(): + raise Exception("to_path is not a directory") + + print(f"Converting {from_path} to {to_path}…") + + from_filepaths, from_dirpaths = files_and_dirs_for_directory(from_path) + to_filepaths, to_dirpaths = files_and_dirs_for_directory(to_path) + + + relative_from_filepaths = make_paths_relative(from_filepaths, from_path) + relative_to_filepaths = make_paths_relative(to_filepaths, to_path) + + converted_from_filepaths = set(convert_filepath(filepath) for filepath in relative_from_filepaths) + + filepaths_missing_in_to_path = converted_from_filepaths - relative_to_filepaths + + + relative_from_dirpaths = make_paths_relative(from_dirpaths, from_path) + relative_to_dirpaths = make_paths_relative(to_dirpaths, to_path) + + dirpaths_missing_in_to_path = relative_from_dirpaths - relative_to_dirpaths + + print(f"Missing {len(filepaths_missing_in_to_path)} files and {len(dirpaths_missing_in_to_path)} directories") + + if len(dirpaths_missing_in_to_path) > 0: + for dirpath in Bar("Creating directories").iter(dirpaths_missing_in_to_path): + (to_path / dirpath).mkdir(parents=True, exist_ok=True) + + if len(filepaths_missing_in_to_path) > 0: + for filepath in Bar("Creating files").iter(filepaths_missing_in_to_path): + if filepath in relative_from_filepaths: + # Just copy the file + shutil.copy(from_path / filepath, to_path / filepath) + elif filepath.suffix == ".mp3" and replace_suffix(filepath, ".flac") in relative_from_filepaths: + # Convert from flac + ffmpeg_flac_to_mp3(from_path / replace_suffix(filepath, ".flac"), to_path / filepath) + else: + raise Exception("Unable to figure out how to get {to_path / filepath} from {from_path}") diff --git a/pkgs/convert-flac-dir-to-mp3/default.nix b/pkgs/convert-flac-dir-to-mp3/default.nix new file mode 100644 index 0000000..05f4a83 --- /dev/null +++ b/pkgs/convert-flac-dir-to-mp3/default.nix @@ -0,0 +1,8 @@ +{ pkgs, ... }: + +pkgs.clerie-build-support.writePythonScript { + name = "convert-flac-dir-to-mp3"; + runtimePackages = ps: with ps; [ progress ]; + runtimeInputs = [ pkgs.ffmpeg-headless ]; + text = builtins.readFile ./convert-flac-dir-to-mp3.py; +} diff --git a/pkgs/overlay.nix b/pkgs/overlay.nix index 1e67ae0..aa4cd40 100644 --- a/pkgs/overlay.nix +++ b/pkgs/overlay.nix @@ -12,6 +12,7 @@ final: prev: { clerie-sops-edit = final.callPackage ./clerie-sops/clerie-sops-edit.nix {}; clerie-update-nixfiles = final.callPackage ./clerie-update-nixfiles/clerie-update-nixfiles.nix {}; chromium-incognito = final.callPackage ./chromium-incognito {}; + convert-flac-dir-to-mp3 = final.callPackage ./convert-flac-dir-to-mp3 {}; curl-timings = final.callPackage ./curl-timings {}; factorio-launcher = final.callPackage ./factorio-launcher {}; feeds-dir = final.callPackage ./feeds-dir {};