Spaces:
Paused
Paused
| from __future__ import annotations | |
| import subprocess | |
| import sys | |
| import tempfile | |
| import threading | |
| from pathlib import Path | |
| MODEL_REPO = "stabilityai/stable-audio-3-small-music" | |
| MODEL_REVISION = "0fef1392cd842149a2b6d445e181c97608faac06" | |
| STABLE_AUDIO_TOOLS_REVISION = "3241adba4fc2a85cf5b29d9eb68d42f40a28e820" | |
| OUTPUT_ROOT = Path(tempfile.gettempdir()) / "stable_audio_3_outputs" | |
| _MODEL = None | |
| _MODEL_CONFIG = None | |
| _MODEL_LOCK = threading.Lock() | |
| def _ensure_stable_audio_tools() -> None: | |
| try: | |
| import stable_audio_tools # noqa: F401 | |
| return | |
| except ImportError: | |
| pass | |
| subprocess.check_call( | |
| [ | |
| sys.executable, | |
| "-m", | |
| "pip", | |
| "install", | |
| "--quiet", | |
| "--no-deps", | |
| ( | |
| "git+https://github.com/Stability-AI/stable-audio-tools.git@" | |
| f"{STABLE_AUDIO_TOOLS_REVISION}" | |
| ), | |
| ] | |
| ) | |
| _ensure_stable_audio_tools() | |
| def _load_model(): | |
| global _MODEL, _MODEL_CONFIG | |
| if _MODEL is not None: | |
| return _MODEL, _MODEL_CONFIG | |
| with _MODEL_LOCK: | |
| if _MODEL is not None: | |
| return _MODEL, _MODEL_CONFIG | |
| import torch | |
| from stable_audio_tools.models import pretrained | |
| original_download = pretrained.hf_hub_download | |
| def pinned_download(repo_id, *args, **kwargs): | |
| if repo_id == MODEL_REPO: | |
| kwargs.setdefault("revision", MODEL_REVISION) | |
| return original_download(repo_id, *args, **kwargs) | |
| pretrained.hf_hub_download = pinned_download | |
| try: | |
| model, config = pretrained.get_pretrained_model(MODEL_REPO) | |
| finally: | |
| pretrained.hf_hub_download = original_download | |
| model = model.to("cuda").to(torch.float16) | |
| model.eval().requires_grad_(False) | |
| _MODEL = model | |
| _MODEL_CONFIG = config | |
| return _MODEL, _MODEL_CONFIG | |
| def _load_audio(path: str): | |
| import torch | |
| import torchaudio | |
| audio, sample_rate = torchaudio.load(path) | |
| if audio.shape[0] > 2: | |
| audio = audio[:2] | |
| return int(sample_rate), audio.to(torch.float32) | |
| def _save_audio(output, sample_rate: int) -> str: | |
| import soundfile as sf | |
| import torch | |
| output = output.permute(1, 0, 2).reshape(output.shape[1], -1) | |
| output = output.to(torch.float32) | |
| peak = output.abs().max().clamp(min=1e-9) | |
| output = output.div(peak).clamp(-1, 1).cpu().numpy().T | |
| OUTPUT_ROOT.mkdir(parents=True, exist_ok=True) | |
| output_dir = Path(tempfile.mkdtemp(dir=OUTPUT_ROOT)) | |
| output_path = output_dir / "stable_audio_3_edit.wav" | |
| sf.write(output_path, output, sample_rate, subtype="PCM_16") | |
| return str(output_path) | |
| def edit_audio( | |
| audio_path: str, | |
| prompt: str, | |
| mode: str, | |
| edit_start: float, | |
| edit_end: float, | |
| continuation_length: float, | |
| strength: float, | |
| seed: int, | |
| ) -> str: | |
| import torch | |
| import torchaudio | |
| model, config = _load_model() | |
| from stable_audio_tools.inference.generation import ( | |
| generate_diffusion_cond_inpaint, | |
| ) | |
| sample_rate = int(config["sample_rate"]) | |
| sample_size = int(config["sample_size"]) | |
| source_rate, source = _load_audio(audio_path) | |
| source_duration = source.shape[-1] / source_rate | |
| if source_rate != sample_rate: | |
| source = torchaudio.functional.resample(source, source_rate, sample_rate) | |
| model_dtype = next(model.parameters()).dtype | |
| source_tuple = (sample_rate, source.to(model_dtype)) | |
| if mode == "Continue": | |
| output_duration = source_duration + continuation_length | |
| else: | |
| output_duration = source_duration | |
| conditioning = [{"prompt": prompt, "seconds_total": output_duration}] | |
| kwargs = { | |
| "steps": 8, | |
| "cfg_scale": 1.0, | |
| "conditioning": conditioning, | |
| "sample_size": sample_size, | |
| "sampler_type": "pingpong", | |
| "seed": int(seed) if seed > 0 else -1, | |
| "device": "cuda", | |
| "sigma_max": 1.0, | |
| "apg_scale": 1.0, | |
| "duration_padding_sec": 6.0, | |
| } | |
| if mode == "Restyle": | |
| kwargs["init_audio"] = source_tuple | |
| kwargs["init_noise_level"] = float(strength) | |
| elif mode == "Inpaint": | |
| kwargs["inpaint_audio"] = source_tuple | |
| kwargs["inpaint_mask_start_seconds"] = float(edit_start) | |
| kwargs["inpaint_mask_end_seconds"] = float(edit_end) | |
| elif mode == "Continue": | |
| kwargs["inpaint_audio"] = source_tuple | |
| kwargs["inpaint_mask_start_seconds"] = float(source_duration) | |
| kwargs["inpaint_mask_end_seconds"] = float(output_duration) | |
| else: | |
| raise ValueError(f"Unknown edit mode: {mode}") | |
| with torch.inference_mode(): | |
| output = generate_diffusion_cond_inpaint(model, **kwargs) | |
| output = output[..., : int(output_duration * sample_rate)] | |
| return _save_audio(output, sample_rate) | |