Vansh Chugh
updated gitignore and comments in app.py
2a0c658
Raw
History Blame Contribute Delete
5.78 kB
import sys
sys.stdout.reconfigure(line_buffering=True) # ensures print() appears in HF Spaces logs in real time
import traceback
import contextlib
import tempfile
import torch
import os
import threading
# import spaces # uncomment when running on ZeroGPU
import librosa
import soundfile as sf
import gradio as gr
from huggingface_hub import snapshot_download
from pyharp import ModelCard, build_endpoint
from anyaccomp.inference_utils import Sing2SongInferencePipeline
repo_id = "amphion/anyaccomp"
base_dir = os.path.dirname(os.path.abspath(__file__))
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
# Model loading state. Populated by the background thread.
inference_pipeline = None
model_loading = True
model_error = None
def load_model():
global inference_pipeline, model_loading, model_error
try:
checkpoint_marker = os.path.join(base_dir, "pretrained", "flow_matching")
if not os.path.exists(checkpoint_marker):
print(f"Downloading model files from {repo_id}...", flush=True)
model_dir = snapshot_download(repo_id=repo_id, local_dir=base_dir)
print(f"Model files downloaded to: {model_dir}", flush=True)
else:
model_dir = base_dir
print("Model files already present, skipping download.", flush=True)
cfg_path = os.path.join(base_dir, "config/flow_matching.json")
vocoder_cfg_path = os.path.join(base_dir, "config/vocoder.json")
checkpoint_path = os.path.join(model_dir, "pretrained/flow_matching")
vocoder_checkpoint_path = os.path.join(model_dir, "pretrained/vocoder")
print("Initializing AnyAccomp InferencePipeline...", flush=True)
pipeline = Sing2SongInferencePipeline(
checkpoint_path, cfg_path,
vocoder_checkpoint_path, vocoder_cfg_path,
device=DEVICE,
)
pipeline.sample_rate = 24000
inference_pipeline = pipeline
print("Model loaded successfully.", flush=True)
except Exception as e:
model_error = str(e)
print(f"Error loading model: {e}", flush=True)
finally:
model_loading = False
# Create a ModelCard describing this endpoint for HARP.
model_card = ModelCard(
name="AnyAccomp",
description="Upload a 3-30 second vocal or instrument track and the model will generate an accompaniment.",
author="Amphion",
tags=["audio", "music", "accompaniment"],
)
# Start model loading in the background so the server can start immediately.
threading.Thread(target=load_model, daemon=True).start()
# @spaces.GPU # uncomment when running on ZeroGPU
@torch.inference_mode()
def process_fn(vocal_filepath, n_timesteps): # add , cfg_scale to re-enable
if model_loading:
raise gr.Error("Model is still loading, please wait a moment and try again.")
if inference_pipeline is None:
raise gr.Error(f"Model failed to load: {model_error}")
if vocal_filepath is None:
raise gr.Error("Please upload a vocal audio file.")
try:
duration = librosa.get_duration(path=vocal_filepath)
if not (3 <= duration <= 30):
raise gr.Error("Audio duration must be between 3 and 30 seconds.")
except Exception as e:
raise gr.Error(f"Cannot read audio file or get duration: {e}")
try:
vocal_audio, _ = librosa.load(vocal_filepath, sr=24000, mono=True)
vocal_tensor = torch.tensor(vocal_audio).unsqueeze(0).to(DEVICE)
vocal_mel = inference_pipeline.encode_vocal(vocal_tensor)
autocast_ctx = torch.amp.autocast("cuda", dtype=torch.bfloat16) if torch.cuda.is_available() else contextlib.nullcontext()
with autocast_ctx:
mel = inference_pipeline.model.reverse_diffusion(
vocal_mel=vocal_mel,
n_timesteps=int(n_timesteps),
cfg=3.0, # replace with cfg_scale to re-enable
)
mel = mel.float()
wav = inference_pipeline._generate_audio(mel)
wav = wav.squeeze().detach().cpu().numpy()
wav = librosa.util.fix_length(data=wav, size=len(vocal_audio))
mixture_wav = wav + vocal_audio
with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as f:
accompaniment_path = f.name
with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as f:
mixture_path = f.name
sf.write(accompaniment_path, wav, 24000)
sf.write(mixture_path, mixture_wav, 24000)
return accompaniment_path, mixture_path
except Exception as e:
traceback.print_exc()
raise gr.Error(f"An error occurred during processing: {e}")
with gr.Blocks() as demo:
input_components = [
gr.Audio(
type="filepath",
label="Input Vocal or Instrument Audio",
).harp_required(True),
gr.Slider(
minimum=10, maximum=100, value=50, step=1,
label="Inference Steps (n_timesteps)",
info="Number of diffusion steps. More steps = slower but higher quality",
),
# gr.Slider(minimum=1.0, maximum=10.0, value=3.0, step=0.1, label="CFG Scale", info="Guidance strength — higher values follow the input melody more closely."),
]
output_components = [
gr.Audio(type="filepath", label="Generated Accompaniment").set_info(
"The generated instrumental accompaniment."
),
gr.Audio(type="filepath", label="Mixture (Vocal + Accompaniment)").set_info(
"Vocal mixed with the generated accompaniment."
),
]
build_endpoint(
model_card=model_card,
input_components=input_components,
output_components=output_components,
process_fn=process_fn,
)
demo.queue().launch()