ibyteohdear commited on
Commit
9d3e068
·
verified ·
1 Parent(s): 9295688

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +109 -42
app.py CHANGED
@@ -10,11 +10,13 @@ from pathlib import Path
10
  import gradio as gr
11
  import torch
12
  import torchaudio
 
 
 
 
 
13
 
14
- # 1. Setup paths so 'mmaudio' package is found
15
  current_dir = os.path.dirname(os.path.abspath(__file__))
16
- # Assumes your weights are in a folder named 'weights' in the root
17
- WEIGHTS_DIR = os.path.join(current_dir, "weights")
18
  sys.path.insert(0, os.path.join(current_dir, "MMAudio"))
19
 
20
  from mmaudio.eval_utils import (ModelConfig, VideoInfo, all_model_cfg, generate, load_image,
@@ -33,29 +35,33 @@ setup_eval_logging()
33
 
34
  device = 'cuda' if torch.cuda.is_available() else 'cpu'
35
  dtype = torch.bfloat16 if device == "cuda" else torch.float32
 
36
 
37
- # 2. Configure Model Paths (Overriding the auto-downloader)
38
- model: ModelConfig = all_model_cfg['large_44k_v2']
39
- # Set these to your local paths manually
40
- model.model_path = os.path.join(WEIGHTS_DIR, "large_44k_v2.pth")
41
- model.vae_path = os.path.join(WEIGHTS_DIR, "vggsound_fp32.pth")
42
- model.synchformer_ckpt = os.path.join(WEIGHTS_DIR, "synchformer_state_dict.pth")
43
- model.bigvgan_16k_path = os.path.join(WEIGHTS_DIR, "bigvgan_16k_v2.pth")
 
 
 
44
 
45
- output_dir = Path('./output/gradio')
46
 
47
- def get_model() -> tuple[MMAudio, FeaturesUtils, SequenceConfig]:
48
- seq_cfg = model.seq_cfg
 
 
 
 
49
 
50
- # Load Main Network
 
51
  net: MMAudio = get_my_mmaudio(model.model_name).to(device, dtype).eval()
52
- if os.path.exists(model.model_path):
53
- net.load_weights(torch.load(model.model_path, map_location=device, weights_only=True))
54
- log.info(f'Loaded weights from {model.model_path}')
55
- else:
56
- log.error(f"WEIGHTS NOT FOUND AT: {model.model_path}")
57
-
58
- # Load Feature Utils (Synchformer, VAE, etc.)
59
  feature_utils = FeaturesUtils(
60
  tod_vae_ckpt=model.vae_path,
61
  synchformer_ckpt=model.synchformer_ckpt,
@@ -63,18 +69,17 @@ def get_model() -> tuple[MMAudio, FeaturesUtils, SequenceConfig]:
63
  mode=model.mode,
64
  bigvgan_vocoder_ckpt=model.bigvgan_16k_path,
65
  need_vae_encoder=False
66
- )
67
- feature_utils = feature_utils.to(device, dtype).eval()
68
 
69
  return net, feature_utils, seq_cfg
70
 
71
- # Initialize global model components
72
- net, feature_utils, seq_cfg = get_model()
 
73
 
74
  @spaces.GPU()
75
  @torch.inference_mode()
76
  def video_to_audio(video, prompt, negative_prompt, seed, num_steps, cfg_strength, duration):
77
- # Rest of your existing logic remains the same...
78
  rng = torch.Generator(device=device)
79
  rng.manual_seed(int(seed)) if seed >= 0 else rng.seed()
80
  fm = FlowMatching(min_sigma=0, inference_mode='euler', num_steps=int(num_steps))
@@ -94,36 +99,98 @@ def video_to_audio(video, prompt, negative_prompt, seed, num_steps, cfg_strength
94
  ).float().cpu()[0]
95
 
96
  output_dir.mkdir(exist_ok=True, parents=True)
97
- path = output_dir / f"{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4"
98
  make_video(video_info, path, audio, sampling_rate=seq_cfg.sampling_rate)
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  gc.collect()
101
  return path
102
 
103
- # ... [Keep your image_to_audio and text_to_audio functions here] ...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
 
105
- # UI Section
106
  video_to_audio_tab = gr.Interface(
107
  fn=video_to_audio,
108
- inputs=[
109
- gr.Video(label="Video"),
110
- gr.Text(label="Prompt"),
111
- gr.Text(label="Negative Prompt", value="music"),
112
- gr.Number(label="Seed (-1 = random)", value=-1),
113
- gr.Slider(label="Num Steps", minimum=1, maximum=100, value=25, step=1),
114
- gr.Slider(label="Guidance Strength", minimum=1, maximum=15, value=4.5, step=0.1),
115
- gr.Number(label="Max Duration (sec)", value=8),
116
- ],
117
- outputs=gr.Video(label="Generated Video"),
118
  title="Video-to-Audio"
119
  )
120
 
121
- # ... [Keep your other tabs] ...
 
 
 
 
 
 
 
 
 
 
 
 
122
 
123
  if __name__ == "__main__":
124
  output_dir.mkdir(exist_ok=True, parents=True)
125
  interface = gr.TabbedInterface(
126
- [video_to_audio_tab], # Add back text_to_audio_tab, image_to_audio_tab
127
- ["Video-to-Audio"]
128
  )
129
  interface.launch(server_name="0.0.0.0", server_port=7860)
 
10
  import gradio as gr
11
  import torch
12
  import torchaudio
13
+ from huggingface_hub import hf_hub_download
14
+
15
+ # --- CONFIGURATION & PATHS ---
16
+ MY_VAULT_REPO = "ibyteohdear/mmaudio-weights-vault"
17
+ HF_TOKEN = os.getenv("HF_TOKEN")
18
 
 
19
  current_dir = os.path.dirname(os.path.abspath(__file__))
 
 
20
  sys.path.insert(0, os.path.join(current_dir, "MMAudio"))
21
 
22
  from mmaudio.eval_utils import (ModelConfig, VideoInfo, all_model_cfg, generate, load_image,
 
35
 
36
  device = 'cuda' if torch.cuda.is_available() else 'cpu'
37
  dtype = torch.bfloat16 if device == "cuda" else torch.float32
38
+ output_dir = Path('./output/gradio')
39
 
40
+ # --- WEIGHT SYNCHRONIZATION ---
41
+ def get_weights():
42
+ log.info(f"Syncing weights from {MY_VAULT_REPO}...")
43
+ # Adjust filenames below to match your actual vault structure
44
+ return {
45
+ "model": hf_hub_download(repo_id=MY_VAULT_REPO, filename="weights/large_44k_v2.pth", token=HF_TOKEN),
46
+ "vae": hf_hub_download(repo_id=MY_VAULT_REPO, filename="ext_weights/vggsound_fp32.pth", token=HF_TOKEN),
47
+ "sync": hf_hub_download(repo_id=MY_VAULT_REPO, filename="ext_weights/synchformer_state_dict.pth", token=HF_TOKEN),
48
+ "vocoder": hf_hub_download(repo_id=MY_VAULT_REPO, filename="ext_weights/bigvgan_16k_v2.pth", token=HF_TOKEN)
49
+ }
50
 
51
+ weight_paths = get_weights()
52
 
53
+ # --- MODEL INITIALIZATION ---
54
+ model: ModelConfig = all_model_cfg['large_44k_v2']
55
+ model.model_path = weight_paths["model"]
56
+ model.vae_path = weight_paths["vae"]
57
+ model.synchformer_ckpt = weight_paths["sync"]
58
+ model.bigvgan_16k_path = weight_paths["vocoder"]
59
 
60
+ def load_all_models() -> tuple[MMAudio, FeaturesUtils, SequenceConfig]:
61
+ seq_cfg = model.seq_cfg
62
  net: MMAudio = get_my_mmaudio(model.model_name).to(device, dtype).eval()
63
+ net.load_weights(torch.load(model.model_path, map_location=device, weights_only=True))
64
+
 
 
 
 
 
65
  feature_utils = FeaturesUtils(
66
  tod_vae_ckpt=model.vae_path,
67
  synchformer_ckpt=model.synchformer_ckpt,
 
69
  mode=model.mode,
70
  bigvgan_vocoder_ckpt=model.bigvgan_16k_path,
71
  need_vae_encoder=False
72
+ ).to(device, dtype).eval()
 
73
 
74
  return net, feature_utils, seq_cfg
75
 
76
+ net, feature_utils, seq_cfg = load_all_models()
77
+
78
+ # --- INFERENCE FUNCTIONS ---
79
 
80
  @spaces.GPU()
81
  @torch.inference_mode()
82
  def video_to_audio(video, prompt, negative_prompt, seed, num_steps, cfg_strength, duration):
 
83
  rng = torch.Generator(device=device)
84
  rng.manual_seed(int(seed)) if seed >= 0 else rng.seed()
85
  fm = FlowMatching(min_sigma=0, inference_mode='euler', num_steps=int(num_steps))
 
99
  ).float().cpu()[0]
100
 
101
  output_dir.mkdir(exist_ok=True, parents=True)
102
+ path = output_dir / f"v2a_{datetime.now().strftime('%H%M%S')}.mp4"
103
  make_video(video_info, path, audio, sampling_rate=seq_cfg.sampling_rate)
104
+ gc.collect()
105
+ return path
106
+
107
+ @spaces.GPU()
108
+ @torch.inference_mode()
109
+ def image_to_audio(image, prompt, negative_prompt, seed, num_steps, cfg_strength, duration):
110
+ rng = torch.Generator(device=device)
111
+ rng.manual_seed(int(seed)) if seed >= 0 else rng.seed()
112
+ fm = FlowMatching(min_sigma=0, inference_mode='euler', num_steps=int(num_steps))
113
+
114
+ image_info = load_image(image)
115
+ clip_frames = image_info.clip_frames.unsqueeze(0)
116
+ sync_frames = image_info.sync_frames.unsqueeze(0)
117
 
118
+ seq_cfg.duration = duration
119
+ net.update_seq_lengths(seq_cfg.latent_seq_len, seq_cfg.clip_seq_len, seq_cfg.sync_seq_len)
120
+
121
+ audio = generate(
122
+ clip_frames, sync_frames, [prompt],
123
+ negative_text=[negative_prompt],
124
+ feature_utils=feature_utils, net=net, fm=fm, rng=rng,
125
+ cfg_strength=cfg_strength, image_input=True
126
+ ).float().cpu()[0]
127
+
128
+ output_dir.mkdir(exist_ok=True, parents=True)
129
+ path = output_dir / f"i2a_{datetime.now().strftime('%H%M%S')}.mp4"
130
+ video_info = VideoInfo.from_image_info(image_info, duration, fps=Fraction(1))
131
+ make_video(video_info, path, audio, sampling_rate=seq_cfg.sampling_rate)
132
  gc.collect()
133
  return path
134
 
135
+ @spaces.GPU()
136
+ @torch.inference_mode()
137
+ def text_to_audio(prompt, negative_prompt, seed, num_steps, cfg_strength, duration):
138
+ rng = torch.Generator(device=device)
139
+ rng.manual_seed(int(seed)) if seed >= 0 else rng.seed()
140
+ fm = FlowMatching(min_sigma=0, inference_mode='euler', num_steps=int(num_steps))
141
+
142
+ seq_cfg.duration = duration
143
+ net.update_seq_lengths(seq_cfg.latent_seq_len, seq_cfg.clip_seq_len, seq_cfg.sync_seq_len)
144
+
145
+ audio = generate(
146
+ None, None, [prompt],
147
+ negative_text=[negative_prompt],
148
+ feature_utils=feature_utils, net=net, fm=fm, rng=rng,
149
+ cfg_strength=cfg_strength
150
+ ).float().cpu()[0]
151
+
152
+ output_dir.mkdir(exist_ok=True, parents=True)
153
+ path = output_dir / f"t2a_{datetime.now().strftime('%H%M%S')}.flac"
154
+ torchaudio.save(path, audio, seq_cfg.sampling_rate)
155
+ gc.collect()
156
+ return path
157
+
158
+ # --- GRADIO UI ---
159
+
160
+ common_inputs = [
161
+ gr.Text(label="Prompt"),
162
+ gr.Text(label="Negative Prompt", value="music"),
163
+ gr.Number(label="Seed (-1 = random)", value=-1),
164
+ gr.Slider(label="Num Steps", minimum=1, maximum=100, value=25, step=1),
165
+ gr.Slider(label="Guidance Strength", minimum=1, maximum=15, value=4.5, step=0.1),
166
+ gr.Number(label="Duration (sec)", value=8),
167
+ ]
168
 
 
169
  video_to_audio_tab = gr.Interface(
170
  fn=video_to_audio,
171
+ inputs=[gr.Video(label="Input Video")] + common_inputs,
172
+ outputs=gr.Video(label="Generated Video with Audio"),
 
 
 
 
 
 
 
 
173
  title="Video-to-Audio"
174
  )
175
 
176
+ image_to_audio_tab = gr.Interface(
177
+ fn=image_to_audio,
178
+ inputs=[gr.Image(label="Input Image", type="filepath")] + common_inputs,
179
+ outputs=gr.Video(label="Static Video with Audio"),
180
+ title="Image-to-Audio"
181
+ )
182
+
183
+ text_to_audio_tab = gr.Interface(
184
+ fn=text_to_audio,
185
+ inputs=common_inputs[:5] + [gr.Number(label="Duration (sec)", value=8)],
186
+ outputs=gr.Audio(label="Generated Audio"),
187
+ title="Text-to-Audio"
188
+ )
189
 
190
  if __name__ == "__main__":
191
  output_dir.mkdir(exist_ok=True, parents=True)
192
  interface = gr.TabbedInterface(
193
+ [video_to_audio_tab, image_to_audio_tab, text_to_audio_tab],
194
+ ["Video-to-Audio", "Image-to-Audio", "Text-to-Audio"]
195
  )
196
  interface.launch(server_name="0.0.0.0", server_port=7860)