Spaces:
Build error
Build error
| from __future__ import annotations | |
| from logging import getLogger | |
| from pathlib import Path | |
| import keyboard | |
| import librosa | |
| import sounddevice as sd | |
| import soundfile as sf | |
| from rich.console import Console | |
| from tqdm.rich import tqdm | |
| LOG = getLogger(__name__) | |
| def preprocess_classify( | |
| input_dir: Path | str, output_dir: Path | str, create_new: bool = True | |
| ) -> None: | |
| # paths | |
| input_dir_ = Path(input_dir) | |
| output_dir_ = Path(output_dir) | |
| speed = 1 | |
| if not input_dir_.is_dir(): | |
| raise ValueError(f"{input_dir} is not a directory.") | |
| output_dir_.mkdir(exist_ok=True) | |
| console = Console() | |
| # get audio paths and folders | |
| audio_paths = list(input_dir_.glob("*.*")) | |
| last_folders = [x for x in output_dir_.glob("*") if x.is_dir()] | |
| console.print("Press ↑ or ↓ to change speed. Press any other key to classify.") | |
| console.print(f"Folders: {[x.name for x in last_folders]}") | |
| pbar_description = "" | |
| pbar = tqdm(audio_paths) | |
| for audio_path in pbar: | |
| # read file | |
| audio, sr = sf.read(audio_path) | |
| # update description | |
| duration = librosa.get_duration(y=audio, sr=sr) | |
| pbar_description = f"{duration:.1f} {pbar_description}" | |
| pbar.set_description(pbar_description) | |
| while True: | |
| # start playing | |
| sd.play(librosa.effects.time_stretch(audio, rate=speed), sr, loop=True) | |
| # wait for key press | |
| key = str(keyboard.read_key()) | |
| if key == "down": | |
| speed /= 1.1 | |
| console.print(f"Speed: {speed:.2f}") | |
| elif key == "up": | |
| speed *= 1.1 | |
| console.print(f"Speed: {speed:.2f}") | |
| else: | |
| break | |
| # stop playing | |
| sd.stop() | |
| # print if folder changed | |
| folders = [x for x in output_dir_.glob("*") if x.is_dir()] | |
| if folders != last_folders: | |
| console.print(f"Folders updated: {[x.name for x in folders]}") | |
| last_folders = folders | |
| # get folder | |
| folder_candidates = [x for x in folders if x.name.startswith(key)] | |
| if len(folder_candidates) == 0: | |
| if create_new: | |
| folder = output_dir_ / key | |
| else: | |
| console.print(f"No folder starts with {key}.") | |
| continue | |
| else: | |
| if len(folder_candidates) > 1: | |
| LOG.warning( | |
| f"Multiple folders ({[x.name for x in folder_candidates]}) start with {key}. " | |
| f"Using first one ({folder_candidates[0].name})." | |
| ) | |
| folder = folder_candidates[0] | |
| folder.mkdir(exist_ok=True) | |
| # move file | |
| new_path = folder / audio_path.name | |
| audio_path.rename(new_path) | |
| # update description | |
| pbar_description = f"Last: {audio_path.name} -> {folder.name}" | |
| # yield result | |
| # yield audio_path, key, folder, new_path | |