AZLABS commited on
Commit
4d1b7c4
·
verified ·
1 Parent(s): c727d9d

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +206 -0
app.py ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ import uuid
10
+ import time
11
+ import gradio as gr
12
+ import g4f
13
+ from g4f import Provider
14
+
15
+ # Configure logging
16
+ log_dir = os.getenv('LOG_DIRECTORY', './')
17
+ LOGGER_FILE_PATH = os.path.join(str(log_dir), 'utils.log')
18
+
19
+ logging.basicConfig(
20
+ filename=LOGGER_FILE_PATH,
21
+ filemode='a',
22
+ format='[%(asctime)s] [%(levelname)s] [%(filename)s] [%(lineno)s:%(funcName)s()] %(message)s',
23
+ datefmt='%Y-%b-%d %H:%M:%S'
24
+ )
25
+ LOGGER = logging.getLogger(__name__)
26
+
27
+ log_level_env = os.getenv('LOG_LEVEL', 'INFO')
28
+ log_level_dict = {
29
+ 'DEBUG': logging.DEBUG,
30
+ 'INFO': logging.INFO,
31
+ 'WARNING': logging.WARNING,
32
+ 'ERROR': logging.ERROR,
33
+ 'CRITICAL': logging.CRITICAL
34
+ }
35
+ if log_level_env in log_level_dict:
36
+ log_level = log_level_dict[log_level_env]
37
+ else:
38
+ log_level = log_level_dict['INFO']
39
+ LOGGER.setLevel(log_level)
40
+
41
+
42
+ class Text2Video:
43
+ """A class to generate videos from text prompts."""
44
+
45
+ def __init__(self) -> None:
46
+ """Initialize the Text2Video class."""
47
+ pass
48
+
49
+ def get_image(self, img_prompt: str) -> str:
50
+ """
51
+ Generate an image based on the provided text prompt using G4F.
52
+ Args:
53
+ img_prompt (str): Text prompt for generating the image.
54
+ Returns:
55
+ str: URL of the generated image.
56
+ """
57
+ try:
58
+ # Using G4F to generate image
59
+ response = g4f.Image.create(
60
+ prompt=f"text: ``` {img_prompt}```. add this backticked text in the image as comics.",
61
+ model="dalle", # or any other available model
62
+ provider=Provider.DeepAI
63
+ )
64
+
65
+ # The response format might vary depending on the provider
66
+ # Assuming it returns a direct image URL
67
+ return response
68
+
69
+ except Exception as e:
70
+ LOGGER.error(f"Error generating image: {e}")
71
+ return ""
72
+
73
+ def download_img_from_url(self, image_url: str, image_path: str) -> str:
74
+ """
75
+ Download an image from a URL.
76
+ Args:
77
+ image_url (str): URL of the image to download.
78
+ image_path (str): Path to save the downloaded image.
79
+ Returns:
80
+ str: Path of the downloaded image.
81
+ """
82
+ try:
83
+ urllib.request.urlretrieve(image_url, image_path)
84
+ return image_path
85
+
86
+ except Exception as e:
87
+ LOGGER.error(f"Error downloading image from URL: {e}")
88
+ return ""
89
+
90
+ def text_to_audio(self, img_prompt: str, audio_path: str) -> str:
91
+ """
92
+ Convert text to speech and save it as an audio file.
93
+ Args:
94
+ img_prompt (str): Text to convert to speech.
95
+ audio_path (str): Path to save the audio file.
96
+ Returns:
97
+ str: Path of the saved audio file.
98
+ """
99
+ try:
100
+ language = 'en'
101
+ myobj = gTTS(text=img_prompt, lang=language, slow=False)
102
+ myobj.save(audio_path)
103
+ return audio_path
104
+ except Exception as e:
105
+ LOGGER.error(f"Error converting text to audio: {e}")
106
+ return ""
107
+
108
+ def get_images_and_audio(self, list_prompts: list) -> tuple:
109
+ """
110
+ Generate images and corresponding audio files from a list of prompts.
111
+ Args:
112
+ list_prompts (list): List of text prompts.
113
+ Returns:
114
+ tuple: A tuple containing lists of image paths and audio paths.
115
+ """
116
+ img_list = []
117
+ audio_paths = []
118
+ for img_prompt in list_prompts:
119
+ try:
120
+ unique_id = uuid.uuid4().hex
121
+ image_path = f"{img_prompt[:9]}_{unique_id}.png"
122
+ img_url = self.get_image(img_prompt)
123
+ image = self.download_img_from_url(img_url, image_path)
124
+ img_list.append(image)
125
+
126
+ audio_path = f"{img_prompt[:9]}_{unique_id}.mp3"
127
+ audio = self.text_to_audio(img_prompt, audio_path)
128
+ audio_paths.append(audio)
129
+
130
+ except Exception as e:
131
+ LOGGER.error(f"Error processing prompt: {img_prompt}, {e}")
132
+
133
+ return img_list, audio_paths
134
+
135
+ def create_video_from_images_and_audio(self, image_files: list, audio_files: list, output_path: str) -> None:
136
+ """
137
+ Create a video from images and corresponding audio files.
138
+ Args:
139
+ image_files (list): List of image files.
140
+ audio_files (list): List of audio files.
141
+ output_path (str): Path to save the output video file.
142
+ """
143
+ try:
144
+ if len(image_files) != len(audio_files):
145
+ LOGGER.error("Error: Number of images doesn't match the number of audio files.")
146
+ return
147
+
148
+ video_clips = []
149
+
150
+ for image_file, audio_file in zip(image_files, audio_files):
151
+ frame = cv2.imread(image_file)
152
+ audio_clip = mp.AudioFileClip(audio_file)
153
+ video_clip = mp.ImageClip(image_file).set_duration(audio_clip.duration)
154
+ video_clip = video_clip.set_audio(audio_clip)
155
+ video_clips.append(video_clip)
156
+
157
+ final_clip = mp.concatenate_videoclips(video_clips)
158
+ final_clip.write_videofile(output_path, codec='libx264', fps=24)
159
+ print("Video created successfully.")
160
+
161
+ except Exception as e:
162
+ LOGGER.error(f"Error creating video: {e}")
163
+
164
+ def generate_video(self, text: list) -> None:
165
+ """
166
+ Generate a video from a list of text prompts.
167
+ Args:
168
+ list_prompts (list): List of text prompts.
169
+ """
170
+ try:
171
+ list_prompts = [sentence.strip() for sentence in text.split(",,") if sentence.strip()]
172
+ output_path = "output_video1.mp4"
173
+ img_list, audio_paths = self.get_images_and_audio(list_prompts)
174
+ self.create_video_from_images_and_audio(img_list, audio_paths, output_path)
175
+ return output_path
176
+ except Exception as e:
177
+ LOGGER.error(f"Error generating video: {e}")
178
+
179
+ def gradio_interface(self):
180
+ with gr.Blocks(css="style.css", theme='abidlabs/dracula_revamped') as demo:
181
+ example_txt = """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.
182
+ 'Hello. Does anybody have food to share?' He asked. 'No', said everyone.,,
183
+ 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,,"""
184
+
185
+ gr.HTML("""
186
+ <center><h1 style="color:#fff">Comics Video Generator</h1></center>""")
187
+
188
+ with gr.Row(elem_id="col-container"):
189
+ input_text = gr.Textbox(label="Comics Text", placeholder="Enter the comics by double comma separated")
190
+
191
+ with gr.Row(elem_id="col-container"):
192
+ button = gr.Button("Generate Video")
193
+
194
+ with gr.Row(elem_id="col-container"):
195
+ output = gr.PlayableVideo()
196
+
197
+ with gr.Row(elem_id="col-container"):
198
+ example = gr.Examples([example_txt], input_text)
199
+
200
+ button.click(self.generate_video, [input_text], output)
201
+ demo.launch(debug=True)
202
+
203
+
204
+ if __name__ == "__main__":
205
+ text2video = Text2Video()
206
+ text2video.gradio_interface()