ibyteohdear commited on
Commit
e99f595
·
verified ·
1 Parent(s): 9f2a732

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +157 -0
app.py CHANGED
@@ -1,3 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # --- GRADIO UI ---
2
 
3
  with gr.Blocks() as demo:
 
1
+ import spaces
2
+ import gc
3
+ import logging
4
+ import sys
5
+ import os
6
+ from datetime import datetime
7
+ from fractions import Fraction
8
+ from pathlib import Path
9
+
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,
23
+ load_video, make_video, setup_eval_logging)
24
+ from mmaudio.model.flow_matching import FlowMatching
25
+ from mmaudio.model.networks import MMAudio, get_my_mmaudio
26
+ from mmaudio.model.sequence_config import SequenceConfig
27
+ from mmaudio.model.utils.features_utils import FeaturesUtils
28
+
29
+ # Optimization flags
30
+ torch.backends.cuda.matmul.allow_tf32 = True
31
+ torch.backends.cudnn.allow_tf32 = True
32
+
33
+ log = logging.getLogger()
34
+ setup_eval_logging()
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
+
44
+ return {
45
+ "model": hf_hub_download(repo_id=MY_VAULT_REPO, filename="weights/mmaudio_large_44k_v2.pth", token=HF_TOKEN),
46
+ "vae": hf_hub_download(repo_id=MY_VAULT_REPO, filename="ext_weights/v1-44.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/v1-44.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,
68
+ enable_conditions=True,
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))
86
+
87
+ video_info = load_video(video, duration)
88
+ clip_frames = video_info.clip_frames.unsqueeze(0)
89
+ sync_frames = video_info.sync_frames.unsqueeze(0)
90
+
91
+ seq_cfg.duration = video_info.duration_sec
92
+ net.update_seq_lengths(seq_cfg.latent_seq_len, seq_cfg.clip_seq_len, seq_cfg.sync_seq_len)
93
+
94
+ audio = generate(
95
+ clip_frames, sync_frames, [prompt],
96
+ negative_text=[negative_prompt],
97
+ feature_utils=feature_utils, net=net, fm=fm, rng=rng,
98
+ cfg_strength=cfg_strength
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
  with gr.Blocks() as demo: