From 9048b18b47d903990be169a238d7835bb11a5047 Mon Sep 17 00:00:00 2001 From: Eddy Pedroni Date: Thu, 22 Oct 2026 17:09:53 +0200 Subject: grabnsplit script --- grabnsplit-project/src/grabnsplit.py | 99 ++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 grabnsplit-project/src/grabnsplit.py (limited to 'grabnsplit-project/src') diff --git a/grabnsplit-project/src/grabnsplit.py b/grabnsplit-project/src/grabnsplit.py new file mode 100644 index 0000000..c4409dc --- /dev/null +++ b/grabnsplit-project/src/grabnsplit.py @@ -0,0 +1,99 @@ +import click +from pathlib import Path + +SAMPLE_RATE = "48000" +FB_URL = "https://files.0xf7.com" + +def download(yt_url: str, destination: Path) -> None: + import yt_dlp + + options = { + "format": "bestaudio/best", + "outtmpl": str(destination), + "playlist_items": "1", + "postprocessors": [ + { + "key": "FFmpegExtractAudio", + "preferredcodec": "wav" + } + ], + "postprocessor_args": [ + "-ar", SAMPLE_RATE, + ], + } + + with yt_dlp.YoutubeDL(options) as downloader: + downloader.download([yt_url]) + +def split(original: Path, destination: Path) -> None: + from demucs.api import Separator + from demucs.audio import save_audio + + separator = Separator(model="htdemucs_6s") + + origin, separated = separator.separate_audio_file(original) + + for stem_name, audio in separated.items(): + output_file = destination / f"{stem_name}.wav" + save_audio( + audio, + str(output_file), + samplerate=separator.samplerate, + ) + +def combine(destination: Path, name: str) -> None: + from ffmpeg import FFmpeg + + inputs = [] + options = { + "map": [], + "c:a": "libmp3lame", + "b:a": "320k", + "ar": SAMPLE_RATE + } + + stems = [ + ("vocals.wav", "Vocals"), + ("guitar.wav", "Guitars"), + ("piano.wav", "Piano"), + ("bass.wav", "Bass"), + ("drums.wav", "Drums"), + ("other.wav", "Other"), + ] + + ffmpeg = FFmpeg().option("y") + + for i, stem in enumerate(stems): + #inputs.append(ffmpeg.input(str(destination / stem[0]))) + ffmpeg.input(str(destination / stem[0])) + options["map"].append(f"{i}:a") + options[f"metadata:s:a:{i}"] = f"title={stem[1]}" + + ffmpeg.output(str(destination / f"{name}.mka"), options) + ffmpeg.execute() + +def upload(file_path: Path) -> None: + from requests import post + from os import getenv + + api_key = post(f"{FB_URL}/api/login", json={"username":getenv("ST_USER"), "password":getenv("ST_PASS")}).content + url = f"{FB_URL}/api/resources/songs/{file_path.name}" + with open(file_path, "rb") as file: + post(url, headers={"X-Auth" : api_key}, data=file).raise_for_status() + +@click.command() +@click.argument("url", required=True) +@click.argument("output_file", required=True) +@click.option("--work_dir", type=click.Path()) +def main(url: str, output_file: str, work_dir: Path): + from tempfile import TemporaryDirectory + with TemporaryDirectory(prefix="grabnsplit") as temp: + dir = Path(work_dir if work_dir is not None else temp) + + original = dir / "original.wav" + + download(url, original.parent / original.stem) + split(original, dir) + combine(dir, output_file) + upload(dir / f"{output_file}.mka") + -- cgit v1.2.3