CoolFace
Apppublic

raaraya/AnimateDiff

sourceHugging Faceapache-2.0updated 3y agoView on Hugging Face
0likes
app.py634 linesDownload Raw Back to root
1 2 3# import os4# import json5# import torch6# import random7# import copy8 9# import gradio as gr10# from glob import glob11# from omegaconf import OmegaConf12# from datetime import datetime13# from safetensors import safe_open14 15# from diffusers import AutoencoderKL16# from diffusers import DDIMScheduler, EulerDiscreteScheduler, PNDMScheduler17# from diffusers.utils.import_utils import is_xformers_available18# from transformers import CLIPTextModel, CLIPTokenizer19 20# from animatediff.models.unet import UNet3DConditionModel21# from animatediff.pipelines.pipeline_animation import AnimationPipeline22# from animatediff.utils.util import save_videos_grid23# from animatediff.utils.convert_from_ckpt import convert_ldm_unet_checkpoint, convert_ldm_clip_checkpoint, convert_ldm_vae_checkpoint24# from animatediff.utils.convert_lora_safetensor_to_diffusers import convert_lora25 26 27# sample_idx     = 028# scheduler_dict = {29#     "Euler": EulerDiscreteScheduler,30#     "PNDM": PNDMScheduler,31#     "DDIM": DDIMScheduler,32# }33 34# css = """35# .toolbutton {36#     margin-buttom: 0em 0em 0em 0em;37#     max-width: 2.5em;38#     min-width: 2.5em !important;39#     height: 2.5em;40# }41# """42 43# class AnimateController:44#     def __init__(self):45        46#         # config dirs47#         self.basedir                = os.getcwd()48#         self.stable_diffusion_dir   = os.path.join(self.basedir, "models", "StableDiffusion")49#         self.motion_module_dir      = os.path.join(self.basedir, "models", "Motion_Module")50#         self.personalized_model_dir = os.path.join(self.basedir, "models", "DreamBooth_LoRA")51#         self.savedir                = os.path.join(self.basedir, "samples", datetime.now().strftime("Gradio-%Y-%m-%dT%H-%M-%S"))52#         self.savedir_sample         = os.path.join(self.savedir, "sample")53#         os.makedirs(self.savedir, exist_ok=True)54 55#         self.stable_diffusion_list   = []56#         self.motion_module_list      = []57#         self.personalized_model_list = []58        59#         self.refresh_stable_diffusion()60#         self.refresh_motion_module()61#         self.refresh_personalized_model()62        63#         # config models64#         self.tokenizer             = None65#         self.text_encoder          = None66#         self.vae                   = None67#         self.unet                  = None68#         self.pipeline              = None69#         self.lora_model_state_dict = {}70        71#         self.inference_config      = OmegaConf.load("configs/inference/inference.yaml")72 73#     def refresh_stable_diffusion(self):74#         self.stable_diffusion_list = glob(os.path.join(self.stable_diffusion_dir, "*/"))75 76#     def refresh_motion_module(self):77#         motion_module_list = glob(os.path.join(self.motion_module_dir, "*.ckpt"))78#         self.motion_module_list = [os.path.basename(p) for p in motion_module_list]79 80#     def refresh_personalized_model(self):81#         personalized_model_list = glob(os.path.join(self.personalized_model_dir, "*.safetensors"))82#         self.personalized_model_list = [os.path.basename(p) for p in personalized_model_list]83 84#     def update_stable_diffusion(self, stable_diffusion_dropdown):85#         self.tokenizer = CLIPTokenizer.from_pretrained(stable_diffusion_dropdown, subfolder="tokenizer")86#         self.text_encoder = CLIPTextModel.from_pretrained(stable_diffusion_dropdown, subfolder="text_encoder").cuda()87#         self.vae = AutoencoderKL.from_pretrained(stable_diffusion_dropdown, subfolder="vae").cuda()88#         self.unet = UNet3DConditionModel.from_pretrained_2d(stable_diffusion_dropdown, subfolder="unet", unet_additional_kwargs=OmegaConf.to_container(self.inference_config.unet_additional_kwargs)).cuda()89#         return gr.Dropdown.update()90 91#     def update_motion_module(self, motion_module_dropdown):92#         if self.unet is None:93#             gr.Info(f"Please select a pretrained model path.")94#             return gr.Dropdown.update(value=None)95#         else:96#             motion_module_dropdown = os.path.join(self.motion_module_dir, motion_module_dropdown)97#             motion_module_state_dict = torch.load(motion_module_dropdown, map_location="cpu")98#             missing, unexpected = self.unet.load_state_dict(motion_module_state_dict, strict=False)99#             assert len(unexpected) == 0100#             return gr.Dropdown.update()101 102#     def update_base_model(self, base_model_dropdown):103#         if self.unet is None:104#             gr.Info(f"Please select a pretrained model path.")105#             return gr.Dropdown.update(value=None)106#         else:107#             base_model_dropdown = os.path.join(self.personalized_model_dir, base_model_dropdown)108#             base_model_state_dict = {}109#             with safe_open(base_model_dropdown, framework="pt", device="cpu") as f:110#                 for key in f.keys():111#                     base_model_state_dict[key] = f.get_tensor(key)112                    113#             converted_vae_checkpoint = convert_ldm_vae_checkpoint(base_model_state_dict, self.vae.config)114#             self.vae.load_state_dict(converted_vae_checkpoint)115 116#             converted_unet_checkpoint = convert_ldm_unet_checkpoint(base_model_state_dict, self.unet.config)117#             self.unet.load_state_dict(converted_unet_checkpoint, strict=False)118 119#             self.text_encoder = convert_ldm_clip_checkpoint(base_model_state_dict)120#             return gr.Dropdown.update()121 122#     def update_lora_model(self, lora_model_dropdown):123#         lora_model_dropdown = os.path.join(self.personalized_model_dir, lora_model_dropdown)124#         self.lora_model_state_dict = {}125#         if lora_model_dropdown == "none": pass126#         else:127#             with safe_open(lora_model_dropdown, framework="pt", device="cpu") as f:128#                 for key in f.keys():129#                     self.lora_model_state_dict[key] = f.get_tensor(key)130#         return gr.Dropdown.update()131 132#     def animate(133#         self,134#         stable_diffusion_dropdown,135#         motion_module_dropdown,136#         base_model_dropdown,137#         lora_alpha_slider,138#         prompt_textbox, 139#         negative_prompt_textbox, 140#         sampler_dropdown, 141#         sample_step_slider, 142#         width_slider, 143#         length_slider, 144#         height_slider, 145#         cfg_scale_slider, 146#         seed_textbox147#     ):    148#         if self.unet is None:149#             raise gr.Error(f"Please select a pretrained model path.")150#         if motion_module_dropdown == "": 151#             raise gr.Error(f"Please select a motion module.")152#         # if base_model_dropdown == "":153#         #     raise gr.Error(f"Please select a base DreamBooth model.")154 155#         if is_xformers_available(): self.unet.enable_xformers_memory_efficient_attention()156 157#         pipeline = AnimationPipeline(158#             vae=self.vae, text_encoder=self.text_encoder, tokenizer=self.tokenizer, unet=self.unet,159#             scheduler=scheduler_dict[sampler_dropdown](**OmegaConf.to_container(self.inference_config.noise_scheduler_kwargs))160#         ).to("cuda")161        162#         if self.lora_model_state_dict != {}:163#             print(f"Lora alpha: {lora_alpha_slider}")164#             pipeline = convert_lora(copy.deepcopy(pipeline), self.lora_model_state_dict, alpha=lora_alpha_slider)165#         pipeline.to("cuda")166 167#         torch.cuda.empty_cache()168        169#         seed_textbox = int(seed_textbox)170#         if seed_textbox != -1 and seed_textbox != "": torch.manual_seed(seed_textbox)171#         else: torch.seed()172#         seed = torch.initial_seed()173        174#         sample = pipeline(175#             prompt_textbox,176#             negative_prompt     = negative_prompt_textbox,177#             num_inference_steps = sample_step_slider,178#             guidance_scale      = cfg_scale_slider,179#             width               = width_slider,180#             height              = height_slider,181#             video_length        = length_slider,182#         ).videos183 184#         save_sample_path = os.path.join(self.savedir_sample, f"{sample_idx}.mp4")185#         save_videos_grid(sample, save_sample_path)186    187#         sample_config = {188#             "prompt": prompt_textbox,189#             "n_prompt": negative_prompt_textbox,190#             "sampler": sampler_dropdown,191#             "num_inference_steps": sample_step_slider,192#             "guidance_scale": cfg_scale_slider,193#             "width": width_slider,194#             "height": height_slider,195#             "video_length": length_slider,196#             "seed": seed197#         }198#         json_str = json.dumps(sample_config, indent=4)199#         with open(os.path.join(self.savedir, "logs.json"), "a") as f:200#             f.write(json_str)201#             f.write("\n\n")202 203#         del pipeline204#         torch.cuda.empty_cache()205 206#         return gr.Video.update(value=save_sample_path)207        208 209# controller = AnimateController()210 211 212# def ui():213#     with gr.Blocks(css=css) as demo:214#         gr.Markdown(215#             """216#             # [AnimateDiff: Animate Your Personalized Text-to-Image Diffusion Models without Specific Tuning](https://arxiv.org/abs/2307.04725)217#             Yuwei Guo, Ceyuan Yang*, Anyi Rao, Yaohui Wang, Yu Qiao, Dahua Lin, Bo Dai (*Corresponding Author)<br>218#             [Arxiv Report](https://arxiv.org/abs/2307.04725) | [Project Page](https://animatediff.github.io/) | [Github](https://github.com/guoyww/animatediff/)219#             """220#         )221#         with gr.Column(variant="panel"):222#             gr.Markdown(223#                 """224#                 ### 1. Model checkpoints (select pretrained model path first).225#                 """226#             )227#             with gr.Row():228#                 stable_diffusion_dropdown = gr.Dropdown(229#                     label="Pretrained Model Path",230#                     choices=controller.stable_diffusion_list,231#                     interactive=True,232#                 )233#                 stable_diffusion_dropdown.change(fn=controller.update_stable_diffusion, inputs=[stable_diffusion_dropdown], outputs=[stable_diffusion_dropdown])234                235#                 stable_diffusion_refresh_button = gr.Button(value="\U0001F503", elem_classes="toolbutton")236#                 def update_stable_diffusion():237#                     controller.refresh_stable_diffusion()238#                     return gr.Dropdown.update(choices=controller.stable_diffusion_list)239#                 stable_diffusion_refresh_button.click(fn=update_stable_diffusion, inputs=[], outputs=[stable_diffusion_dropdown])240 241#             with gr.Row():242#                 motion_module_dropdown = gr.Dropdown(243#                     label="Select motion module",244#                     choices=controller.motion_module_list,245#                     interactive=True,246#                 )247#                 motion_module_dropdown.change(fn=controller.update_motion_module, inputs=[motion_module_dropdown], outputs=[motion_module_dropdown])248                249#                 motion_module_refresh_button = gr.Button(value="\U0001F503", elem_classes="toolbutton")250#                 def update_motion_module():251#                     controller.refresh_motion_module()252#                     return gr.Dropdown.update(choices=controller.motion_module_list)253#                 motion_module_refresh_button.click(fn=update_motion_module, inputs=[], outputs=[motion_module_dropdown])254                255#                 base_model_dropdown = gr.Dropdown(256#                     label="Select base Dreambooth model (required)",257#                     choices=controller.personalized_model_list,258#                     interactive=True,259#                 )260#                 base_model_dropdown.change(fn=controller.update_base_model, inputs=[base_model_dropdown], outputs=[base_model_dropdown])261                262#                 lora_model_dropdown = gr.Dropdown(263#                     label="Select LoRA model (optional)",264#                     choices=["none"] + controller.personalized_model_list,265#                     value="none",266#                     interactive=True,267#                 )268#                 lora_model_dropdown.change(fn=controller.update_lora_model, inputs=[lora_model_dropdown], outputs=[lora_model_dropdown])269                270#                 lora_alpha_slider = gr.Slider(label="LoRA alpha", value=0.7, minimum=0, maximum=2, interactive=True)271                272#                 personalized_refresh_button = gr.Button(value="\U0001F503", elem_classes="toolbutton")273#                 def update_personalized_model():274#                     controller.refresh_personalized_model()275#                     return [276#                         gr.Dropdown.update(choices=controller.personalized_model_list),277#                         gr.Dropdown.update(choices=["none"] + controller.personalized_model_list)278#                     ]279#                 personalized_refresh_button.click(fn=update_personalized_model, inputs=[], outputs=[base_model_dropdown, lora_model_dropdown])280 281#         with gr.Column(variant="panel"):282#             gr.Markdown(283#                 """284#                 ### 2. Configs for AnimateDiff.285#                 """286#             )287            288#             prompt_textbox = gr.Textbox(label="Prompt", lines=2)289#             negative_prompt_textbox = gr.Textbox(label="Negative prompt", lines=2)290                291#             with gr.Row().style(equal_height=False):292#                 with gr.Column():293#                     with gr.Row():294#                         sampler_dropdown   = gr.Dropdown(label="Sampling method", choices=list(scheduler_dict.keys()), value=list(scheduler_dict.keys())[0])295#                         sample_step_slider = gr.Slider(label="Sampling steps", value=25, minimum=10, maximum=100, step=1)296                        297#                     width_slider     = gr.Slider(label="Width",            value=512, minimum=256, maximum=1024, step=64)298#                     height_slider    = gr.Slider(label="Height",           value=512, minimum=256, maximum=1024, step=64)299#                     length_slider    = gr.Slider(label="Animation length", value=16,  minimum=8,   maximum=24,   step=1)300#                     cfg_scale_slider = gr.Slider(label="CFG Scale",        value=7.5, minimum=0,   maximum=20)301                    302#                     with gr.Row():303#                         seed_textbox = gr.Textbox(label="Seed", value=-1)304#                         seed_button  = gr.Button(value="\U0001F3B2", elem_classes="toolbutton")305#                         seed_button.click(fn=lambda: gr.Textbox.update(value=random.randint(1, 1e8)), inputs=[], outputs=[seed_textbox])306            307#                     generate_button = gr.Button(value="Generate", variant='primary')308                    309#                 result_video = gr.Video(label="Generated Animation", interactive=False)310 311#             generate_button.click(312#                 fn=controller.animate,313#                 inputs=[314#                     stable_diffusion_dropdown,315#                     motion_module_dropdown,316#                     base_model_dropdown,317#                     lora_alpha_slider,318#                     prompt_textbox, 319#                     negative_prompt_textbox, 320#                     sampler_dropdown, 321#                     sample_step_slider, 322#                     width_slider, 323#                     length_slider, 324#                     height_slider, 325#                     cfg_scale_slider, 326#                     seed_textbox,327#                 ],328#                 outputs=[result_video]329#             )330            331#     return demo332 333 334# if __name__ == "__main__":335#     demo = ui()336#     demo.queue(max_size=20)337#     demo.launch()338 339 340import os341import torch342import random343 344import gradio as gr345from glob import glob346from omegaconf import OmegaConf347from safetensors import safe_open348 349from diffusers import AutoencoderKL350from diffusers import EulerDiscreteScheduler, DDIMScheduler351from diffusers.utils.import_utils import is_xformers_available352from transformers import CLIPTextModel, CLIPTokenizer353 354from animatediff.models.unet import UNet3DConditionModel355from animatediff.pipelines.pipeline_animation import AnimationPipeline356from animatediff.utils.util import save_videos_grid357from animatediff.utils.convert_from_ckpt import convert_ldm_unet_checkpoint, convert_ldm_clip_checkpoint, convert_ldm_vae_checkpoint358 359 360pretrained_model_path = "models/StableDiffusion/stable-diffusion-v1-5"361inference_config_path = "configs/inference/inference.yaml"362 363css = """364.toolbutton {365    margin-buttom: 0em 0em 0em 0em;366    max-width: 2.5em;367    min-width: 2.5em !important;368    height: 2.5em;369}370"""371 372examples = [373    # 1-ToonYou374    [375        "toonyou_beta3.safetensors", 376        "mm_sd_v14.ckpt", 377        "masterpiece, best quality, 1girl, solo, cherry blossoms, hanami, pink flower, white flower, spring season, wisteria, petals, flower, plum blossoms, outdoors, falling petals, white hair, black eyes",378        "worst quality, low quality, nsfw, logo",379        512, 512, "13204175718326964000"380    ],381    # 2-Lyriel382    [383        "lyriel_v16.safetensors", 384        "mm_sd_v15.ckpt", 385        "A forbidden castle high up in the mountains, pixel art, intricate details2, hdr, intricate details, hyperdetailed5, natural skin texture, hyperrealism, soft light, sharp, game art, key visual, surreal",386        "3d, cartoon, anime, sketches, worst quality, low quality, normal quality, lowres, normal quality, monochrome, grayscale, skin spots, acnes, skin blemishes, bad anatomy, girl, loli, young, large breasts, red eyes, muscular",387        512, 512, "6681501646976930000"388    ],389    # 3-RCNZ390    [391        "rcnzCartoon3d_v10.safetensors", 392        "mm_sd_v14.ckpt", 393        "Jane Eyre with headphones, natural skin texture,4mm,k textures, soft cinematic light, adobe lightroom, photolab, hdr, intricate, elegant, highly detailed, sharp focus, cinematic look, soothing tones, insane details, intricate details, hyperdetailed, low contrast, soft cinematic light, dim colors, exposure blend, hdr, faded",394        "deformed, distorted, disfigured, poorly drawn, bad anatomy, wrong anatomy, extra limb, missing limb, floating limbs, mutated hands and fingers, disconnected limbs, mutation, mutated, ugly, disgusting, blurry, amputation",395        512, 512, "2416282124261060"396    ],397    # 4-MajicMix398    [399        "majicmixRealistic_v5Preview.safetensors", 400        "mm_sd_v14.ckpt", 401        "1girl, offshoulder, light smile, shiny skin best quality, masterpiece, photorealistic",402        "bad hand, worst quality, low quality, normal quality, lowres, bad anatomy, bad hands, watermark, moles",403        512, 512, "7132772652786303"404    ],405    # 5-RealisticVision406    [407        "realisticVisionV20_v20.safetensors", 408        "mm_sd_v15.ckpt", 409        "photo of coastline, rocks, storm weather, wind, waves, lightning, 8k uhd, dslr, soft lighting, high quality, film grain, Fujifilm XT3",410        "blur, haze, deformed iris, deformed pupils, semi-realistic, cgi, 3d, render, sketch, cartoon, drawing, anime, mutated hands and fingers, deformed, distorted, disfigured, poorly drawn, bad anatomy, wrong anatomy, extra limb, missing limb, floating limbs, disconnected limbs, mutation, mutated, ugly, disgusting, amputation",411        512, 512, "1490157606650685400"412    ]413]414 415# clean unrelated ckpts416# ckpts = [417#     "realisticVisionV40_v20Novae.safetensors",418#     "majicmixRealistic_v5Preview.safetensors",419#     "rcnzCartoon3d_v10.safetensors",420#     "lyriel_v16.safetensors",421#     "toonyou_beta3.safetensors"422# ]423 424# for path in glob(os.path.join("models", "DreamBooth_LoRA", "*.safetensors")):425#     for ckpt in ckpts:426#         if path.endswith(ckpt): break427#     else:428#         print(f"### Cleaning {path} ...")429#         os.system(f"rm -rf {path}")430 431# os.system(f"rm -rf {os.path.join('models', 'DreamBooth_LoRA', '*.safetensors')}")432 433# os.system(f"bash download_bashscripts/1-ToonYou.sh")434# os.system(f"bash download_bashscripts/2-Lyriel.sh")435# os.system(f"bash download_bashscripts/3-RcnzCartoon.sh")436# os.system(f"bash download_bashscripts/4-MajicMix.sh")437# os.system(f"bash download_bashscripts/5-RealisticVision.sh")438 439# clean Grdio cache440print(f"### Cleaning cached examples ...")441os.system(f"rm -rf gradio_cached_examples/")442 443 444class AnimateController:445    def __init__(self):446        447        # config dirs448        self.basedir                = os.getcwd()449        self.stable_diffusion_dir   = os.path.join(self.basedir, "models", "StableDiffusion")450        self.motion_module_dir      = os.path.join(self.basedir, "models", "Motion_Module")451        self.personalized_model_dir = os.path.join(self.basedir, "models", "DreamBooth_LoRA")452        self.savedir                = os.path.join(self.basedir, "samples")453        os.makedirs(self.savedir, exist_ok=True)454 455        self.base_model_list    = []456        self.motion_module_list = []457        458        self.selected_base_model    = None459        self.selected_motion_module = None460        461        self.refresh_motion_module()462        self.refresh_personalized_model()463        464        # config models465        self.inference_config      = OmegaConf.load(inference_config_path)466 467        self.tokenizer             = CLIPTokenizer.from_pretrained(pretrained_model_path, subfolder="tokenizer")468        self.text_encoder          = CLIPTextModel.from_pretrained(pretrained_model_path, subfolder="text_encoder").cuda()469        self.vae                   = AutoencoderKL.from_pretrained(pretrained_model_path, subfolder="vae").cuda()470        self.unet                  = UNet3DConditionModel.from_pretrained_2d(pretrained_model_path, subfolder="unet", unet_additional_kwargs=OmegaConf.to_container(self.inference_config.unet_additional_kwargs)).cuda()471        472        self.update_base_model(self.base_model_list[0])473        self.update_motion_module(self.motion_module_list[0])474        475        476    def refresh_motion_module(self):477        motion_module_list = glob(os.path.join(self.motion_module_dir, "*.ckpt"))478        self.motion_module_list = [os.path.basename(p) for p in motion_module_list]479 480    def refresh_personalized_model(self):481        base_model_list = glob(os.path.join(self.personalized_model_dir, "*.safetensors"))482        self.base_model_list = [os.path.basename(p) for p in base_model_list]483 484 485    def update_base_model(self, base_model_dropdown):486        self.selected_base_model = base_model_dropdown487        488        base_model_dropdown = os.path.join(self.personalized_model_dir, base_model_dropdown)489        base_model_state_dict = {}490        with safe_open(base_model_dropdown, framework="pt", device="cpu") as f:491            for key in f.keys(): base_model_state_dict[key] = f.get_tensor(key)492                493        converted_vae_checkpoint = convert_ldm_vae_checkpoint(base_model_state_dict, self.vae.config)494        self.vae.load_state_dict(converted_vae_checkpoint)495 496        converted_unet_checkpoint = convert_ldm_unet_checkpoint(base_model_state_dict, self.unet.config)497        self.unet.load_state_dict(converted_unet_checkpoint, strict=False)498 499        self.text_encoder = convert_ldm_clip_checkpoint(base_model_state_dict)500        return gr.Dropdown.update()501 502    def update_motion_module(self, motion_module_dropdown):503        self.selected_motion_module = motion_module_dropdown504        505        motion_module_dropdown = os.path.join(self.motion_module_dir, motion_module_dropdown)506        motion_module_state_dict = torch.load(motion_module_dropdown, map_location="cpu")507        _, unexpected = self.unet.load_state_dict(motion_module_state_dict, strict=False)508        assert len(unexpected) == 0509        return gr.Dropdown.update()510    511    512    def animate(513        self,514        base_model_dropdown,515        motion_module_dropdown,516        prompt_textbox,517        negative_prompt_textbox,518        width_slider,519        height_slider,520        seed_textbox,521    ):522        if self.selected_base_model != base_model_dropdown: self.update_base_model(base_model_dropdown)523        if self.selected_motion_module != motion_module_dropdown: self.update_motion_module(motion_module_dropdown)524        525        if is_xformers_available(): self.unet.enable_xformers_memory_efficient_attention()526 527        pipeline = AnimationPipeline(528            vae=self.vae, text_encoder=self.text_encoder, tokenizer=self.tokenizer, unet=self.unet,529            scheduler=DDIMScheduler(**OmegaConf.to_container(self.inference_config.noise_scheduler_kwargs))530        ).to("cuda")531        532        if int(seed_textbox) > 0: seed = int(seed_textbox)533        else: seed = random.randint(1, 1e16)534        torch.manual_seed(int(seed))535        536        assert seed == torch.initial_seed()537        print(f"### seed: {seed}")538        539        generator = torch.Generator(device="cuda")540        generator.manual_seed(seed)541        542        sample = pipeline(543            prompt_textbox,544            negative_prompt     = negative_prompt_textbox,545            num_inference_steps = 25,546            guidance_scale      = 8.,547            width               = width_slider,548            height              = height_slider,549            video_length        = 16,550            generator           = generator,551        ).videos552 553        save_sample_path = os.path.join(self.savedir, f"sample.mp4")554        save_videos_grid(sample, save_sample_path)555    556        json_config = {557            "prompt": prompt_textbox,558            "n_prompt": negative_prompt_textbox,559            "width": width_slider,560            "height": height_slider,561            "seed": seed,562            "base_model": base_model_dropdown,563            "motion_module": motion_module_dropdown,564        }565        return gr.Video.update(value=save_sample_path), gr.Json.update(value=json_config)566        567 568controller = AnimateController()569 570 571def ui():572    with gr.Blocks(css=css) as demo:573        gr.Markdown(574            """575            # AnimateDiff: Animate Your Personalized Text-to-Image Diffusion Models without Specific Tuning576            Yuwei Guo, Ceyuan Yang*, Anyi Rao, Yaohui Wang, Yu Qiao, Dahua Lin, Bo Dai (*Corresponding Author)<br>577            [Arxiv Report](https://arxiv.org/abs/2307.04725) | [Project Page](https://animatediff.github.io/) | [Github](https://github.com/guoyww/animatediff/)578            """579        )580        gr.Markdown(581            """582            ### Quick Start583            1. Select desired `Base DreamBooth Model`.584            2. Select `Motion Module` from `mm_sd_v14.ckpt` and `mm_sd_v15.ckpt`. We recommend trying both of them for the best results.585            3. Provide `Prompt` and `Negative Prompt` for each model. You are encouraged to refer to each model's webpage on CivitAI to learn how to write prompts for them. Below are the DreamBooth models in this demo. Click to visit their homepage.586                - [`toonyou_beta3.safetensors`](https://civitai.com/models/30240?modelVersionId=78775)587                - [`lyriel_v16.safetensors`](https://civitai.com/models/22922/lyriel)588                - [`rcnzCartoon3d_v10.safetensors`](https://civitai.com/models/66347?modelVersionId=71009)589                - [`majicmixRealistic_v5Preview.safetensors`](https://civitai.com/models/43331?modelVersionId=79068)590                - [`realisticVisionV20_v20.safetensors`](https://civitai.com/models/4201?modelVersionId=29460)591            4. Click `Generate`, wait for ~1 min, and enjoy.592            """593        )594        with gr.Row():595            with gr.Column():596                base_model_dropdown     = gr.Dropdown( label="Base DreamBooth Model", choices=controller.base_model_list,    value=controller.base_model_list[0],    interactive=True )597                motion_module_dropdown  = gr.Dropdown( label="Motion Module",  choices=controller.motion_module_list, value=controller.motion_module_list[0], interactive=True )598 599                base_model_dropdown.change(fn=controller.update_base_model,       inputs=[base_model_dropdown],    outputs=[base_model_dropdown])600                motion_module_dropdown.change(fn=controller.update_motion_module, inputs=[motion_module_dropdown], outputs=[motion_module_dropdown])601 602                prompt_textbox          = gr.Textbox( label="Prompt",          lines=3 )603                negative_prompt_textbox = gr.Textbox( label="Negative Prompt", lines=3, value="worst quality, low quality, nsfw, logo")604 605                with gr.Accordion("Advance", open=False):606                    with gr.Row():607                        width_slider  = gr.Slider(  label="Width",  value=512, minimum=256, maximum=1024, step=64 )608                        height_slider = gr.Slider(  label="Height", value=512, minimum=256, maximum=1024, step=64 )609                    with gr.Row():610                        seed_textbox = gr.Textbox( label="Seed",  value=-1)611                        seed_button  = gr.Button(value="\U0001F3B2", elem_classes="toolbutton")612                        seed_button.click(fn=lambda: gr.Textbox.update(value=random.randint(1, 1e16)), inputs=[], outputs=[seed_textbox])613 614                generate_button = gr.Button( value="Generate", variant='primary' )615 616            with gr.Column():617                result_video = gr.Video( label="Generated Animation", interactive=False )618                json_config  = gr.Json( label="Config", value=None )619 620            inputs  = [base_model_dropdown, motion_module_dropdown, prompt_textbox, negative_prompt_textbox, width_slider, height_slider, seed_textbox]621            outputs = [result_video, json_config]622            623            generate_button.click( fn=controller.animate, inputs=inputs, outputs=outputs )624                625        gr.Examples( fn=controller.animate, examples=examples, inputs=inputs, outputs=outputs, cache_examples=True )626        627    return demo628 629 630if __name__ == "__main__":631    demo = ui()632    demo.queue(max_size=20)633    demo.launch()634