Spaces:
Starting
on
T4
Starting
on
T4
Allow Melody in MCP call
Browse files- app.py +13 -4
- modules/file_utils.py +33 -0
- requirements.txt +3 -1
app.py
CHANGED
@@ -33,7 +33,7 @@ import librosa
|
|
33 |
import modules.user_history
|
34 |
from modules.version_info import versions_html, commit_hash, get_xformers_version
|
35 |
from modules.gradio import *
|
36 |
-
from modules.file_utils import get_file_parts, get_filename_from_filepath, convert_title_to_filename, get_unique_file_path, delete_file, download_and_save_image
|
37 |
from modules.constants import IS_SHARED_SPACE, HF_REPO_ID, TMPDIR, HF_API_TOKEN
|
38 |
from modules.storage import upload_files_to_repo
|
39 |
|
@@ -294,11 +294,17 @@ def predict(model, text, melody_filepath = None, duration=10, dimension=2, topk=
|
|
294 |
if melody_filepath in ["None", ""]:
|
295 |
melody_filepath = None
|
296 |
|
|
|
|
|
|
|
|
|
|
|
|
|
297 |
#if background is a url string, download it using download_and_save_image
|
298 |
if background is None or background in ["None", ""]:
|
299 |
background = load_background_filepath(video_orientation)
|
300 |
|
301 |
-
if background.startswith("http://"
|
302 |
username = profile if isinstance(profile, str) else profile.value.username if hasattr(profile.value, 'username') else "default_user" if (profile is None) else profile
|
303 |
background = download_and_save_image(background, Path(TMPDIR) / str(username), HF_API_TOKEN)
|
304 |
|
@@ -615,13 +621,14 @@ def fix_path(path: str) -> str:
|
|
615 |
return "./" + path[index:].replace("\\", "/")
|
616 |
return path
|
617 |
# Add this wrapper function above the gr.api definitions
|
618 |
-
def predict_simple(model: str, text: str, duration: int = 10, dimension: int = 2, topk: int = 200, topp: float = 0.01, temperature: float = 1.0, cfg_coef: float = 4.0, background: str = "./assets/background.png", title: str = "UnlimitedMusicGen", settings_font: str = "./assets/arial.ttf", settings_font_color: str = "#c87f05", seed: int = -1, overlap: int = 1, prompt_index: int = -1, include_title: bool = True, include_settings: bool = True, profile: str = "Satoshi Nakamoto", segment_length: int = 30, settings_font_size: int = 28, settings_animate_waveform: bool = False, video_orientation: str = "Landscape", return_history_json: bool = False) -> tp.List[tp.Tuple[str, str, str]]:
|
619 |
"""
|
620 |
Generate music and video based on the provided parameters and model.
|
621 |
|
622 |
Args:
|
623 |
model (str): Model name to use for generation.
|
624 |
text (str): Prompt describing the music.
|
|
|
625 |
duration (int): Total duration in seconds.
|
626 |
dimension (int): Audio stacking/concatenation dimension.
|
627 |
topk (int): Top-k sampling value.
|
@@ -637,6 +644,7 @@ def predict_simple(model: str, text: str, duration: int = 10, dimension: int = 2
|
|
637 |
prompt_index (int, optional): Melody segment index. Default to -1.
|
638 |
include_title (bool, optional): Whether to add title to video. Default to True.
|
639 |
include_settings (bool, optional): Whether to add settings to video. Default to True.
|
|
|
640 |
profile (str, optional): User profile.
|
641 |
segment_length (int, optional): Segment length in seconds.
|
642 |
settings_font_size (int, optional): Font size for settings text.
|
@@ -664,7 +672,7 @@ def predict_simple(model: str, text: str, duration: int = 10, dimension: int = 2
|
|
664 |
elif isinstance(actual_profile_data, str) and actual_profile_data: # string username
|
665 |
profile_username_to_send = actual_profile_data
|
666 |
|
667 |
-
UMG_result = predict(model, text, melody_filepath=
|
668 |
|
669 |
# upload to storage and return urls
|
670 |
folder_name = f"user_uploads/{convert_title_to_filename(profile_username_to_send)}/{convert_title_to_filename(title)}"
|
@@ -868,6 +876,7 @@ def ui(**kwargs):
|
|
868 |
launch_kwargs['allowed_paths'] = ["assets", "./assets", "images", "./images", 'e:/TMP']
|
869 |
launch_kwargs['favicon_path'] = "./assets/favicon.ico"
|
870 |
launch_kwargs['mcp_server'] = True
|
|
|
871 |
|
872 |
gr.api(ping, api_name="ping")
|
873 |
gr.api(predict_simple)
|
|
|
33 |
import modules.user_history
|
34 |
from modules.version_info import versions_html, commit_hash, get_xformers_version
|
35 |
from modules.gradio import *
|
36 |
+
from modules.file_utils import get_file_parts, get_filename_from_filepath, convert_title_to_filename, get_unique_file_path, delete_file, download_and_save_image, download_and_save_file
|
37 |
from modules.constants import IS_SHARED_SPACE, HF_REPO_ID, TMPDIR, HF_API_TOKEN
|
38 |
from modules.storage import upload_files_to_repo
|
39 |
|
|
|
294 |
if melody_filepath in ["None", ""]:
|
295 |
melody_filepath = None
|
296 |
|
297 |
+
|
298 |
+
# if melody_filepath is a url string, download it using download_and_save_file
|
299 |
+
if melody_filepath and melody_filepath.startswith(("http://", "https://")):
|
300 |
+
username = profile if isinstance(profile, str) else profile.value.username if hasattr(profile.value, 'username') else "default_user" if (profile is None) else profile
|
301 |
+
melody_filepath = download_and_save_file(melody_filepath, Path(TMPDIR) / str(username), HF_API_TOKEN)
|
302 |
+
|
303 |
#if background is a url string, download it using download_and_save_image
|
304 |
if background is None or background in ["None", ""]:
|
305 |
background = load_background_filepath(video_orientation)
|
306 |
|
307 |
+
if background.startswith(("http://", "https://")):
|
308 |
username = profile if isinstance(profile, str) else profile.value.username if hasattr(profile.value, 'username') else "default_user" if (profile is None) else profile
|
309 |
background = download_and_save_image(background, Path(TMPDIR) / str(username), HF_API_TOKEN)
|
310 |
|
|
|
621 |
return "./" + path[index:].replace("\\", "/")
|
622 |
return path
|
623 |
# Add this wrapper function above the gr.api definitions
|
624 |
+
def predict_simple(model: str, text: str, melody_filepath: str = None, duration: int = 10, dimension: int = 2, topk: int = 200, topp: float = 0.01, temperature: float = 1.0, cfg_coef: float = 4.0, background: str = "./assets/background.png", title: str = "UnlimitedMusicGen", settings_font: str = "./assets/arial.ttf", settings_font_color: str = "#c87f05", seed: int = -1, overlap: int = 1, prompt_index: int = -1, include_title: bool = True, include_settings: bool = True, harmony_only: bool = False, profile: str = "Satoshi Nakamoto", segment_length: int = 30, settings_font_size: int = 28, settings_animate_waveform: bool = False, video_orientation: str = "Landscape", return_history_json: bool = False) -> tp.List[tp.Tuple[str, str, str]]:
|
625 |
"""
|
626 |
Generate music and video based on the provided parameters and model.
|
627 |
|
628 |
Args:
|
629 |
model (str): Model name to use for generation.
|
630 |
text (str): Prompt describing the music.
|
631 |
+
melody_filepath (str, optional): Path to melody conditioning file. Default to None.
|
632 |
duration (int): Total duration in seconds.
|
633 |
dimension (int): Audio stacking/concatenation dimension.
|
634 |
topk (int): Top-k sampling value.
|
|
|
644 |
prompt_index (int, optional): Melody segment index. Default to -1.
|
645 |
include_title (bool, optional): Whether to add title to video. Default to True.
|
646 |
include_settings (bool, optional): Whether to add settings to video. Default to True.
|
647 |
+
harmony_only (bool, optional): Whether to use harmony only. Default to False.
|
648 |
profile (str, optional): User profile.
|
649 |
segment_length (int, optional): Segment length in seconds.
|
650 |
settings_font_size (int, optional): Font size for settings text.
|
|
|
672 |
elif isinstance(actual_profile_data, str) and actual_profile_data: # string username
|
673 |
profile_username_to_send = actual_profile_data
|
674 |
|
675 |
+
UMG_result = predict(model, text, melody_filepath=melody_filepath, duration=duration, dimension=dimension, topk=topk, topp=topp, temperature=temperature, cfg_coef=cfg_coef, background=background, title=title, settings_font=settings_font, settings_font_color=settings_font_color, seed=seed, overlap=overlap, prompt_index=prompt_index, include_title=include_title, include_settings=include_settings, harmony_only=harmony_only, profile=profile, segment_length=segment_length, settings_font_size=settings_font_size, settings_animate_waveform=settings_animate_waveform, video_orientation=video_orientation, excerpt_duration=3.5, return_history_json=return_history_json)
|
676 |
|
677 |
# upload to storage and return urls
|
678 |
folder_name = f"user_uploads/{convert_title_to_filename(profile_username_to_send)}/{convert_title_to_filename(title)}"
|
|
|
876 |
launch_kwargs['allowed_paths'] = ["assets", "./assets", "images", "./images", 'e:/TMP']
|
877 |
launch_kwargs['favicon_path'] = "./assets/favicon.ico"
|
878 |
launch_kwargs['mcp_server'] = True
|
879 |
+
launch_kwargs['ssr_mode'] = False
|
880 |
|
881 |
gr.api(ping, api_name="ping")
|
882 |
gr.api(predict_simple)
|
modules/file_utils.py
CHANGED
@@ -153,4 +153,37 @@ def download_and_save_image(url: str, dst_folder: Path, token: str = None) -> Pa
|
|
153 |
dst = Path(unique_filepath_str)
|
154 |
dst_folder.mkdir(parents=True, exist_ok=True)
|
155 |
pil_image.save(dst)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
return dst
|
|
|
153 |
dst = Path(unique_filepath_str)
|
154 |
dst_folder.mkdir(parents=True, exist_ok=True)
|
155 |
pil_image.save(dst)
|
156 |
+
return dst
|
157 |
+
|
158 |
+
def download_and_save_file(url: str, dst_folder: Path, token: str = None) -> Path:
|
159 |
+
"""
|
160 |
+
Downloads a binary file (e.g., audio or video) from a URL with authentication if a token is provided,
|
161 |
+
and saves it in dst_folder with a unique filename.
|
162 |
+
|
163 |
+
Args:
|
164 |
+
url (str): The file URL.
|
165 |
+
dst_folder (Path): The destination folder for the file.
|
166 |
+
token (str, optional): A valid Bearer token.
|
167 |
+
|
168 |
+
Returns:
|
169 |
+
Path: The saved file's path.
|
170 |
+
"""
|
171 |
+
headers = {}
|
172 |
+
if token:
|
173 |
+
headers["Authorization"] = f"Bearer {token}"
|
174 |
+
|
175 |
+
response = requests.get(url, headers=headers)
|
176 |
+
response.raise_for_status()
|
177 |
+
|
178 |
+
parsed_url = urlparse(url)
|
179 |
+
original_filename = os.path.basename(parsed_url.path)
|
180 |
+
base, ext = os.path.splitext(original_filename)
|
181 |
+
|
182 |
+
unique_filepath_str = get_unique_file_path(str(dst_folder), base, ext)
|
183 |
+
dst = Path(unique_filepath_str)
|
184 |
+
dst_folder.mkdir(parents=True, exist_ok=True)
|
185 |
+
|
186 |
+
with open(dst, "wb") as f:
|
187 |
+
f.write(response.content)
|
188 |
+
|
189 |
return dst
|
requirements.txt
CHANGED
@@ -38,4 +38,6 @@ spacy==3.7.6
|
|
38 |
sentencepiece
|
39 |
num2words
|
40 |
numpy<1.26.4
|
41 |
-
matplotlib
|
|
|
|
|
|
38 |
sentencepiece
|
39 |
num2words
|
40 |
numpy<1.26.4
|
41 |
+
matplotlib
|
42 |
+
fastapi>=0.115.0
|
43 |
+
starlette>=0.40.0
|