Vansh Chugh commited on
Commit
20daaa7
·
1 Parent(s): 027f950

testing org anyaccomp implementation

Browse files
Files changed (3) hide show
  1. README.md +2 -2
  2. app.py +151 -87
  3. requirements.txt +4 -5
README.md CHANGED
@@ -4,8 +4,8 @@ emoji: 🎵
4
  colorFrom: blue
5
  colorTo: purple
6
  sdk: gradio
7
- sdk_version: 5.28.0
8
- python_version: '3.13'
9
  app_file: app.py
10
  pinned: false
11
  license: mit
 
4
  colorFrom: blue
5
  colorTo: purple
6
  sdk: gradio
7
+ sdk_version: 4.44.1
8
+ python_version: '3.11'
9
  app_file: app.py
10
  pinned: false
11
  license: mit
app.py CHANGED
@@ -1,105 +1,169 @@
 
 
1
  import os
2
- import tempfile
3
-
4
  import librosa
5
  import numpy as np
6
  import soundfile as sf
7
- import torch
8
  import gradio as gr
9
-
10
  from huggingface_hub import snapshot_download
11
- from pyharp import ModelCard, build_endpoint
12
 
13
  from anyaccomp.inference_utils import Sing2SongInferencePipeline
14
 
15
- BASE_DIR = os.path.dirname(os.path.abspath(__file__))
16
- SAMPLE_RATE = 24000
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
18
 
19
- # Download the pretrained checkpoints the first time this Space starts up.
20
- # The repo lays them out under pretrained/, which matches what the config files expect.
21
- if not os.path.exists(os.path.join(BASE_DIR, "pretrained", "flow_matching")):
22
- snapshot_download(
23
- repo_id="amphion/anyaccomp",
24
- local_dir=BASE_DIR,
25
- repo_type="model",
26
- ignore_patterns=["README.md", "*.txt", ".gitattributes"],
27
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
- # Load all three model components once at startup so they're warm for every request.
30
- pipeline = Sing2SongInferencePipeline(
31
- checkpoint_path=os.path.join(BASE_DIR, "pretrained", "flow_matching"),
32
- cfg_path=os.path.join(BASE_DIR, "config", "flow_matching.json"),
33
- vocoder_checkpoint_path=os.path.join(BASE_DIR, "pretrained", "vocoder"),
34
- vocoder_cfg_path=os.path.join(BASE_DIR, "config", "vocoder.json"),
35
- device=DEVICE,
36
- )
37
-
38
-
39
- @torch.inference_mode()
40
- def process_fn(audio_path, n_timesteps, cfg_scale):
41
- # Validate length before doing anything expensive.
42
- duration = librosa.get_duration(path=audio_path)
43
- if not (3 <= duration <= 30):
44
- raise gr.Error("Audio must be between 3 and 30 seconds long.")
45
-
46
- # Load the vocal and encode it into discrete chromagram tokens.
47
- vocal_audio, _ = librosa.load(audio_path, sr=SAMPLE_RATE, mono=True)
48
- vocal_tensor = torch.tensor(vocal_audio).unsqueeze(0).to(DEVICE)
49
- vocal_mel = pipeline.encode_vocal(vocal_tensor)
50
-
51
- # Run the flow-matching diffusion to generate the accompaniment mel spectrogram.
52
- with torch.amp.autocast("cuda", dtype=torch.bfloat16):
53
- mel = pipeline.model.reverse_diffusion(
54
- vocal_mel=vocal_mel,
55
- n_timesteps=int(n_timesteps),
56
- cfg=cfg_scale,
57
- )
58
-
59
- # Decode mel → waveform, then trim/pad so it lines up with the input.
60
- wav = pipeline._generate_audio(mel.float())
61
- wav = wav.squeeze().detach().cpu().numpy()
62
- wav = librosa.util.fix_length(data=wav, size=len(vocal_audio))
63
-
64
- # Write to a temp file; Gradio expects a file path back.
65
- with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as f:
66
- out_path = f.name
67
- sf.write(out_path, wav, SAMPLE_RATE)
68
- return out_path
69
-
70
-
71
- model_card = ModelCard(
72
- name="AnyAccomp",
73
- description="Generates musical accompaniment from a 3-30 second vocal or instrument track.",
74
- author="Amphion Team",
75
- tags=["accompaniment generation", "music generation"],
76
- )
77
-
78
- with gr.Blocks() as demo:
79
- audio_input = gr.Audio(
80
- type="filepath",
81
- label="Input Vocal or Instrument Audio (3-30 seconds)",
82
- ).harp_required(True)
83
-
84
- n_timesteps_slider = gr.Slider(
85
- minimum=10, maximum=100, value=50, step=1,
86
- label="Inference Steps",
87
  )
88
- cfg_slider = gr.Slider(
89
- minimum=1.0, maximum=10.0, value=3.0, step=0.1,
90
- label="CFG Scale",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  )
92
 
93
- accompaniment_output = gr.Audio(
94
- type="filepath",
95
- label="Generated Accompaniment",
96
- ).set_info("Generated accompaniment track for the input audio.")
97
 
98
- build_endpoint(
99
- model_card=model_card,
100
- input_components=[audio_input, n_timesteps_slider, cfg_slider],
101
- output_components=[accompaniment_output],
102
- process_fn=process_fn,
103
- )
104
 
105
- demo.queue().launch(show_error=True, pwa=True, ssr_mode=False)
 
 
1
+ import spaces
2
+ import torch
3
  import os
4
+ import random
 
5
  import librosa
6
  import numpy as np
7
  import soundfile as sf
 
8
  import gradio as gr
9
+ import time
10
  from huggingface_hub import snapshot_download
 
11
 
12
  from anyaccomp.inference_utils import Sing2SongInferencePipeline
13
 
14
+ repo_id = "amphion/anyaccomp"
15
+ base_dir = os.path.dirname(os.path.abspath(__file__))
16
+
17
+ print(f"Downloading model files from {repo_id}...")
18
+ model_dir = snapshot_download(repo_id=repo_id, local_dir=base_dir)
19
+ print(f"Model files downloaded to: {model_dir}")
20
+
21
+ CFG_PATH = os.path.join(base_dir, "config/flow_matching.json")
22
+ VOCODER_CFG_PATH = os.path.join(base_dir, "config/vocoder.json")
23
+ CHECKPOINT_PATH = os.path.join(model_dir, "pretrained/flow_matching")
24
+ VOCODER_CHECKPOINT_PATH = os.path.join(model_dir, "pretrained/vocoder")
25
+
26
+ INFER_DST = os.path.join(base_dir, "output_gradio")
27
+ os.makedirs(INFER_DST, exist_ok=True)
28
+ acc_dst = os.path.join(INFER_DST, "accompaniment")
29
+ mixture_dst = os.path.join(INFER_DST, "mixture")
30
+ os.makedirs(acc_dst, exist_ok=True)
31
+ os.makedirs(mixture_dst, exist_ok=True)
32
+
33
  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
34
 
35
+ print("Initializing AnyAccomp InferencePipeline...")
36
+ try:
37
+ inference_pipeline = Sing2SongInferencePipeline(
38
+ CHECKPOINT_PATH,
39
+ CFG_PATH,
40
+ VOCODER_CHECKPOINT_PATH,
41
+ VOCODER_CFG_PATH,
42
+ device=DEVICE,
43
  )
44
+ inference_pipeline.sample_rate = 24000
45
+ print("Model loaded successfully.")
46
+ except Exception as e:
47
+ print(f"Error loading model: {e}")
48
+ inference_pipeline = None
49
+
50
+
51
+ @spaces.GPU
52
+ def sing2song_inference(vocal_filepath, n_timesteps, cfg_scale, seed):
53
+ if inference_pipeline is None:
54
+ raise gr.Error("Model could not be loaded. Please check paths and environment configuration.")
55
+
56
+ if vocal_filepath is None:
57
+ raise gr.Error("Please upload a vocal audio file.")
58
+
59
+ if seed == -1 or seed is None:
60
+ seed = random.randint(0, 2**32 - 1)
61
+
62
+ seed = int(seed)
63
+ print(f"Using seed: {seed}")
64
+
65
+ random.seed(seed)
66
+ np.random.seed(seed)
67
+ torch.manual_seed(seed)
68
+ if torch.cuda.is_available():
69
+ torch.cuda.manual_seed_all(seed)
70
+ torch.backends.cudnn.deterministic = True
71
+
72
+ try:
73
+ duration = librosa.get_duration(path=vocal_filepath)
74
+ if not (3 <= duration <= 30):
75
+ raise gr.Error("Audio duration must be between 3 and 30 seconds.")
76
+ except Exception as e:
77
+ raise gr.Error(f"Cannot read audio file or get duration: {e}")
78
 
79
+ try:
80
+ vocal_audio, _ = librosa.load(vocal_filepath, sr=24000, mono=True)
81
+ vocal_tensor = torch.tensor(vocal_audio).unsqueeze(0).to(DEVICE)
82
+
83
+ vocal_mel = inference_pipeline.encode_vocal(vocal_tensor)
84
+
85
+ with torch.cuda.amp.autocast(dtype=torch.bfloat16):
86
+ mel = inference_pipeline.model.reverse_diffusion(
87
+ vocal_mel=vocal_mel,
88
+ n_timesteps=int(n_timesteps),
89
+ cfg=cfg_scale,
90
+ )
91
+
92
+ mel = mel.float()
93
+ wav = inference_pipeline._generate_audio(mel)
94
+ wav = wav.squeeze().detach().cpu().numpy()
95
+
96
+ wav = librosa.util.fix_length(data=wav, size=len(vocal_audio))
97
+ mixture_wav = wav + vocal_audio
98
+
99
+ timestamp = int(time.time())
100
+ original_filename = os.path.basename(vocal_filepath)
101
+ base_filename = f"{os.path.splitext(original_filename)[0]}_{timestamp}.wav"
102
+
103
+ accompaniment_path = os.path.join(acc_dst, base_filename)
104
+ mixture_path = os.path.join(mixture_dst, base_filename)
105
+
106
+ sf.write(accompaniment_path, wav, 24000)
107
+ sf.write(mixture_path, mixture_wav, 24000)
108
+
109
+ return accompaniment_path, mixture_path, "Status: Complete!"
110
+
111
+ except Exception as e:
112
+ import traceback
113
+ traceback.print_exc()
114
+ raise gr.Error(f"An error occurred during processing: {e}")
115
+
116
+
117
+ def randomize_seed():
118
+ return random.randint(0, 2**32 - 1)
119
+
120
+
121
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
122
+ gr.Markdown(
123
+ """
124
+ # AnyAccomp: GENERALIZABLE ACCOMPANIMENT GENERATION
125
+ Upload a 3-30 second vocal or instrument track (.wav or .mp3) and the model will generate an accompaniment for it.
126
+ """
 
 
 
 
 
 
 
 
 
 
127
  )
128
+
129
+ with gr.Row():
130
+ with gr.Column(scale=1):
131
+ gr.Markdown("### 1. Upload Audio")
132
+ vocal_input = gr.Audio(
133
+ type="filepath",
134
+ label="Upload Vocal or Instrument Audio",
135
+ sources=["upload", "microphone"],
136
+ )
137
+
138
+ gr.Markdown("### 2. Adjust Parameters (Optional)")
139
+ with gr.Accordion("Advanced Settings", open=True):
140
+ n_timesteps_slider = gr.Slider(
141
+ minimum=10, maximum=100, value=50, step=1,
142
+ label="Inference Steps (n_timesteps)",
143
+ )
144
+ cfg_slider = gr.Slider(
145
+ minimum=1.0, maximum=10.0, value=3.0, step=0.1,
146
+ label="CFG Scale",
147
+ )
148
+ with gr.Row():
149
+ seed_input = gr.Number(value=-1, label="Seed (-1 for random)", precision=0)
150
+ random_seed_btn = gr.Button("🎲")
151
+
152
+ with gr.Column(scale=1):
153
+ gr.Markdown("### 3. Generate and Listen")
154
+ status_text = gr.Markdown("Status: Ready")
155
+ accompaniment_output = gr.Audio(label="Generated Accompaniment", type="filepath")
156
+ mixture_output = gr.Audio(label="Mixture (Vocal + Accompaniment)", type="filepath")
157
+ submit_btn = gr.Button("Generate Accompaniment", variant="primary")
158
+
159
+ submit_btn.click(
160
+ fn=sing2song_inference,
161
+ inputs=[vocal_input, n_timesteps_slider, cfg_slider, seed_input],
162
+ outputs=[accompaniment_output, mixture_output, status_text],
163
  )
164
 
165
+ random_seed_btn.click(fn=randomize_seed, inputs=None, outputs=seed_input)
 
 
 
166
 
 
 
 
 
 
 
167
 
168
+ if __name__ == "__main__":
169
+ demo.launch()
requirements.txt CHANGED
@@ -1,12 +1,11 @@
1
- git+https://github.com/TEAMuP-dev/pyharp.git#egg=pyharp
2
  torch==2.11.0
3
  torchaudio==2.11.0
4
- numpy<2.0
5
  huggingface_hub
6
  librosa
7
  soundfile
8
- accelerate
9
  json5
10
  einops
11
- transformers
12
- # do not include gradio — pyharp pins it to 5.28.0
 
1
+ spaces
2
  torch==2.11.0
3
  torchaudio==2.11.0
4
+ numpy==1.26.4
5
  huggingface_hub
6
  librosa
7
  soundfile
8
+ accelerate==1.6.0
9
  json5
10
  einops
11
+ transformers==4.47.1