|
import os |
|
import json |
|
import urllib.request |
|
from PIL import Image |
|
from gtts import gTTS |
|
import cv2 |
|
import moviepy.editor as mp |
|
import logging |
|
from hercai import Hercai |
|
import uuid |
|
import time |
|
import gradio as gr |
|
from typing import Tuple, List |
|
|
|
|
|
log_dir = os.getenv('LOG_DIRECTORY', './') |
|
LOGGER_FILE_PATH = os.path.join(str(log_dir), 'utils.log') |
|
|
|
logging.basicConfig( |
|
filename=LOGGER_FILE_PATH, |
|
filemode='a', |
|
format='[%(asctime)s] [%(levelname)s] [%(filename)s] [%(lineno)s:%(funcName)s()] %(message)s', |
|
datefmt='%Y-%b-%d %H:%M:%S', |
|
level=logging.INFO, |
|
handlers=[ |
|
logging.FileHandler(LOGGER_FILE_PATH), |
|
logging.StreamHandler() |
|
] |
|
) |
|
LOGGER = logging.getLogger(__name__) |
|
|
|
class Text2Video: |
|
def __init__(self) -> None: |
|
"""Initialize the Text2Video class.""" |
|
self.herc = Hercai() |
|
LOGGER.info("Initialized Text2Video with Hercai API") |
|
|
|
def get_image(self, img_prompt: str) -> str: |
|
"""Generate an image based on the provided text prompt.""" |
|
try: |
|
|
|
enhanced_prompt = ( |
|
f"Create a high-quality comic panel: {img_prompt}. " |
|
"Style: Professional comic book illustration, " |
|
"vivid colors, clear composition, dramatic lighting. " |
|
"Include text as comic-style captions. " |
|
"Resolution: High detail, 1792x1024 aspect ratio. " |
|
"Quality: Professional grade comic art." |
|
) |
|
|
|
result = self.herc.draw_image( |
|
model="simurg", |
|
prompt=enhanced_prompt, |
|
negative_prompt="blurry, low quality, poorly drawn, distorted" |
|
) |
|
|
|
LOGGER.info(f"Successfully generated image for prompt: {img_prompt[:50]}...") |
|
return result["url"] |
|
|
|
except Exception as e: |
|
LOGGER.error(f"Error generating image: {e}") |
|
raise |
|
|
|
def download_img_from_url(self, image_url: str, image_path: str) -> str: |
|
"""Download and process image from URL.""" |
|
try: |
|
urllib.request.urlretrieve(image_url, image_path) |
|
|
|
|
|
img = Image.open(image_path) |
|
target_size = (1792, 1024) |
|
img = img.resize(target_size, Image.Resampling.LANCZOS) |
|
img.save(image_path, quality=95) |
|
|
|
LOGGER.info(f"Successfully downloaded and processed image: {image_path}") |
|
return image_path |
|
|
|
except Exception as e: |
|
LOGGER.error(f"Error downloading image: {e}") |
|
raise |
|
|
|
def create_video_from_images_and_audio(self, image_files: list, audio_files: list, output_path: str) -> None: |
|
"""Create video with enhanced quality settings.""" |
|
try: |
|
if len(image_files) != len(audio_files): |
|
raise ValueError("Number of images doesn't match number of audio files") |
|
|
|
video_clips = [] |
|
for image_file, audio_file in zip(image_files, audio_files): |
|
audio_clip = mp.AudioFileClip(audio_file) |
|
video_clip = mp.ImageClip(image_file).set_duration(audio_clip.duration) |
|
video_clip = video_clip.set_audio(audio_clip) |
|
video_clips.append(video_clip) |
|
|
|
final_clip = mp.concatenate_videoclips(video_clips) |
|
|
|
|
|
final_clip.write_videofile( |
|
output_path, |
|
codec='libx264', |
|
fps=24, |
|
audio_codec='aac', |
|
audio_bitrate='192k', |
|
preset='medium', |
|
threads=4 |
|
) |
|
|
|
LOGGER.info("Video created successfully") |
|
|
|
except Exception as e: |
|
LOGGER.error(f"Error creating video: {e}") |
|
raise |
|
|
|
|
|
|
|
def gradio_interface(self): |
|
"""Create enhanced Gradio interface.""" |
|
with gr.Blocks(theme='abidlabs/dracula_revamped') as demo: |
|
gr.HTML(""" |
|
<center> |
|
<h1 style="color:#fff">AI Comic Video Generator</h1> |
|
<p style="color:#ddd">Create engaging comic-style videos from your stories</p> |
|
</center> |
|
""") |
|
|
|
with gr.Row(): |
|
input_text = gr.Textbox( |
|
label="Story Script", |
|
placeholder="Enter your story (separate scenes with ,,)", |
|
lines=5 |
|
) |
|
|
|
with gr.Row(): |
|
generate_btn = gr.Button("🎬 Generate Comic Video", variant="primary") |
|
|
|
with gr.Row(): |
|
output = gr.Video(label="Generated Comic Video") |
|
|
|
example_txt = """Once upon a time in a magical forest,, |
|
A brave knight discovered a mysterious crystal,, |
|
The crystal began to glow with incredible power""" |
|
|
|
gr.Examples([[example_txt]], [input_text]) |
|
|
|
generate_btn.click( |
|
self.generate_video, |
|
inputs=[input_text], |
|
outputs=[output] |
|
) |
|
|
|
demo.launch(debug=True) |