""" Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved. This source code is licensed under the license found in the LICENSE file in the root directory of this source tree. """ from tempfile import NamedTemporaryFile import argparse import torch import gradio as gr import os import subprocess import sys from pathlib import Path import time import typing as tp import warnings import gc from tqdm import tqdm import numpy as np import random import shutil from mutagen.mp4 import MP4 #from typing import List, Union import librosa import modules.user_history from modules.version_info import versions_html, commit_hash, get_xformers_version from modules.gradio import * 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 # Added for MCP call from smolagents.mcp_client import MCPClient from modules.storage import upload_files_to_repo from modules.constants import HF_REPO_ID, umg_mcp_server, TMPDIR, HF_API_TOKEN, IS_SHARED_SPACE MODEL = None MODELS = None #IS_SHARED_SPACE = "Agents-MCP-Hackathon/UnlimitedMusicGen" in os.environ.get('SPACE_ID', '') INTERRUPTED = False UNLOAD_MODEL = False MOVE_TO_CPU = False MAX_PROMPT_INDEX = 0 git = os.environ.get('GIT', "git") #s.environ["CUDA_LAUNCH_BLOCKING"] = "1" os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "max_split_size_mb:128,expandable_segments:True" os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0' os.environ['CUDA_MODULE_LOADING']='LAZY' os.environ['USE_FLASH_ATTENTION'] = '1' os.environ['XFORMERS_FORCE_DISABLE_TRITON']= '1' def interrupt_callback(): return INTERRUPTED def interrupt(): global INTERRUPTING INTERRUPTING = True class FileCleaner: def __init__(self, file_lifetime: float = 3600): self.file_lifetime = file_lifetime self.files = [] def add(self, path: tp.Union[str, Path]): self._cleanup() self.files.append((time.time(), Path(path))) def _cleanup(self): now = time.time() for time_added, path in list(self.files): if now - time_added > self.file_lifetime: if path.exists(): path.unlink() self.files.pop(0) else: break #file_cleaner = FileCleaner() def toggle_audio_src(choice): """ Toggle the audio input source between microphone and file upload. Args: choice (str): The selected audio source, either 'mic' or 'upload'. Returns: gr.Update: Gradio update object to change the audio input component. """ if choice == "mic": return gr.update(source="microphone", value=None, label="Microphone") else: return gr.update(source="upload", value=None, label="File") def get_waveform(*args, **kwargs): """ Generate a waveform video for the given audio input. Args: melody_filepath (str): Path to the melody audio file. Returns: tuple: (sample_rate, audio_data) loaded from the file. """ be = time.time() with warnings.catch_warnings(): warnings.simplefilter('ignore') out = gr.make_waveform(*args, **kwargs) print("Make a video took", time.time() - be) return out def load_model(version, progress=gr.Progress(track_tqdm=True)): """ Load a MusicGen model by version name, optionally showing progress. Args: version (str): The model version to load. progress (gr.Progress, optional): Gradio progress tracker. Returns: MusicGen: The loaded MusicGen model instance. """ global MODEL, MODELS, UNLOAD_MODEL print("Loading model", version) with tqdm(total=100, desc=f"Loading model '{version}'", unit="step") as pbar: if MODELS is None: pbar.update(50) # Simulate progress for loading result = MusicGen.get_pretrained(version) pbar.update(50) # Complete progress return result else: t1 = time.monotonic() if MODEL is not None: MODEL.to('cpu') # Move to cache print("Previous model moved to CPU in %.2fs" % (time.monotonic() - t1)) pbar.update(30) # Simulate progress for moving model to CPU t1 = time.monotonic() if MODELS.get(version) is None: print("Loading model %s from disk" % version) result = MusicGen.get_pretrained(version) MODELS[version] = result print("Model loaded in %.2fs" % (time.monotonic() - t1)) pbar.update(70) # Simulate progress for loading from disk return result result = MODELS[version].to('cuda') print("Cached model loaded in %.2fs" % (time.monotonic() - t1)) pbar.update(100) # Complete progress return result def get_melody(melody_filepath): audio_data= list(librosa.load(melody_filepath, sr=None)) audio_data[0], audio_data[1] = audio_data[1], audio_data[0] melody = tuple(audio_data) return melody def git_tag(): """ Get the current git tag or fallback to the first line of CHANGELOG.md if unavailable. Returns: str: The current git tag or '' if not available. """ try: return subprocess.check_output([git, "describe", "--tags"], shell=False, encoding='utf8').strip() except Exception: try: from pathlib import Path changelog_md = Path(__file__).parent.parent / "CHANGELOG.md" with changelog_md.open(encoding="utf-8") as file: return next((line.strip() for line in file if line.strip()), "") except Exception: return "" def load_background_filepath(video_orientation): """ Get the background image path based on video orientation. Args: video_orientation (str): Either 'Landscape' or 'Portrait'. Returns: str: Path to the background image file. """ if video_orientation == "Landscape": return "./assets/background.png" else: return "./assets/background_portrait.png" def load_melody_filepath(melody_filepath, title, assigned_model, topp, temperature, cfg_coef, segment_length = 30): """ Update melody-related UI fields based on the selected melody file and settings. Args: melody_filepath (str): Path to the melody file. title (str): The song title. assigned_model (str): The selected model name. topp (float): Top-p sampling value. temperature (float): Sampling temperature. cfg_coef (float): Classifier-free guidance coefficient. segment_length (int, optional): Segment length in seconds. Returns: tuple: Updated values for title, prompt_index, model, topp, temperature, cfg_coef, overlap. """ # get melody filename #$Union[str, os.PathLike] symbols = ['_', '.', '-'] MAX_OVERLAP = int(segment_length // 2) - 1 if (melody_filepath is None) or (melody_filepath == ""): return title, gr.update(maximum=0, value=-1) , gr.update(value="medium", interactive=True), gr.update(value=topp), gr.update(value=temperature), gr.update(value=cfg_coef), gr.update(maximum=MAX_OVERLAP) if (title is None) or ("MusicGen" in title) or (title == ""): melody_name, melody_extension = get_filename_from_filepath(melody_filepath) # fix melody name for symbols for symbol in symbols: melody_name = melody_name.replace(symbol, ' ').title() #additonal melody setting updates topp = 800 temperature = 0.5 cfg_coef = 3.25 else: melody_name = title if ("melody" not in assigned_model): assigned_model = "melody-large" print(f"Melody name: {melody_name}, Melody Filepath: {melody_filepath}, Model: {assigned_model}\n") # get melody length in number of segments and modify the UI melody = get_melody(melody_filepath) sr, melody_data = melody[0], melody[1] segment_samples = sr * segment_length total_melodys = max(min((len(melody_data) // segment_samples), 25), 0) print(f"Melody length: {len(melody_data)}, Melody segments: {total_melodys}\n") MAX_PROMPT_INDEX = total_melodys return gr.update(value=melody_name), gr.update(maximum=MAX_PROMPT_INDEX, value=-1), gr.update(value=assigned_model, interactive=True), gr.update(value=topp), gr.update(value=temperature), gr.update(value=cfg_coef), gr.update(maximum=MAX_OVERLAP) def predict( model_name_arg, # Renamed from 'model' text_arg, melody_filepath_arg, duration_arg, dimension_arg, topk_arg, topp_arg, temperature_arg, cfg_coef_arg, background_image_arg, # Renamed from 'background' title_arg, settings_font_path_arg, # Renamed from 'settings_font' settings_font_color_arg, seed_arg, overlap_arg=1, prompt_index_arg=0, include_title_arg=True, include_settings_arg=True, harmony_only_arg=False, profile_arg: tp.Optional[gr.OAuthProfile] = None, # Type hint for clarity, Gradio passes OAuthProfile or None username_arg: tp.Optional[str] = None, # Optional username for profile segment_length_arg=30, settings_font_size_arg=28, settings_animate_waveform_arg=False, video_orientation_arg="Landscape", excerpt_duration_arg=3.5, progress_arg=gr.Progress(track_tqdm=True) # Renamed from 'progress', Gradio handles this ): """ Generate music and video by calling a remote MCP endpoint tool. This function replaces the original local model inference. """ global INTERRUPTED, INTERRUPTING # Retained, though effect on remote job is indirect INTERRUPTED = False INTERRUPTING = False # Helper to get value if it's a Gradio State object def get_value_if_state(arg): if hasattr(arg, 'value'): return arg.value return arg model_name_arg = get_value_if_state(model_name_arg) text_arg = get_value_if_state(text_arg) melody_filepath_arg = get_value_if_state(melody_filepath_arg) duration_arg = get_value_if_state(duration_arg) dimension_arg = get_value_if_state(dimension_arg) topk_arg = get_value_if_state(topk_arg) topp_arg = get_value_if_state(topp_arg) temperature_arg = get_value_if_state(temperature_arg) cfg_coef_arg = get_value_if_state(cfg_coef_arg) background_image_arg = get_value_if_state(background_image_arg) title_arg = get_value_if_state(title_arg) settings_font_path_arg = get_value_if_state(settings_font_path_arg) settings_font_color_arg = get_value_if_state(settings_font_color_arg) seed_arg = get_value_if_state(seed_arg) overlap_arg = get_value_if_state(overlap_arg) prompt_index_arg = get_value_if_state(prompt_index_arg) include_title_arg = get_value_if_state(include_title_arg) include_settings_arg = get_value_if_state(include_settings_arg) # harmony_only_arg is handled specifically below # profile_arg is handled specifically below segment_length_arg = get_value_if_state(segment_length_arg) settings_font_size_arg = get_value_if_state(settings_font_size_arg) settings_animate_waveform_arg = get_value_if_state(settings_animate_waveform_arg) video_orientation_arg = get_value_if_state(video_orientation_arg) excerpt_duration_arg = get_value_if_state(excerpt_duration_arg) print(f"Initiating MCP call to {umg_mcp_server} tool UnlimitedMusicGen_predict") mcp_client = None melody_file_url = None # Changed from melody_file_obj background_image_url = None # Changed from background_reference try: # Upload files to Hugging Face Hub and get URLs files_to_upload = [] if melody_filepath_arg and melody_filepath_arg not in ["None", ""] and not melody_filepath_arg.startswith("http"): files_to_upload.append(melody_filepath_arg) if background_image_arg and background_image_arg not in ["None", ""] and not background_image_arg.startswith("http"): files_to_upload.append(background_image_arg) uploaded_file_urls = {} if files_to_upload: # Use a unique folder name for each upload session, e.g., based on timestamp or a random string # For simplicity, using a fixed folder name here, but consider making it unique. # The username from profile_arg could be used to create a user-specific folder. profile_username_for_folder = "default_user" if profile_arg: # Check if profile_arg is a Gradio State object holding an OAuthProfile or string actual_profile_data = profile_arg if hasattr(profile_arg, 'value'): # Handles gr.State wrapping OAuthProfile or string (and profile_arg.value is not None) actual_profile_data = profile_arg.value if hasattr(actual_profile_data, 'username') and actual_profile_data.username: # OAuthProfile object profile_username_for_folder = actual_profile_data.username elif isinstance(actual_profile_data, str) and actual_profile_data: # String username profile_username_for_folder = actual_profile_data folder_name = f"user_uploads/{profile_username_for_folder}/{convert_title_to_filename(title_arg)}/{seed_arg}/{time.strftime('%Y%m%d%H%M%S')}" upload_results = upload_files_to_repo( files=files_to_upload, repo_id=HF_REPO_ID, folder_name=folder_name, create_permalink=False # We need individual links ) print(f"Upload results: {upload_results}") if isinstance(upload_results, list): for i, file_path in enumerate(files_to_upload): original_filename = os.path.basename(file_path) # Find the corresponding URL from upload_results # The upload_results list contains tuples of (response, link) # We need to match the uploaded file with its original path to assign the correct URL # Assuming the order is preserved or filenames in links are reliable for _, link in upload_results: if original_filename in link: uploaded_file_urls[file_path] = link break else: print(f"Warning: Expected a list from upload_files_to_repo, got {type(upload_results)}") if melody_filepath_arg and melody_filepath_arg in uploaded_file_urls: melody_file_url = uploaded_file_urls[melody_filepath_arg] print(f"Melody file uploaded to: {melody_file_url}") elif melody_filepath_arg and melody_filepath_arg not in ["None", ""]: # File was provided but not uploaded (e.g. error) print(f"Warning: Melody file {melody_filepath_arg} was provided but not successfully uploaded or URL not found.") if background_image_arg and background_image_arg in uploaded_file_urls: background_image_url = uploaded_file_urls[background_image_arg] print(f"Background image uploaded to: {background_image_url}") elif background_image_arg and background_image_arg.startswith("http"): background_image_url = background_image_arg # It's already a URL print(f"Using existing background image URL: {background_image_url}") elif background_image_arg and background_image_arg not in ["None", ""]: # File was provided but not uploaded print(f"Warning: Background image {background_image_arg} was provided but not successfully uploaded or URL not found.") mcp_client = MCPClient({"url": umg_mcp_server, "transport": "sse"}) tools = mcp_client.get_tools() predict_tool = next((t for t in tools if "predict_simple" in t.name), None) if not predict_tool: raise gr.Error(f"MCP tool '{predict_tool.name}' not found on the server.") profile_username_to_send = "default_user" if profile_arg: actual_profile_data = profile_arg # Unwrap if it's a gr.State object if hasattr(profile_arg, 'value') and profile_arg.value is not None: actual_profile_data = profile_arg.value # Now actual_profile_data is either an OAuthProfile or a string username if hasattr(actual_profile_data, 'username') and actual_profile_data.username: # OAuthProfile profile_username_to_send = actual_profile_data.username elif isinstance(actual_profile_data, str) and actual_profile_data: # string username profile_username_to_send = actual_profile_data actual_harmony_only = False if isinstance(harmony_only_arg, str): actual_harmony_only = harmony_only_arg.lower() == "yes" elif isinstance(harmony_only_arg, bool): actual_harmony_only = harmony_only_arg tool_args = { "model": model_name_arg, "text": text_arg, "melody_filepath": melody_file_url, # Pass URL instead of file object "duration": duration_arg, "dimension": dimension_arg, "topk": topk_arg, "topp": topp_arg, "temperature": temperature_arg, "cfg_coef": cfg_coef_arg, "background": background_image_url, # Pass URL "title": title_arg, "settings_font": settings_font_path_arg, "settings_font_color": settings_font_color_arg, "seed": seed_arg, "overlap": overlap_arg, "prompt_index": prompt_index_arg, "include_title": include_title_arg, "include_settings": include_settings_arg, "harmony_only": actual_harmony_only, "profile": profile_username_to_send, "segment_length": segment_length_arg, "settings_font_size": settings_font_size_arg, "settings_animate_waveform": settings_animate_waveform_arg, "video_orientation": video_orientation_arg, "return_history_json": True # "excerpt_duration": excerpt_duration_arg, } print(f"Calling remote MCP tool '{predict_tool.name}' with arguments (URLs for files).") results = predict_tool(**tool_args) print(f"MCP tool call completed. Raw results: {results}") if isinstance(results, str) and results.startswith('[') and results.endswith(']'): try: import ast results = ast.literal_eval(results) print(f"Parsed results as list: {results}") except (SyntaxError, ValueError) as e: print(f"Failed to parse results string as list: {e}") if not isinstance(results, (list, tuple)) or len(results) != 3: raise gr.Error(f"MCP tool '{predict_tool.name}' did not return the expected 3 values. Received: {results}") waveform_video_path, wave_file_path, seed_used = results if not ((waveform_video_path is None or isinstance(waveform_video_path, str)) and (wave_file_path is None or isinstance(wave_file_path, str))): error_msg = (f"MCP tool returned invalid file paths. " f"Video path type: {type(waveform_video_path)}, " f"Audio path type: {type(wave_file_path)}") raise gr.Error(error_msg) if not isinstance(seed_used, (int, float)): # Allow float for seed then cast later raise gr.Error(f"MCP tool returned a non-numeric seed. Received type: {type(seed_used)}, value: {seed_used}") if isinstance(waveform_video_path, str) and (waveform_video_path.startswith("http://") or waveform_video_path.startswith("https://")): waveform_video_path = str(download_and_save_file(waveform_video_path, Path(TMPDIR) / str(profile_username_to_send), HF_API_TOKEN)) if isinstance(wave_file_path, str) and (wave_file_path.startswith("http://") or wave_file_path.startswith("https://")): wave_file_path = str(download_and_save_file(wave_file_path, Path(TMPDIR) / str(profile_username_to_send), HF_API_TOKEN)) return waveform_video_path, wave_file_path, int(seed_used) except Exception as e: error_message = f"Error during MCP tool call or file upload: {str(e)}" print(error_message) import traceback traceback.print_exc() if isinstance(e, gr.Error): raise else: raise gr.Error(error_message) finally: # No file objects to close here as we are passing URLs if mcp_client: try: mcp_client.disconnect() print("MCP client disconnected.") except Exception as e_disconnect: print(f"Error disconnecting MCP client: {e_disconnect}") gr.set_static_paths(paths=["fonts/","assets/","images/"]) def ui(**kwargs): with gr.Blocks(title="UnlimitedMusicGen",css_paths="style_20250331.css", theme='Surn/beeuty') as demo: with gr.Tab("UnlimitedMusicGen"): gr.Markdown( """ # UnlimitedMusicGen This is your MCP Client demo for [UnlimitedMusicGen](https://github.com/Oncorporation/audiocraft), a simple and controllable model for music generation presented at: ["Simple and Controllable Music Generation"](https://huggingface.co/papers/2306.05284) Disclaimer: This won't run on CPU only. Clone this App and run on GPU instance! Todo: Working on improved Interrupt. Theme Available at ["Surn/Beeuty"](https://huggingface.co/spaces/Surn/Beeuty) """ ) with gr.Row(): with gr.Column(): with gr.Row(): with gr.Column(): text = gr.Text(label="Describe your music", interactive=True, value="4/4 100bpm 32khz, Industrial/Electronic Soundtrack, Dark, Intense, soft fade-in, soft fade-out", key="prompt", lines=4) autoplay_cb = gr.Checkbox(value=False, label="Autoplay?", key="autoplay_cb") with gr.Column(): duration = gr.Slider(minimum=1, maximum=720, value=10, label="Duration (s)", interactive=True, key="total_duration", step=1) model = gr.Radio(["melody", "medium", "small", "large", "melody-large", "stereo-small", "stereo-medium", "stereo-large", "stereo-melody", "stereo-melody-large", "style"], label="AI Model", value="style", interactive=True, key="chosen_model") with gr.Row(): submit = gr.Button("Generate", elem_id="btn-generate") # Adapted from https://github.com/rkfg/audiocraft/blob/long/app.py, MIT license. _ = gr.Button("Interrupt", elem_id="btn-interrupt").click(fn=interrupt, queue=False) with gr.Row(): with gr.Column(): radio = gr.Radio(["file", "mic"], value="file", label="Condition on a melody (optional) File or Mic") melody_filepath = gr.Audio(sources=["upload"], type="filepath", label="Melody Condition (optional)", interactive=True, elem_id="melody-input", key="melody_input") with gr.Column(): harmony_only = gr.Radio(label="Use Harmony Only",choices=["No", "Yes"], value="No", interactive=True, info="Remove Drums?", key="use_harmony") prompt_index = gr.Slider(label="Melody Condition Sample Segment", minimum=-1, maximum=MAX_PROMPT_INDEX, step=1, value=-1, interactive=True, info="Which 10-30 second segment to condition with, - 1 = align with conditioning melody", key="melody_index") with gr.Accordion("Video", open=False): with gr.Row(): background= gr.Image(value="./assets/background.png", sources=["upload"], label="Background", width=768, height=512, type="filepath", interactive=True, key="background_imagepath") with gr.Column(): include_title = gr.Checkbox(label="Add Title", value=True, interactive=True,key="add_title") include_settings = gr.Checkbox(label="Add Settings to background", value=True, interactive=True, key="add_settings") video_orientation = gr.Radio(label="Video Orientation", choices=["Landscape", "Portrait"], value="Landscape", interactive=True, key="video_orientation") with gr.Row(): title = gr.Textbox(label="Title", value="UnlimitedMusicGen", interactive=True, key="song_title") settings_font = gr.Text(label="Settings Font", value="./assets/arial.ttf", interactive=True) settings_font_color = gr.ColorPicker(label="Settings Font Color", value="#c87f05", interactive=True, key="settings_font_color") settings_font_size = gr.Slider(minimum=8, maximum=64, value=28, step=1, label="Settings Font Size", interactive=True, key="settings_font_size") settings_animate_waveform = gr.Checkbox(label="Animate Waveform", value=False, interactive=True, key="animate_waveform") with gr.Accordion("Expert", open=False): with gr.Row(): segment_length = gr.Slider(minimum=10, maximum=30, value=30, step=1,label="Music Generation Segment Length (s)", interactive=True,key="segment_length") overlap = gr.Slider(minimum=0, maximum=14, value=1, step=1, label="Segment Overlap", interactive=True) dimension = gr.Slider(minimum=-2, maximum=2, value=2, step=1, label="Dimension", info="determines which direction to add new segements of audio. (1 = stack tracks, 2 = lengthen, -2..0 = ?)", interactive=True) with gr.Row(): topk = gr.Number(label="Top-k", value=280, precision=0, interactive=True, info="more structured", key="topk") topp = gr.Number(label="Top-p", value=1150, precision=0, interactive=True, info="more variation, overwrites Top-k if not zero", key="topp") temperature = gr.Number(label="Randomness Temperature", value=0.7, precision=None, step=0.1, interactive=True, info="less than one to follow Melody Condition song closely", key="temperature") cfg_coef = gr.Number(label="Classifier Free Guidance", value=3.75, precision=None, step=0.1, interactive=True, info="3.0-4.0, stereo and small need more", key="cfg_coef") with gr.Row(): seed = gr.Number(label="Seed", value=-1, precision=0, interactive=True, key="seed") gr.Button('\U0001f3b2\ufe0f', elem_classes="small-btn").click(fn=lambda: -1, outputs=[seed], queue=False) reuse_seed = gr.Button('\u267b\ufe0f', elem_classes="small-btn") with gr.Column() as c: output = gr.Video(label="Generated Music", interactive=False, show_download_button=True, show_share_button=True, autoplay=False) wave_file = gr.File(label=".wav file", elem_id="output_wavefile", interactive=True) seed_used = gr.Number(label='Seed used', value=-1, interactive=False) radio.change(toggle_audio_src, radio, [melody_filepath], queue=False, show_progress=False, api_name="audio_src_change") video_orientation.change(load_background_filepath, inputs=[video_orientation], outputs=[background], queue=False, show_progress=False, api_name="video_orientation_change") melody_filepath.change(load_melody_filepath, inputs=[melody_filepath, title, model,topp, temperature, cfg_coef, segment_length], outputs=[title, prompt_index , model, topp, temperature, cfg_coef, overlap], api_name="melody_filepath_change", queue=False) reuse_seed.click(fn=lambda x: x, inputs=[seed_used], outputs=[seed], queue=False, api_name="reuse_seed_click") autoplay_cb.change(fn=lambda x: gr.update(autoplay=x), inputs=[autoplay_cb], outputs=[output], queue=False, api_name="autoplay_cb_change") segment_length.release(fn=load_melody_filepath, queue=False, api_name="segment_length_change", trigger_mode="once", inputs=[melody_filepath, title, model,topp, temperature, cfg_coef, segment_length], outputs=[title, prompt_index , model, topp, temperature, cfg_coef, overlap], show_progress="minimal") gr.Examples( examples=[ [ "4/4 120bpm 320kbps 32khz, An 80s driving pop song with heavy drums and synth pads in the background", "./assets/bach.mp3", "melody", "80s Pop Synth", 950, 0.6, 3.5 ], [ "4/4 120bpm 320kbps 32khz, A cheerful country song with acoustic guitars", "./assets/bolero_ravel.mp3", "stereo-melody-large", "Country Guitar", 750, 0.7, 4.0 ], [ "4/4 120bpm 320kbps 32khz, 90s rock song with electric guitar and heavy drums", None, "stereo-medium", "90s Rock Guitar", 1150, 0.7, 3.75 ], [ "4/4 120bpm 320kbps 32khz, a light and cheery EDM track, with syncopated drums, aery pads, and strong emotions", "./assets/bach.mp3", "melody-large", "EDM my Bach", 500, 0.7, 3.75 ], [ "4/4 320kbps 32khz, lofi slow bpm electro chill with organic samples", None, "medium", "LoFi Chill", 0, 0.7, 4.0 ], ], inputs=[text, melody_filepath, model, title, topp, temperature, cfg_coef], outputs=[output] ) with gr.Tab("User History") as history_tab: modules.user_history.setup(display_type="video_path") modules.user_history.render() user_profile = gr.State(None) with gr.Row("Versions") as versions_row: gr.HTML(value=versions_html(), visible=True, elem_id="versions") submit.click( modules.user_history.get_profile, inputs=[], outputs=[user_profile], queue=True, api_name="submit" ).then( predict, inputs=[model, text, melody_filepath, duration, dimension, topk, topp, temperature, cfg_coef, background, title, settings_font, settings_font_color, seed, overlap, prompt_index, include_title, include_settings, harmony_only, user_profile, segment_length, settings_font_size, settings_animate_waveform, video_orientation], outputs=[output, wave_file, seed_used], scroll_to_output=True) # Show the interface launch_kwargs = {} share = kwargs.get('share', False) server_port = kwargs.get('server_port', 0) server_name = kwargs.get('listen') launch_kwargs['server_name'] = server_name if server_port > 0: launch_kwargs['server_port'] = server_port if share: launch_kwargs['share'] = share launch_kwargs['allowed_paths'] = ["assets", "./assets", "images", "./images", 'e:/TMP'] launch_kwargs['favicon_path'] = "./assets/favicon.ico" launch_kwargs['mcp_server'] = False demo.queue(max_size=10, api_open=True).launch(**launch_kwargs) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument( '--listen', type=str, default='0.0.0.0' if 'SPACE_ID' in os.environ else '127.0.0.1', help='IP to listen on for connections to Gradio', ) parser.add_argument( '--username', type=str, default='', help='Username for authentication' ) parser.add_argument( '--password', type=str, default='', help='Password for authentication' ) parser.add_argument( '--server_port', type=int, default=0, help='Port to run the server listener on', ) parser.add_argument( '--inbrowser', action='store_true', help='Open in browser' ) parser.add_argument( '--share', action='store_true', help='Share the gradio UI' ) parser.add_argument( '--unload_model', action='store_true', help='Unload the model after every generation to save GPU memory' ) parser.add_argument( '--unload_to_cpu', action='store_true', help='Move the model to main RAM after every generation to save GPU memory but reload faster than after full unload (see above)' ) parser.add_argument( '--cache', action='store_true', help='Cache models in RAM to quickly switch between them' ) args = parser.parse_args() launch_kwargs = {} launch_kwargs['listen'] = args.listen if args.username and args.password: launch_kwargs['auth'] = (args.username, args.password) if args.server_port: launch_kwargs['server_port'] = args.server_port if args.inbrowser: launch_kwargs['inbrowser'] = args.inbrowser if args.share: launch_kwargs['share'] = args.share launch_kwargs['favicon_path']= "./assets/favicon.ico" UNLOAD_MODEL = args.unload_model MOVE_TO_CPU = args.unload_to_cpu if args.cache: MODELS = {} ui( unload_to_cpu = MOVE_TO_CPU, share=args.share, **launch_kwargs, )