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")