robertselvam commited on
Commit
6d8c213
·
verified ·
1 Parent(s): 88a87e4

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +282 -0
app.py ADDED
@@ -0,0 +1,282 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ import urllib.request
4
+ from PIL import Image
5
+ from gtts import gTTS
6
+ import cv2
7
+ import moviepy.editor as mp
8
+ import logging
9
+ from openai import AzureOpenAI
10
+ import uuid
11
+ import time
12
+ import gradio as gr
13
+ # Configure logging
14
+ log_dir = os.getenv('LOG_DIRECTORY', './')
15
+ LOGGER_FILE_PATH = os.path.join(str(log_dir), 'utils.log')
16
+
17
+ logging.basicConfig(
18
+ filename=LOGGER_FILE_PATH,
19
+ filemode='a',
20
+ format='[%(asctime)s] [%(levelname)s] [%(filename)s] [%(lineno)s:%(funcName)s()] %(message)s',
21
+ datefmt='%Y-%b-%d %H:%M:%S'
22
+ )
23
+ LOGGER = logging.getLogger(__name__)
24
+
25
+ log_level_env = os.getenv('LOG_LEVEL', 'INFO')
26
+ log_level_dict = {
27
+ 'DEBUG': logging.DEBUG,
28
+ 'INFO': logging.INFO,
29
+ 'WARNING': logging.WARNING,
30
+ 'ERROR': logging.ERROR,
31
+ 'CRITICAL': logging.CRITICAL
32
+ }
33
+ if log_level_env in log_level_dict:
34
+ log_level = log_level_dict[log_level_env]
35
+ else:
36
+ log_level = log_level_dict['INFO']
37
+ LOGGER.setLevel(log_level)
38
+
39
+
40
+ class Text2Video:
41
+ """A class to generate videos from text prompts."""
42
+
43
+ def __init__(self) -> None:
44
+ """
45
+ Initialize the Text2Video class.
46
+
47
+ Args:
48
+ file_path (str): Path to the configuration file.
49
+ """
50
+ self.client = AzureOpenAI()
51
+
52
+ def get_image(self, img_prompt: str) -> str:
53
+ """
54
+ Generate an image based on the provided text prompt.
55
+
56
+ Args:
57
+ img_prompt (str): Text prompt for generating the image.
58
+
59
+ Returns:
60
+ str: URL of the generated image.
61
+ """
62
+ try:
63
+ # Generate image using Azure OpenAI client
64
+ result = self.client.images.generate(
65
+ model="Dalle3",
66
+ prompt=f"text: ``` {img_prompt}```. add this backticked text in the image as comics.",
67
+ n=1,
68
+ quality="hd",
69
+ size="1792x1024",
70
+ style="vivid"
71
+ )
72
+
73
+ # Extract URL from the result
74
+ image_url = json.loads(result.model_dump_json())['data'][0]['url']
75
+ return image_url
76
+
77
+ except Exception as e:
78
+ # Log any errors encountered during image generation
79
+ LOGGER.error(f"Error generating image: {e}")
80
+ return ""
81
+
82
+ def download_img_from_url(self, image_url: str, image_path: str) -> str:
83
+ """
84
+ Download an image from a URL.
85
+
86
+ Args:
87
+ image_url (str): URL of the image to download.
88
+ image_path (str): Path to save the downloaded image.
89
+
90
+ Returns:
91
+ str: Path of the downloaded image.
92
+ """
93
+ try:
94
+ # Download the image from the provided URL and save it to the specified path
95
+ urllib.request.urlretrieve(image_url, image_path)
96
+ return image_path # Return the path of the downloaded image if successful
97
+
98
+ except Exception as e:
99
+ # Log any errors encountered during image download
100
+ LOGGER.error(f"Error downloading image from URL: {e}")
101
+ return "" # Return an empty string if an error occurs
102
+
103
+ def text_to_audio(self, img_prompt: str, audio_path: str) -> str:
104
+ """
105
+ Convert text to speech and save it as an audio file.
106
+
107
+ Args:
108
+ img_prompt (str): Text to convert to speech.
109
+ audio_path (str): Path to save the audio file.
110
+
111
+ Returns:
112
+ str: Path of the saved audio file.
113
+ """
114
+ try:
115
+ language = 'en'
116
+
117
+ # Create a gTTS object to convert text to speech
118
+ myobj = gTTS(text=img_prompt, lang=language, slow=False)
119
+
120
+ # Save the audio file at the specified path
121
+ myobj.save(audio_path)
122
+
123
+ # Return the path of the saved audio file if successful
124
+ return audio_path
125
+ except Exception as e:
126
+
127
+ # Log any errors encountered during text-to-audio conversion
128
+ LOGGER.error(f"Error converting text to audio: {e}")
129
+ return ""
130
+
131
+ def get_images_and_audio(self, list_prompts: list) -> tuple:
132
+ """
133
+ Generate images and corresponding audio files from a list of prompts.
134
+
135
+ Args:
136
+ list_prompts (list): List of text prompts.
137
+
138
+ Returns:
139
+ tuple: A tuple containing lists of image paths and audio paths.
140
+ """
141
+ img_list = [] # Initialize an empty list to store image paths
142
+ audio_paths = [] # Initialize an empty list to store audio paths
143
+ for img_prompt in list_prompts:
144
+ try:
145
+ # Generate a unique identifier for this file
146
+ unique_id = uuid.uuid4().hex
147
+
148
+ # Construct the image path using the unique identifier
149
+ image_path = f"{img_prompt[:9]}_{unique_id}.png"
150
+
151
+ # Generate image URL based on the prompt
152
+ img_url = self.get_image(img_prompt)
153
+
154
+ # Download and save the image
155
+ image = self.download_img_from_url(img_url, image_path)
156
+
157
+ # Add the image path to the list
158
+ img_list.append(image)
159
+
160
+ # Construct the audio path using the unique identifier
161
+ audio_path = f"{img_prompt[:9]}_{unique_id}.mp3"
162
+
163
+ # Convert text to audio and save it
164
+ audio = self.text_to_audio(img_prompt, audio_path)
165
+
166
+ # Add the audio path to the list
167
+ audio_paths.append(audio)
168
+
169
+ except Exception as e:
170
+ LOGGER.error(f"Error processing prompt: {img_prompt}, {e}")
171
+
172
+ # Return lists of image paths and audio paths as a tuple
173
+ return img_list, audio_paths
174
+
175
+ def create_video_from_images_and_audio(self, image_files: list, audio_files: list, output_path: str) -> None:
176
+ """
177
+ Create a video from images and corresponding audio files.
178
+
179
+ Args:
180
+ image_files (list): List of image files.
181
+ audio_files (list): List of audio files.
182
+ output_path (str): Path to save the output video file.
183
+ """
184
+ try:
185
+ # Check if the number of images matches the number of audio files
186
+ if len(image_files) != len(audio_files):
187
+ LOGGER.error("Error: Number of images doesn't match the number of audio files.")
188
+ return
189
+
190
+ # Initialize an empty list to store video clips
191
+ video_clips = []
192
+
193
+
194
+ for image_file, audio_file in zip(image_files, audio_files):
195
+
196
+ # Read the image frame
197
+ frame = cv2.imread(image_file)
198
+
199
+ # Load the audio clip
200
+ audio_clip = mp.AudioFileClip(audio_file)
201
+
202
+ # Create video clip with image
203
+ video_clip = mp.ImageClip(image_file).set_duration(audio_clip.duration)
204
+
205
+ # Set audio for the video clip
206
+ video_clip = video_clip.set_audio(audio_clip)
207
+
208
+ # Append the video clip to the list
209
+ video_clips.append(video_clip)
210
+
211
+ # Concatenate all video clips into a single clip
212
+ final_clip = mp.concatenate_videoclips(video_clips)
213
+
214
+ # Write the final video to the output path
215
+ final_clip.write_videofile(output_path, codec='libx264', fps=24)
216
+ print("Video created successfully.")
217
+
218
+ except Exception as e:
219
+ # Log any errors encountered during video creation
220
+ LOGGER.error(f"Error creating video: {e}")
221
+
222
+ def generate_video(self, text: list) -> None:
223
+ """
224
+ Generate a video from a list of text prompts.
225
+
226
+ Args:
227
+ list_prompts (list): List of text prompts.
228
+ """
229
+ try:
230
+ list_prompts = [sentence.strip() for sentence in text.split(",,") if sentence.strip()]
231
+
232
+ # Set the output path for the generated video
233
+ output_path = "output_video1.mp4"
234
+
235
+ # Generate images and corresponding audio files
236
+ img_list, audio_paths = self.get_images_and_audio(list_prompts)
237
+
238
+ # Create video from images and audio
239
+ self.create_video_from_images_and_audio(img_list, audio_paths, output_path)
240
+
241
+ return output_path
242
+ except Exception as e:
243
+
244
+ # Log any errors encountered during video generation
245
+ LOGGER.error(f"Error generating video: {e}")
246
+
247
+ def gradio_interface(self):
248
+
249
+ with gr.Blocks() as demo:
250
+ example_txt = """
251
+ once upon a time there was a village. It was a nice place to live, except for one thing. people did not like to share.,, One day a visitor came to town. 'Hello. Does anybody have food to share?' He asked. 'No', said everyone.,,
252
+ 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,, The visitor sniffed his broth.Some people came outside to see what he was doing. Some watched from their windows.,,
253
+ 'Mmmm, I love stone soup. The only thing better is stone soup with cabbage', said the visitor. That gave one man in the village an idea. He brought a cabbage and put it in the pot.,,
254
+ Then the visitor said, 'I once had stone soup with cabbage and carrots. It was delicious!', A woman brought carrots and put them in the pot.,,
255
+ Then the visitor said, 'I once had stone soup with cabbage, carrots and corn. It was delicious!', A boy brought corn and put it in the pot.,,
256
+ Then the visitor said, 'I once had stone soup with cabbage and carrots and corn and beans. It was delicious!', A girl brought beans and put them in the pot.,,
257
+ The soup cooked and cooked. Finally it was ready. Everyone ate a big bowl. 'This is delicious!',,
258
+ They all said the soup made them so happy that they danced and sang all night long.,,
259
+ From then on, the people in the village shared. And their very favorite thing to share was stone soup! """
260
+
261
+ gr.HTML("""
262
+ <center><h1 style="color:#fff">Comics Video Generator</h1></center>""")
263
+
264
+ with gr.Row():
265
+ input_text = gr.Textbox(label="Comics Text",placeholder="Enter the comics by double comma separated")
266
+
267
+ with gr.Row():
268
+ button = gr.Button("Generate Video")
269
+
270
+ with gr.Row():
271
+ output = gr.PlayableVideo()
272
+
273
+
274
+ with gr.Row():
275
+ example = gr.Examples([example_txt], input_text)
276
+
277
+ button.click(self.generate_video,[input_text],output)
278
+ demo.launch(debug =True)
279
+
280
+ if __name__ == "__main__":
281
+ text2video = Text2Video()
282
+ text2video.gradio_interface()