CoolFace
Apppublic

ZeroTwo3/videoshop-backend

sourceHugging Faceopenrailupdated 3y agoView on Hugging Face
2likes
app.py423 linesDownload Raw Back to root
1import argparse2from concurrent.futures import ProcessPoolExecutor3import os4from pathlib import Path5import subprocess as sp6from tempfile import NamedTemporaryFile7import time8import typing as tp9import warnings10 11import torch12import gradio as gr13 14from audiocraft.data.audio_utils import convert_audio15from audiocraft.data.audio import audio_write16from audiocraft.models import MusicGen, MultiBandDiffusion17 18 19MODEL = None  # Last used model20IS_BATCHED = "facebook/MusicGen" in os.environ.get('SPACE_ID', '')21print(IS_BATCHED)22MAX_BATCH_SIZE = 1223BATCHED_DURATION = 1524INTERRUPTING = False25MBD = None26# We have to wrap subprocess call to clean a bit the log when using gr.make_waveform27_old_call = sp.call28 29 30def _call_nostderr(*args, **kwargs):31    # Avoid ffmpeg vomiting on the logs.32    kwargs['stderr'] = sp.DEVNULL33    kwargs['stdout'] = sp.DEVNULL34    _old_call(*args, **kwargs)35 36 37sp.call = _call_nostderr38# Preallocating the pool of processes.39pool = ProcessPoolExecutor(4)40pool.__enter__()41 42 43def interrupt():44    global INTERRUPTING45    INTERRUPTING = True46 47 48class FileCleaner:49    def __init__(self, file_lifetime: float = 3600):50        self.file_lifetime = file_lifetime51        self.files = []52 53    def add(self, path: tp.Union[str, Path]):54        self._cleanup()55        self.files.append((time.time(), Path(path)))56 57    def _cleanup(self):58        now = time.time()59        for time_added, path in list(self.files):60            if now - time_added > self.file_lifetime:61                if path.exists():62                    path.unlink()63                self.files.pop(0)64            else:65                break66 67 68file_cleaner = FileCleaner()69 70 71def make_waveform(*args, **kwargs):72    # Further remove some warnings.73    be = time.time()74    with warnings.catch_warnings():75        warnings.simplefilter('ignore')76        out = gr.make_waveform(*args, **kwargs)77        print("Make a video took", time.time() - be)78        return out79 80 81def load_model(version='facebook/musicgen-melody'):82    global MODEL83    print("Loading model", version)84    if MODEL is None or MODEL.name != version:85        MODEL = MusicGen.get_pretrained(version)86 87 88def load_diffusion():89    global MBD90    if MBD is None:91        print("loading MBD")92        MBD = MultiBandDiffusion.get_mbd_musicgen()93 94 95def _do_predictions(texts, melodies, duration, progress=False, **gen_kwargs):96    MODEL.set_generation_params(duration=duration, **gen_kwargs)97    print("new batch", len(texts), texts, [None if m is None else (m[0], m[1].shape) for m in melodies])98    be = time.time()99    processed_melodies = []100    target_sr = 32000101    target_ac = 1102    for melody in melodies:103        if melody is None:104            processed_melodies.append(None)105        else:106            sr, melody = melody[0], torch.from_numpy(melody[1]).to(MODEL.device).float().t()107            if melody.dim() == 1:108                melody = melody[None]109            melody = melody[..., :int(sr * duration)]110            melody = convert_audio(melody, sr, target_sr, target_ac)111            processed_melodies.append(melody)112 113    if any(m is not None for m in processed_melodies):114        outputs = MODEL.generate_with_chroma(115            descriptions=texts,116            melody_wavs=processed_melodies,117            melody_sample_rate=target_sr,118            progress=progress,119            return_tokens=USE_DIFFUSION120        )121    else:122        outputs = MODEL.generate(texts, progress=progress, return_tokens=USE_DIFFUSION)123    if USE_DIFFUSION:124        outputs_diffusion = MBD.tokens_to_wav(outputs[1])125        outputs = torch.cat([outputs[0], outputs_diffusion], dim=0)126    outputs = outputs.detach().cpu().float()127    pending_videos = []128    out_wavs = []129    for output in outputs:130        with NamedTemporaryFile("wb", suffix=".wav", delete=False) as file:131            audio_write(132                file.name, output, MODEL.sample_rate, strategy="loudness",133                loudness_headroom_db=16, loudness_compressor=True, add_suffix=False)134            pending_videos.append(pool.submit(make_waveform, file.name))135            out_wavs.append(file.name)136            file_cleaner.add(file.name)137    out_videos = [pending_video.result() for pending_video in pending_videos]138    for video in out_videos:139        file_cleaner.add(video)140    print("batch finished", len(texts), time.time() - be)141    print("Tempfiles currently stored: ", len(file_cleaner.files))142    return out_videos, out_wavs143 144 145def predict_batched(texts, melodies):146    max_text_length = 512147    texts = [text[:max_text_length] for text in texts]148    load_model('facebook/musicgen-melody')149    res = _do_predictions(texts, melodies, BATCHED_DURATION)150    return res151 152 153def predict_full(model, decoder, text, melody, duration, topk, topp, temperature, cfg_coef, progress=gr.Progress()):154    global INTERRUPTING155    global USE_DIFFUSION156    INTERRUPTING = False157    if temperature < 0:158        raise gr.Error("Temperature must be >= 0.")159    if topk < 0:160        raise gr.Error("Topk must be non-negative.")161    if topp < 0:162        raise gr.Error("Topp must be non-negative.")163 164    topk = int(topk)165    if decoder == "MultiBand_Diffusion":166        USE_DIFFUSION = True167        load_diffusion()168    else:169        USE_DIFFUSION = False170    load_model(model)171 172    def _progress(generated, to_generate):173        progress((min(generated, to_generate), to_generate))174        if INTERRUPTING:175            raise gr.Error("Interrupted.")176    MODEL.set_custom_progress_callback(_progress)177 178    videos, wavs = _do_predictions(179        [text], [melody], duration, progress=True,180        top_k=topk, top_p=topp, temperature=temperature, cfg_coef=cfg_coef)181    if USE_DIFFUSION:182        return videos[0], wavs[0], videos[1], wavs[1]183    return videos[0], wavs[0], None, None184 185 186def toggle_audio_src(choice):187    if choice == "mic":188        return gr.update(source="microphone", value=None, label="Microphone")189    else:190        return gr.update(source="upload", value=None, label="File")191 192 193def toggle_diffusion(choice):194    if choice == "MultiBand_Diffusion":195        return [gr.update(visible=True)] * 2196    else:197        return [gr.update(visible=False)] * 2198 199 200def ui_full(launch_kwargs):201    with gr.Blocks() as interface:202        203        with gr.Row():204            with gr.Column():205                with gr.Row():206                    text = gr.Text(label="Input Text", interactive=True)207                    # with gr.Column():208                        # radio = gr.Radio(["file", "mic"], value="file",209                        #                  label="Condition on a melody (optional) File or Mic")210                        # melody = gr.Audio(source="upload", type="numpy", label="File",211                        #                   interactive=True, elem_id="melody-input")212                with gr.Row():213                    submit = gr.Button("Submit")214                    # Adapted from https://github.com/rkfg/audiocraft/blob/long/app.py, MIT license.215                    _ = gr.Button("Interrupt").click(fn=interrupt, queue=False)216                with gr.Row():217                    model = gr.Radio(["facebook/musicgen-melody", "facebook/musicgen-medium", "facebook/musicgen-small",218                                      "facebook/musicgen-large"],219                                     label="Model", value="facebook/musicgen-melody", interactive=True)220                # with gr.Row():221                #     decoder = gr.Radio(["Default", "MultiBand_Diffusion"],222                #                        label="Decoder", value="Default", interactive=True)223                # decoder = "Default"224                with gr.Row():225                    duration = gr.Slider(minimum=1, maximum=120, value=10, label="Duration", interactive=True)226                # with gr.Row():227                #     topk = gr.Number(label="Top-k", value=250, interactive=True)228                #     topp = gr.Number(label="Top-p", value=0, interactive=True)229                #     temperature = gr.Number(label="Temperature", value=1.0, interactive=True)230                #     cfg_coef = gr.Number(label="Classifier Free Guidance", value=3.0, interactive=True)231                232            with gr.Column():233                output = gr.Video(label="Generated Music")234                audio_output = gr.Audio(label="Generated Music (wav)", type='filepath')235                # diffusion_output = gr.Video(label="MultiBand Diffusion Decoder")236                # audio_diffusion = gr.Audio(label="MultiBand Diffusion Decoder (wav)", type='filepath')237 238        melody = gr.Audio(source= None, type="numpy", label="File",239                                    interactive=False, visible= False, elem_id="melody-input")240        decoder = gr.Radio(["Default", "MultiBand_Diffusion"],241                                       label="Decoder", value="Default", interactive=True, visible= False)242        # duration = gr.Slider(minimum=1, maximum=120, value=10, label="Duration", interactive=True, visible= False)243        topk = gr.Number(label="Top-k", value=250, interactive=True, visible= False)244        topp = gr.Number(label="Top-p", value=0, interactive=True, visible= False)245        temperature = gr.Number(label="Temperature", value=1.0, interactive=True, visible= False)246        cfg_coef = gr.Number(label="Classifier Free Guidance", value=3.0, interactive=True, visible= False)247        diffusion_output = gr.Video(label="MultiBand Diffusion Decoder" , visible=False)248        audio_diffusion = gr.Audio(label="MultiBand Diffusion Decoder (wav)", type='filepath', visible= False)249        250        print("melody", melody)251        print("decoder", decoder)252        print("topk", topk)253        print("topp", topp)254        print("cfg_coef", cfg_coef)255        print("diffusion_output" , diffusion_output)256        print("audio_diffusion" , audio_diffusion)257        258        submit.click(toggle_diffusion, decoder, [diffusion_output, audio_diffusion], queue=False,259                     show_progress=False).then(predict_full, inputs=[model, decoder, text, melody, duration, topk, topp,260                                                                     temperature, cfg_coef],261                                               outputs=[output, audio_output, diffusion_output, audio_diffusion])262        # radio.change(toggle_audio_src, radio, [melody], queue=False, show_progress=False)263        264        # gr.Examples(265        #     fn=predict_full,266        #     examples=[267        #         [268        #             "An 80s driving pop song with heavy drums and synth pads in the background",269        #             "./assets/bach.mp3",270        #             "facebook/musicgen-melody",271        #             "Default"272        #         ],273        #         [274        #             "A cheerful country song with acoustic guitars",275        #             "./assets/bolero_ravel.mp3",276        #             "facebook/musicgen-melody",277        #             "Default"278        #         ],279        #         [280        #             "90s rock song with electric guitar and heavy drums",281        #             None,282        #             "facebook/musicgen-medium",283        #             "Default"284        #         ],285        #         [286        #             "a light and cheerly EDM track, with syncopated drums, aery pads, and strong emotions",287        #             "./assets/bach.mp3",288        #             "facebook/musicgen-melody",289        #             "Default"290        #         ],291        #         [292        #             "lofi slow bpm electro chill with organic samples",293        #             None,294        #             "facebook/musicgen-medium",295        #             "Default"296        #         ],297        #         [298        #             "Punk rock with loud drum and power guitar",299        #             None,300        #             "facebook/musicgen-medium",301        #             "MultiBand_Diffusion"302        #         ],303        #     ],304        #     inputs=[text, melody, model, decoder],305        #     outputs=[output]306        # )307        gr.Markdown(308            """309            """310        )311 312        interface.queue().launch(**launch_kwargs)313 314def ui_batched(launch_kwargs):315    with gr.Blocks() as demo:316        gr.Markdown(317            """318            This project generate Music from prompt.319            """320        )321        with gr.Row():322            with gr.Column():323                with gr.Row():324                    text = gr.Text(label="Describe your music", lines=2, interactive=True)325                    with gr.Column():326                        radio = gr.Radio(["file", "mic"], value="file",327                                         label="Condition on a melody (optional) File or Mic")328                        melody = gr.Audio(source="upload", type="numpy", label="File",329                                          interactive=True, elem_id="melody-input")330                with gr.Row():331                    submit = gr.Button("Generate")332            with gr.Column():333                output = gr.Video(label="Generated Music")334                audio_output = gr.Audio(label="Generated Music (wav)", type='filepath')335        submit.click(predict_batched, inputs=[text, melody],336                     outputs=[output, audio_output], batch=True, max_batch_size=MAX_BATCH_SIZE)337        radio.change(toggle_audio_src, radio, [melody], queue=False, show_progress=False)338        gr.Examples(339            fn=predict_batched,340            # examples=[341            #     [342            #         "An 80s driving pop song with heavy drums and synth pads in the background",343            #         "./assets/bach.mp3",344            #     ],345            #     [346            #         "A cheerful country song with acoustic guitars",347            #         "./assets/bolero_ravel.mp3",348            #     ],349            #     [350            #         "90s rock song with electric guitar and heavy drums",351            #         None,352            #     ],353            #     [354            #         "a light and cheerly EDM track, with syncopated drums, aery pads, and strong emotions bpm: 130",355            #         "./assets/bach.mp3",356            #     ],357            #     [358            #         "lofi slow bpm electro chill with organic samples",359            #         None,360            #     ],361            # ],362            examples=[363 364            ],365            inputs=[text, melody],366            outputs=[output]367        )368        gr.Markdown("""369                370        """)371 372        demo.queue(max_size=8 * 4).launch(**launch_kwargs)373 374 375if __name__ == "__main__":376    parser = argparse.ArgumentParser()377    parser.add_argument(378        '--listen',379        type=str,380        default='0.0.0.0' if 'SPACE_ID' in os.environ else '127.0.0.1',381        help='IP to listen on for connections to Gradio',382    )383    parser.add_argument(384        '--username', type=str, default='', help='Username for authentication'385    )386    parser.add_argument(387        '--password', type=str, default='', help='Password for authentication'388    )389    parser.add_argument(390        '--server_port',391        type=int,392        default=0,393        help='Port to run the server listener on',394    )395    parser.add_argument(396        '--inbrowser', action='store_true', help='Open in browser'397    )398    parser.add_argument(399        '--share', action='store_true', help='Share the gradio UI'400    )401 402    args = parser.parse_args()403 404    launch_kwargs = {}405    launch_kwargs['server_name'] = args.listen406 407    if args.username and args.password:408        launch_kwargs['auth'] = (args.username, args.password)409    if args.server_port:410        launch_kwargs['server_port'] = args.server_port411    if args.inbrowser:412        launch_kwargs['inbrowser'] = args.inbrowser413    if args.share:414        launch_kwargs['share'] = args.share415 416    # Show the interface417    if IS_BATCHED:418        global USE_DIFFUSION419        USE_DIFFUSION = False420        ui_batched(launch_kwargs)421    else:422        ui_full(launch_kwargs)423