Spaces:
Running on Zero
Running on Zero
File size: 5,851 Bytes
90bee07 f725827 90bee07 f725827 90bee07 dd40c18 90bee07 f725827 90bee07 f725827 c0f1647 90bee07 c0f1647 90bee07 f725827 90bee07 f725827 86b1d3f 90bee07 86b1d3f 90bee07 86b1d3f 90bee07 | 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 | """
SonicMaster on HARP: text-controlled music restoration and mastering.
The model runs here rather than on the authors' Space, so a request draws on
this Space's own allowance instead of theirs. The weights come from
amaai-lab/SonicMaster and the inference code is vendored from the authors'
repository, which LICENSE-SonicMaster carries.
"""
import tempfile
from pathlib import Path
import gradio as gr
import spaces
from pyharp import (Channels, ModelCard, SampleRate, Subcategory,
build_endpoint)
import sonicmaster_runtime
model_card = ModelCard(
name="SonicMaster",
description=(
"Text-controlled all-in-one music restoration and mastering: one "
"instruction in plain language fixes reverb, clipping, tonal balance, "
"dynamics, or the stereo image. The model is a flow-matching "
"transformer over Stable Audio's latent space, conditioned on a "
"FLAN-T5 encoding of the instruction, so the wording of the prompt is "
"what selects the treatment. Audio is resampled to 44.1 kHz stereo and "
"processed in overlapping 30-second chunks, each conditioned on the "
"tail of the one before it, which keeps a long track consistent across "
"chunk boundaries. SonicMaster itself is Apache 2.0, but it decodes "
"through Stable Audio Open's VAE, so results are also governed by the "
"Stability AI Community License: "
"https://huggingface.co/stabilityai/stable-audio-open-1.0/blob/main/LICENSE.md "
"which permits non-commercial use and commercial use below an annual "
"revenue threshold. Repository: "
"https://github.com/AMAAI-Lab/SonicMaster Paper: "
"https://arxiv.org/abs/2508.03448"
),
author="Jan Melechovsky, Ambuj Mehrish, Dorien Herremans",
tags=[Subcategory.POST_PROCESSING, SampleRate(sonicmaster_runtime.SAMPLE_RATE),
Channels(sonicmaster_runtime.CHANNELS), "text-guided"],
)
@spaces.GPU(duration=240)
def process_fn(input_audio_path, prompt, num_inference_steps, guidance_scale,
solver, seed):
"""
Apply the instruction to the recording.
Args:
input_audio_path (str): The recording to edit.
prompt (str): What to change about it.
num_inference_steps (float): Flow solver steps per chunk.
guidance_scale (float): How strongly the instruction is followed.
solver (str): Which solver steps the flow.
seed (float): Seed for the noise.
Returns:
output_path (str): The edited audio.
"""
if not (prompt or "").strip():
raise gr.Error("Describe what to change about the audio.")
output_path = Path(tempfile.mkdtemp()) / "sonicmaster.wav"
return sonicmaster_runtime.enhance(
input_audio_path,
prompt.strip(),
output_path,
num_inference_steps=int(num_inference_steps),
guidance_scale=float(guidance_scale),
seed=int(seed),
solver=solver,
)
if __name__ == "__main__":
with gr.Blocks() as demo:
input_components = [
gr.Audio(type="filepath", label="Input audio").harp_required(True).set_info((
"The recording to treat. It is resampled to 44.1 kHz and "
"forced to stereo, since that is what the model was trained "
"on, and a mono input is duplicated across both channels."
)),
gr.Textbox(label="Instruction", value="Remove the reverb from this recording.",
info=(
"What to change, in plain language, for example "
"\"reduce the reverb\", \"brighten the high end\", "
"\"even out the loudness\", or \"widen the stereo "
"image\". One instruction at a time works better "
"than several combined."
)),
gr.Slider(minimum=1, maximum=50, step=1, value=10,
label="Solver steps",
info=(
"How many steps the flow solver takes per chunk. "
"More steps follow the instruction more closely and "
"cost proportionally more time."
)),
gr.Slider(minimum=1.0, maximum=7.0, step=0.1, value=1.0,
label="Instruction strength",
info=(
"How strongly the instruction is weighted against "
"leaving the audio alone. Raising it applies a more "
"pronounced treatment, at the risk of artifacts."
)),
gr.Dropdown(choices=["Euler", "rk4"], value="Euler", label="Solver",
info=(
"Euler takes one evaluation per step. rk4 takes "
"four, which is steadier at a low step count and "
"roughly four times slower."
)),
gr.Number(value=0, precision=0, label="Seed",
info=(
"Seeds the noise the solver starts from, so the same "
"seed and settings reproduce a result."
)),
]
output_components = [
gr.Audio(type="filepath", label="Treated audio").set_info((
"The result, at 44.1 kHz stereo."
)),
]
build_endpoint(
model_card=model_card,
input_components=input_components,
output_components=output_components,
process_fn=process_fn,
)
demo.queue().launch(server_name="0.0.0.0", server_port=7860,
show_error=True, pwa=True)
|