Spaces:
Running on Zero
Running on Zero
File size: 5,698 Bytes
2c29da2 64bb8a5 2c29da2 9c10999 2c29da2 8255c7d 2c29da2 ccdb35c 2c29da2 02ced71 bbac552 2c29da2 30f2487 2c29da2 fd01067 2c29da2 fd01067 2c29da2 07115fc c2d7fd1 07115fc c2d7fd1 07115fc c2d7fd1 07115fc 2c29da2 79fe149 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | from __future__ import annotations
import spaces # imported first, as ZeroGPU requires
import gradio as gr
import soundfile as sf
from pyharp import ModelCard, build_endpoint
from pyharp.tags import Subcategory
from stable_audio_runtime import edit_audio, load_model
MIN_AUDIO_SECONDS = 5
MAX_AUDIO_SECONDS = 30
model_card = ModelCard(
name="Stable Audio 3",
description=(
"Restyle, inpaint, or continue music audio using a text prompt. "
"Repository: https://github.com/Stability-AI/stable-audio-3 Paper: "
"https://arxiv.org/abs/2605.17991"
),
author="Zach Evans, Julian D. Parker, Matthew Rice, et al.",
tags=[Subcategory.EDITING],
)
# pyharp runs process_fn in a worker, which imports this file as __mp_main__ and starts with the
# server. stable-audio-tools is installed and the model downloaded, built and placed there, on the
# worker's main thread, so that no request does any of it inside its GPU reservation.
if __name__ != "__main__":
load_model()
def _audio_duration(path: str | None) -> float:
if not path:
raise gr.Error("Please upload a music clip.")
try:
duration = float(sf.info(path).duration)
except Exception as exc:
raise gr.Error(f"Could not read the audio file: {exc}") from exc
if duration < MIN_AUDIO_SECONDS:
raise gr.Error(f"Audio must be at least {MIN_AUDIO_SECONDS} seconds.")
if duration > MAX_AUDIO_SECONDS:
raise gr.Error(f"Audio must be no longer than {MAX_AUDIO_SECONDS} seconds.")
return duration
def process_fn(
audio_path: str | None,
prompt: str,
mode: str,
edit_start: float,
edit_end: float,
continuation_length: float,
strength: float,
seed: int,
) -> str:
# Checked before the GPU is reserved, so a request the model cannot take spends none of the
# caller's ZeroGPU allowance
duration = _audio_duration(audio_path)
prompt = (prompt or "").strip()
if not prompt:
raise gr.Error("Please enter an editing prompt.")
if mode == "Inpaint" and (
edit_start < 0 or edit_end > duration or edit_end <= edit_start
):
raise gr.Error(
"The inpaint region must be inside the uploaded clip, "
"with the end after the start."
)
return run_edit(audio_path, prompt, mode, edit_start, edit_end, continuation_length,
strength, seed)
# A 6 s restyle measured about 24 s, and inputs are capped at 30 s
@spaces.GPU(duration=120)
def run_edit(audio_path, prompt, mode, edit_start, edit_end, continuation_length, strength,
seed) -> str:
try:
return edit_audio(
audio_path=audio_path,
prompt=prompt,
mode=mode,
edit_start=float(edit_start),
edit_end=float(edit_end),
continuation_length=float(continuation_length),
strength=float(strength),
seed=int(seed),
)
except gr.Error:
raise
except Exception as exc:
raise gr.Error(f"Stable Audio 3 inference failed: {exc}") from exc
if __name__ == "__main__":
with gr.Blocks(title="Stable Audio 3") as demo:
input_components = [
gr.Audio(type="filepath", label="Music Audio")
.harp_required(True)
.set_info("Music clip between 5 and 30 seconds."),
gr.Textbox(
label="Prompt",
placeholder="A warm synthwave groove with punchy drums",
info=(
"Describe what the audio should become. What this changes depends "
"on the Edit Mode below."
),
).harp_required(True),
gr.Dropdown(
choices=["Restyle", "Inpaint", "Continue"],
value="Restyle",
label="Edit Mode",
info=(
"Restyle reworks the whole clip, Inpaint replaces the region "
"between the edit points, and Continue extends past the end."
),
),
gr.Slider(
minimum=0,
maximum=30,
value=4,
step=0.1,
label="Edit Start (seconds)",
).set_info("Used by Inpaint mode."),
gr.Slider(
minimum=0,
maximum=30,
value=8,
step=0.1,
label="Edit End (seconds)",
).set_info("Used by Inpaint mode."),
gr.Slider(
minimum=1,
maximum=15,
value=8,
step=1,
label="Continuation Length (seconds)",
).set_info("Used by Continue mode."),
gr.Slider(
minimum=0.1,
maximum=1.0,
value=0.75,
step=0.05,
label="Transformation Strength",
).set_info("Used by Restyle mode."),
gr.Slider(
minimum=0,
maximum=99999,
value=0,
step=1,
label="Seed",
).set_info("Use 0 for a random seed."),
]
output_components = [
gr.Audio(type="filepath", label="Edited Audio").set_info((
"The edited result, at 16-bit."
)),
]
build_endpoint(
model_card=model_card,
input_components=input_components,
output_components=output_components,
process_fn=process_fn,
)
demo.queue(default_concurrency_limit=1).launch(show_error=True, pwa=True, ssr_mode=False)
|