Update app.py
Browse files
app.py
CHANGED
@@ -1,4 +1,3 @@
|
|
1 |
-
|
2 |
import os
|
3 |
import json
|
4 |
import urllib.request
|
@@ -11,6 +10,7 @@ from hercai import Hercai
|
|
11 |
import uuid
|
12 |
import time
|
13 |
import gradio as gr
|
|
|
14 |
|
15 |
# Configure detailed logging
|
16 |
log_dir = os.getenv('LOG_DIRECTORY', './') # Get log directory from environment variable, default to current directory
|
@@ -42,7 +42,7 @@ LOGGER.setLevel(log_level) # Set the log level for the logger instance
|
|
42 |
|
43 |
class Text2Video:
|
44 |
"""
|
45 |
-
A class to generate videos from text prompts, with detailed logging and a user-friendly interface.
|
46 |
"""
|
47 |
|
48 |
def __init__(self) -> None:
|
@@ -53,12 +53,14 @@ class Text2Video:
|
|
53 |
self.herc = Hercai("") # Replace "" with your actual Hercai API key if you have one
|
54 |
LOGGER.info("Hercai initialized successfully")
|
55 |
|
56 |
-
def get_image(self, img_prompt: str) -> str:
|
57 |
"""
|
58 |
-
Generate an image from a text prompt using
|
59 |
|
60 |
Args:
|
61 |
img_prompt (str): The text prompt to generate the image from.
|
|
|
|
|
62 |
|
63 |
Returns:
|
64 |
str: The URL of the generated image. Returns an empty string if an error occurred.
|
@@ -69,12 +71,46 @@ class Text2Video:
|
|
69 |
modified_prompt = f"Generate a comic book style image with speech bubbles containing the following text: '{img_prompt}'. " \
|
70 |
f"Include elements like vibrant colors, onomatopoeia, and exaggerated expressions to enhance the comic book aesthetic."
|
71 |
# Log the modified prompt
|
72 |
-
LOGGER.info(f"Modified prompt for
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
|
79 |
# Log the generated image URL
|
80 |
LOGGER.info(f"Image generated successfully: {image_url}")
|
@@ -82,7 +118,7 @@ class Text2Video:
|
|
82 |
|
83 |
except Exception as e:
|
84 |
# Log any errors encountered during image generation
|
85 |
-
LOGGER.error(f"Error generating image for prompt '{img_prompt}': {e}")
|
86 |
return ""
|
87 |
|
88 |
def download_img_from_url(self, image_url: str, image_path: str) -> str:
|
@@ -138,12 +174,14 @@ class Text2Video:
|
|
138 |
LOGGER.error(f"Error converting text '{img_prompt}' to audio: {e}")
|
139 |
return ""
|
140 |
|
141 |
-
def get_images_and_audio(self, list_prompts: list) -> tuple:
|
142 |
"""
|
143 |
-
Generate images and corresponding audio files for a list of text prompts.
|
144 |
|
145 |
Args:
|
146 |
list_prompts (list): A list of text prompts.
|
|
|
|
|
147 |
|
148 |
Returns:
|
149 |
tuple: A tuple containing two lists: image paths and audio paths.
|
@@ -160,8 +198,8 @@ class Text2Video:
|
|
160 |
# Construct the image path using the unique identifier
|
161 |
image_path = f"{img_prompt[:9]}_{unique_id}.png"
|
162 |
|
163 |
-
# Generate the image URL using
|
164 |
-
img_url = self.get_image(img_prompt)
|
165 |
|
166 |
# Download the image from the generated URL
|
167 |
image = self.download_img_from_url(img_url, image_path)
|
@@ -237,13 +275,14 @@ class Text2Video:
|
|
237 |
# Log any errors encountered during video creation
|
238 |
LOGGER.error(f"Error creating video: {e}")
|
239 |
|
240 |
-
|
241 |
-
def generate_video(self, text: str) -> str:
|
242 |
"""
|
243 |
-
Generate a video from a comma-separated string of text prompts
|
244 |
|
245 |
Args:
|
246 |
text (str): A comma-separated string of text prompts, where each prompt represents a scene or frame in the video.
|
|
|
|
|
247 |
|
248 |
Returns:
|
249 |
str: The file path of the generated video file. Returns an empty string if an error occurred.
|
@@ -257,8 +296,8 @@ class Text2Video:
|
|
257 |
# Define the output path for the generated video
|
258 |
output_path = "output_video.mp4"
|
259 |
|
260 |
-
# Generate images and corresponding audio files for each prompt
|
261 |
-
img_list, audio_paths = self.get_images_and_audio(list_prompts)
|
262 |
|
263 |
# Create the video from the generated images and audio files
|
264 |
self.create_video_from_images_and_audio(img_list, audio_paths, output_path)
|
@@ -271,7 +310,6 @@ class Text2Video:
|
|
271 |
LOGGER.error(f"Error generating video from text '{text}': {e}")
|
272 |
return ""
|
273 |
|
274 |
-
|
275 |
def gradio_interface(self):
|
276 |
"""
|
277 |
Creates a user-friendly Gradio interface for the video generation application.
|
@@ -287,6 +325,20 @@ class Text2Video:
|
|
287 |
input_text = gr.Textbox(label="Comics Text",
|
288 |
placeholder="Enter the comics text, separating scenes with double commas (,,)")
|
289 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
290 |
# Create a button that triggers the video generation process
|
291 |
with gr.Row(elem_id="col-container"):
|
292 |
button = gr.Button("Generate Video")
|
@@ -302,8 +354,8 @@ class Text2Video:
|
|
302 |
'That's okay', said the visitor. 'I will make stone soup for everyone'. Then he took a stone and dropped it into a giant pot,,"""
|
303 |
example = gr.Examples([example_txt], input_text)
|
304 |
|
305 |
-
# Define the button's click event to call the generate_video function with the user's input
|
306 |
-
button.click(self.generate_video, [input_text], output)
|
307 |
|
308 |
LOGGER.info("Gradio interface launched successfully")
|
309 |
# Launch the Gradio interface
|
|
|
|
|
1 |
import os
|
2 |
import json
|
3 |
import urllib.request
|
|
|
10 |
import uuid
|
11 |
import time
|
12 |
import gradio as gr
|
13 |
+
import requests
|
14 |
|
15 |
# Configure detailed logging
|
16 |
log_dir = os.getenv('LOG_DIRECTORY', './') # Get log directory from environment variable, default to current directory
|
|
|
42 |
|
43 |
class Text2Video:
|
44 |
"""
|
45 |
+
A class to generate videos from text prompts, with detailed logging, model selection, and a user-friendly interface.
|
46 |
"""
|
47 |
|
48 |
def __init__(self) -> None:
|
|
|
53 |
self.herc = Hercai("") # Replace "" with your actual Hercai API key if you have one
|
54 |
LOGGER.info("Hercai initialized successfully")
|
55 |
|
56 |
+
def get_image(self, img_prompt: str, image_generator: str, image_model: str) -> str:
|
57 |
"""
|
58 |
+
Generate an image from a text prompt using the selected AI model, with detailed logging and comic book styling.
|
59 |
|
60 |
Args:
|
61 |
img_prompt (str): The text prompt to generate the image from.
|
62 |
+
image_generator (str): The name of the AI image generation service (Hercai, Prodia, or Pollinations).
|
63 |
+
image_model (str): The specific model to use within the selected AI image generation service.
|
64 |
|
65 |
Returns:
|
66 |
str: The URL of the generated image. Returns an empty string if an error occurred.
|
|
|
71 |
modified_prompt = f"Generate a comic book style image with speech bubbles containing the following text: '{img_prompt}'. " \
|
72 |
f"Include elements like vibrant colors, onomatopoeia, and exaggerated expressions to enhance the comic book aesthetic."
|
73 |
# Log the modified prompt
|
74 |
+
LOGGER.info(f"Modified prompt for {image_generator}: {modified_prompt}")
|
75 |
+
image_url = ""
|
76 |
+
|
77 |
+
if image_generator == "Hercai":
|
78 |
+
# Log the selected Hercai model
|
79 |
+
LOGGER.info(f"Using Hercai model: {image_model}")
|
80 |
+
|
81 |
+
# Generate the image using Hercai
|
82 |
+
image_result = self.herc.draw_image(model=image_model, prompt=modified_prompt, negative_prompt="Dark and gloomy")
|
83 |
+
# Extract the image URL from the result
|
84 |
+
image_url = image_result["url"]
|
85 |
+
|
86 |
+
elif image_generator == "Prodia":
|
87 |
+
# Log the selected Prodia model
|
88 |
+
LOGGER.info(f"Using Prodia model: {image_model}")
|
89 |
+
# Create the Prodia API call
|
90 |
+
api_url = "https://api.prodia.com/v1/generate"
|
91 |
+
payload = {
|
92 |
+
"model": image_model,
|
93 |
+
"prompt": modified_prompt,
|
94 |
+
"negative_prompt": "Dark and gloomy"
|
95 |
+
}
|
96 |
+
headers = {
|
97 |
+
"Authorization": "Bearer YOUR_PRODIA_API_KEY" # Replace YOUR_PRODIA_API_KEY with your actual Prodia API key
|
98 |
+
}
|
99 |
+
response = requests.post(api_url, json=payload, headers=headers)
|
100 |
+
if response.status_code == 200:
|
101 |
+
image_url = response.json()["url"]
|
102 |
+
# Log the generated image URL
|
103 |
+
LOGGER.info(f"Image generated successfully using Prodia: {image_url}")
|
104 |
+
else:
|
105 |
+
# Log an error if the Prodia API call failed
|
106 |
+
LOGGER.error(f"Error generating image using Prodia: {response.text}")
|
107 |
+
|
108 |
+
elif image_generator == "Pollinations":
|
109 |
+
# Log the selected Pollinations model
|
110 |
+
LOGGER.info(f"Using Pollinations model: {image_model}")
|
111 |
+
# Implement Pollinations API call here, similar to Prodia
|
112 |
+
# Replace the following placeholder with your Pollinations API call
|
113 |
+
# ...
|
114 |
|
115 |
# Log the generated image URL
|
116 |
LOGGER.info(f"Image generated successfully: {image_url}")
|
|
|
118 |
|
119 |
except Exception as e:
|
120 |
# Log any errors encountered during image generation
|
121 |
+
LOGGER.error(f"Error generating image for prompt '{img_prompt}' using {image_generator}: {e}")
|
122 |
return ""
|
123 |
|
124 |
def download_img_from_url(self, image_url: str, image_path: str) -> str:
|
|
|
174 |
LOGGER.error(f"Error converting text '{img_prompt}' to audio: {e}")
|
175 |
return ""
|
176 |
|
177 |
+
def get_images_and_audio(self, list_prompts: list, image_generator: str, image_model: str) -> tuple:
|
178 |
"""
|
179 |
+
Generate images and corresponding audio files for a list of text prompts using the selected AI model.
|
180 |
|
181 |
Args:
|
182 |
list_prompts (list): A list of text prompts.
|
183 |
+
image_generator (str): The name of the AI image generation service (Hercai, Prodia, or Pollinations).
|
184 |
+
image_model (str): The specific model to use within the selected AI image generation service.
|
185 |
|
186 |
Returns:
|
187 |
tuple: A tuple containing two lists: image paths and audio paths.
|
|
|
198 |
# Construct the image path using the unique identifier
|
199 |
image_path = f"{img_prompt[:9]}_{unique_id}.png"
|
200 |
|
201 |
+
# Generate the image URL using the selected AI model
|
202 |
+
img_url = self.get_image(img_prompt, image_generator, image_model)
|
203 |
|
204 |
# Download the image from the generated URL
|
205 |
image = self.download_img_from_url(img_url, image_path)
|
|
|
275 |
# Log any errors encountered during video creation
|
276 |
LOGGER.error(f"Error creating video: {e}")
|
277 |
|
278 |
+
def generate_video(self, text: str, image_generator: str, image_model: str) -> str:
|
|
|
279 |
"""
|
280 |
+
Generate a video from a comma-separated string of text prompts using the selected AI model.
|
281 |
|
282 |
Args:
|
283 |
text (str): A comma-separated string of text prompts, where each prompt represents a scene or frame in the video.
|
284 |
+
image_generator (str): The name of the AI image generation service (Hercai, Prodia, or Pollinations).
|
285 |
+
image_model (str): The specific model to use within the selected AI image generation service.
|
286 |
|
287 |
Returns:
|
288 |
str: The file path of the generated video file. Returns an empty string if an error occurred.
|
|
|
296 |
# Define the output path for the generated video
|
297 |
output_path = "output_video.mp4"
|
298 |
|
299 |
+
# Generate images and corresponding audio files for each prompt using the selected AI model
|
300 |
+
img_list, audio_paths = self.get_images_and_audio(list_prompts, image_generator, image_model)
|
301 |
|
302 |
# Create the video from the generated images and audio files
|
303 |
self.create_video_from_images_and_audio(img_list, audio_paths, output_path)
|
|
|
310 |
LOGGER.error(f"Error generating video from text '{text}': {e}")
|
311 |
return ""
|
312 |
|
|
|
313 |
def gradio_interface(self):
|
314 |
"""
|
315 |
Creates a user-friendly Gradio interface for the video generation application.
|
|
|
325 |
input_text = gr.Textbox(label="Comics Text",
|
326 |
placeholder="Enter the comics text, separating scenes with double commas (,,)")
|
327 |
|
328 |
+
# Create a dropdown menu for selecting the AI image generation service
|
329 |
+
with gr.Row(elem_id="col-container"):
|
330 |
+
image_generator = gr.Dropdown(label="Image Generator",
|
331 |
+
choices=["Hercai", "Prodia", "Pollinations"],
|
332 |
+
value="Hercai",
|
333 |
+
interactive=True)
|
334 |
+
|
335 |
+
# Create a dropdown menu for selecting the specific model within the chosen service
|
336 |
+
with gr.Row(elem_id="col-container"):
|
337 |
+
image_model = gr.Dropdown(label="Image Model",
|
338 |
+
choices=["v1", "v2", "v3", "simurg", "animefy", "raava", "shonin"],
|
339 |
+
value="v3",
|
340 |
+
interactive=True)
|
341 |
+
|
342 |
# Create a button that triggers the video generation process
|
343 |
with gr.Row(elem_id="col-container"):
|
344 |
button = gr.Button("Generate Video")
|
|
|
354 |
'That's okay', said the visitor. 'I will make stone soup for everyone'. Then he took a stone and dropped it into a giant pot,,"""
|
355 |
example = gr.Examples([example_txt], input_text)
|
356 |
|
357 |
+
# Define the button's click event to call the generate_video function with the user's input and model selection
|
358 |
+
button.click(self.generate_video, [input_text, image_generator, image_model], output)
|
359 |
|
360 |
LOGGER.info("Gradio interface launched successfully")
|
361 |
# Launch the Gradio interface
|