diff --git a/README.md b/README.md index 6dd61369..6e00e4cf 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,25 @@ +# Gradio UI for Animated Drawings +I really love the Animated Drawings tool, but it was quite hard to explain how to use it to friends. This is why i decided to create this more convinient way using a Gradio Interface. + +To utilize this tool, follow these simple steps: + +### Setup and Starting the Gradio UI +0. Run the shell script "start_gradio.sh" in the terminal. It will install gradio and run the "gradio_script.py" script. open the localhost on your browser and start using it! + +### Inside of the GUI +1. Input the directory path to your AnimatedDrawings folder. +2. Specify your desired output directory for the generated .yaml file. +3. Click the "Refresh" button to populate the drop-down menus for Character, Motion, and Target. This action will populate these fields based on the folder names in the .../AnimatedDrawings/examples/characters directory for Characters, filenames in the .../AnimatedDrawings/config/motion directory for Motion, and filenames in the .../AnimatedDrawings/config/retarget directory for Target. +4. Next, select your preferred export option - file only, video, or GIF. Choosing MP4 will present a preview directly in the Gradio interface. +5. Finally, click "Export" to generate and export your MVC .yaml files. + +I hope you all find this tool beneficial and enjoyable to use. My next step will involve the Docker part of AnimatedDrawings, though I'm still familiarizing myself with it, so stay tuned for more developments! + + +### Demo Video +https://github.com/vensu-art/AnimatedDrawingsGradio/assets/116193678/107204cc-b4c4-42d0-8abf-510c5df4c46a + + # Animated Drawings ![Sequence 02](https://user-images.githubusercontent.com/6675724/219223438-2c93f9cb-d4b5-45e9-a433-149ed76affa6.gif) diff --git a/gradio_script.py b/gradio_script.py new file mode 100644 index 00000000..ead5fb69 --- /dev/null +++ b/gradio_script.py @@ -0,0 +1,159 @@ +import gradio as gr +import os +import subprocess + + +# Get the names of folders in a directory +def get_folder_names(directory): + return [d for d in os.listdir(directory) if os.path.isdir(os.path.join(directory, d))] + +# Get the names of files in a directory +def get_file_names(directory): + return [f for f in os.listdir(directory) if os.path.isfile(os.path.join(directory, f))] + + +# Function to write MVC +def writeMVC(character_folder, motion_file, target_file, export_radio, output_path, video_path): + # Sets the video format to None, MP4 or Gif + export_format = "" + if export_radio == 1: + export_format = """ +controller: + MODE: video_render + OUTPUT_VIDEO_PATH: {output_video_path}/video.mp4 + OUTPUT_VIDEO_CODEC: avc1 +""".format( + output_video_path=video_path + ) + elif export_radio == 2: + export_format = """ +controller: + MODE: video_render + OUTPUT_VIDEO_PATH: {output_video_path}/video.gif +""".format( + output_video_path=video_path + ) + + updated_config = export_format + """ +scene: + ANIMATED_CHARACTERS: + - character_cfg: examples/characters/{character_cfg}/char_cfg.yaml + motion_cfg: examples/config/motion/{motion_cfg} + retarget_cfg: examples/config/retarget/{retarget_cfg} +""".format( + character_cfg=character_folder, + motion_cfg=motion_file, + retarget_cfg=target_file, + ) + + config_filename = os.path.join(output_path, "custom_config.yaml") + with open(config_filename, "w") as f: + f.write(updated_config) + + + # Run the script to generate + cmd = ['python', '-c', +""" +from animated_drawings import render +render.start('{}') +""".format(config_filename)] + + subprocess.run(cmd) + + + # If the video was generated, return it. + if export_radio == 1: + video_path = os.path.join(video_path, "video.mp4") + if os.path.exists(video_path): + return video_path + + return + + +# Function to refresh dropdown options +def refresh_options(directory): + character_folder_path = os.path.join(directory, 'examples/characters') + motion_file_path = os.path.join(directory, 'examples/config/motion') + target_file_path = os.path.join(directory, 'examples/config/retarget') + + character_choices = get_folder_names(character_folder_path) + motion_choices = get_file_names(motion_file_path) + target_choices = get_file_names(target_file_path) + + # Debug + # print(character_choices) + # print(motion_choices) + # print(target_choices) + + return character_dropdown.update(choices=character_choices), motion_dropdown.update(choices=motion_choices), target_dropdown.update(choices=target_choices), gr.update(visible=True) + + +# Variables for Gradio +character_choices = [] +motion_choices = [] +target_choices = [] + + +# Gradio UI +with gr.Blocks() as iface: + with gr.Row(): + output_video = gr.Video(label="Animation") + + with gr.Row(): + directory_path = gr.Textbox(label="Directory", info="/Users/.../AnimatedDrawings") + output_path = gr.Textbox(label="Output Path Yaml", info="/Users/.../your_yaml_folder") + + + with gr.Row(): + character_dropdown = gr.Dropdown(choices=character_choices, label="Character") + motion_dropdown = gr.Dropdown(choices=motion_choices, label="Motion") + target_dropdown = gr.Dropdown(choices=target_choices, label="Target") + refresh_button = gr.Button("Refresh") + + with gr.Row(): + export_radio = gr.Radio(["None", "MP4", "GIF"], type="index", label="Export", info="Choose the export format") + video_path = gr.Textbox(label="Output Path Video", info="/Users/.../your_video_folder") + + + with gr.Row(): + submit = gr.Button("Export") + + # Gradio Actions + submit.click(writeMVC, [character_dropdown, motion_dropdown, target_dropdown, export_radio, directory_path, video_path], [output_video]) + refresh_button.click(refresh_options, directory_path, [character_dropdown, motion_dropdown, target_dropdown]) #, [character_folder, motion_file, target_file] + +# Launch Gradio as Web UI +iface.launch() + + + + +# Examples from the provided yaml files +""" +# Define the output format GIF or MP4 +controller: + MODE: video_render + OUTPUT_VIDEO_PATH: ./video.mp4 + OUTPUT_VIDEO_CODEC: avc1 + +controller: + MODE: video_render + OUTPUT_VIDEO_PATH: ./video.gif + +# Define the characters, motion and target + scene: + ANIMATED_CHARACTERS: + - character_cfg: examples/characters/char1/char_cfg.yaml + motion_cfg: examples/config/motion/dab.yaml + retarget_cfg: examples/config/retarget/fair1_ppf_duo1.yaml + +# Define View and Background +view: + CAMERA_POS: [0.1, 1.3, 2.7] + WINDOW_DIMENSIONS: [300, 400] + BACKGROUND_IMAGE: examples/characters/char4/background.png + +view: + CAMERA_POS: [2.0, 0.7, 8.0] + CAMERA_FWD: [0.0, 0.5, 8.0] +""" \ No newline at end of file diff --git a/start_gradio.sh b/start_gradio.sh new file mode 100644 index 00000000..ece00ad3 --- /dev/null +++ b/start_gradio.sh @@ -0,0 +1,22 @@ +# start_gradio.sh + +#!/bin/bash + +# check if gradio is installed +pip list | grep gradio &> /dev/null +if [ $? != 0 ]; then + echo "Gradio not found. Installing Gradio..." + pip install gradio +fi + +# check if python3 is installed +command -v python3 >/dev/null 2>&1 || { + echo >&2 "Python3 required but it's not installed. Installing Python3..."; + brew install python3; +} + +# navigate to the script's directory +cd "$(dirname "$0")" + +# start the gradio script +python3 gradio_script.py \ No newline at end of file