| | import requests |
| | import constants |
| | import os |
| | from PIL import Image |
| | from gradio_client import Client |
| | import moviepy.editor as mp |
| | from moviepy.video.VideoClip import ImageClip |
| | from moviepy.editor import AudioFileClip |
| | from structured_output_extractor import StructuredOutputExtractor |
| | from pydantic import BaseModel, Field |
| | from typing import List |
| | import tempfile |
| | import os |
| |
|
| |
|
| | def get_summarization(text: str): |
| | print('\n\nSummarizing text: ', text, type(text)) |
| | |
| | data = {"text_input": text} |
| |
|
| | |
| | headers = {"Authorization": f"Bearer {constants.HF_TOKEN}"} |
| |
|
| | try: |
| | |
| | response = requests.post(constants.SUMMARIZATION_ENDPOINT, json=data, headers=headers) |
| | |
| | if response.status_code == 200: |
| | response_data = response.json() |
| | print("Returning Summarization") |
| | return response_data.get("output", "No output found.") |
| | else: |
| | print("Some Error Occured During Summarization Request") |
| | print(response) |
| | print(f"Error: {response.status_code}, {response.text}") |
| | return {"error_occured" : response.text} |
| | except Exception as e: |
| | print(f"An exception occurred: {e}") |
| | return {"error_occured" : e} |
| | |
| | |
| | def segments_to_chunks(segments): |
| | chunks = [] |
| | for segment in segments: |
| | chunks.append(segment.get("text")) |
| | return chunks |
| | |
| |
|
| | def get_image_prompts(text_input : List, summary): |
| | print(f"summary: {summary}") |
| | |
| | class ImagePromptResponseSchema(BaseModel): |
| | image_prompts: List[str] = Field( |
| | description="List of detailed image prompts, Each Image Prompt Per Chunk" |
| | ) |
| |
|
| | extractor = StructuredOutputExtractor(response_schema=ImagePromptResponseSchema) |
| | chunks_count = len(text_input) |
| | chunks = "chunk: " + "\nchunk: ".join(text_input) |
| | prompt = f""" |
| | ROLE: You are a Highly Experienced Image Prompt Synthesizer |
| | SYSTEM PROMPT: Given the Overall Summary and All Chunks of the Text: |
| | 1. Read the summary and the combined context of all chunks (the entire script). |
| | 2. **Identify the central theme and setting** of the complete text. |
| | 3. For each chunk, examine both the chunk and its summary, then create a **focused, context-aware image prompt** based on key visual elements. |
| | 4. **Ensure thematic consistency across all chunks:** |
| | - The environment, mood, and lighting must remain true to the established theme (e.g., a dark, eerie jungle remains consistently dark and mysterious throughout). |
| | 5. **Keep the image style as 3D (this MUST be followed).** |
| | 6. **Negatives:** Do not include hyper-realistic elements or real-life human depictions, and avoid any out-of-context settings (e.g., a park in a jungle story). |
| | 7. **Use mood-specific lighting and color palettes:** |
| | - For example, if the theme is a dark jungle, use deep greens, blacks, misty blues, and dim moonlight. |
| | - Ensure that all visual elements (fog, shadows, expressions) support the horror/suspense atmosphere. |
| | 8. NEVER generate prompts that could lead to NSFW images or any explicit content. Use safe and appropriate descriptions. |
| | |
| | ### Example: |
| | **Summary:** |
| | This text is a story of a man who ventured into a dark jungle and encountered a mysterious lion. |
| | |
| | **Chunks:** |
| | 1. A man enters the dark jungle, mist swirling around him. |
| | 2. He comes face-to-face with a majestic yet eerie lion. |
| | |
| | **Combined Context:** |
| | "A man ventures into a dense, eerie jungle and unexpectedly meets a mysterious lion." |
| | |
| | **Generated Prompts:** |
| | - **Chunk 1:** |
| | "[style: 3D | theme: dark jungle] A lone man steps into a dense, eerie jungle at twilight. Thick mist swirls around his feet as towering, twisted trees loom overhead. Dim, bluish moonlight filters through the foliage, casting long, haunting shadows." |
| | |
| | - **Chunk 2:** |
| | "[style: 3D | theme: dark jungle] In a clearing within the jungle, a majestic lion appears with an unsettling aura. Its eyes glow faintly in the dim light, and the surrounding trees seem to lean in, enhancing the mysterious tension." |
| | |
| | TASK: Here is the summary: {summary}\n\n and \n\n Total of {chunks_count} chunks, generate an Image Prompt for each chunk\n\n {chunks} |
| | """ |
| | result = extractor.extract(prompt) |
| | return result.model_dump() |
| | |
| | |
| |
|
| |
|
| |
|
| | def generate_image(prompt, path='test_image.png'): |
| | try: |
| | |
| | client = Client(constants.IMAGE_GENERATION_SPACE_NAME, hf_token=constants.HF_TOKEN) |
| |
|
| | |
| | result = client.predict( |
| | param_0=prompt, |
| | api_name="/predict" |
| | ) |
| |
|
| | image = Image.open(result) |
| | image.save(path) |
| |
|
| | |
| | return result |
| |
|
| | except Exception as e: |
| | print(f"Error during image generation: {e}") |
| | return {"error": str(e)} |
| | |
| | def generate_images(image_prompts, folder_name='test_folder'): |
| | folder_path = tmp_folder(folder_name) |
| | for index, prompt in enumerate(image_prompts): |
| | print(index, prompt) |
| | image_path = generate_image(prompt=prompt, path=f"{folder_path}/{index}.png") |
| | yield prompt, image_path |
| | |
| |
|
| |
|
| | def tmp_folder(folder_name: str) -> str: |
| | |
| | base_tmp_path = os.path.join(os.getcwd(), "tmp_dir") |
| | |
| | |
| | if not os.path.exists(base_tmp_path): |
| | os.makedirs(base_tmp_path) |
| | print(f"Base temporary folder '{base_tmp_path}' created.") |
| | |
| | |
| | folder_path = os.path.join(base_tmp_path, folder_name) |
| | |
| | |
| | os.makedirs(folder_path, exist_ok=True) |
| | |
| | print(f"Temporary folder '{folder_name}' is ready at {folder_path}.") |
| | |
| | return folder_path |
| |
|
| |
|
| |
|
| | from moviepy.editor import * |
| |
|
| |
|
| | import os |
| | import tempfile |
| | from moviepy.editor import AudioFileClip, ImageClip, concatenate_videoclips |
| |
|
| |
|
| | def generate_video(audio_file, images, segments): |
| | try: |
| | video_dir = "./generated_videos" |
| | os.makedirs(video_dir, exist_ok=True) |
| |
|
| | file_extension = os.path.splitext(audio_file.name)[1] |
| | temp_audio_path = tempfile.NamedTemporaryFile(delete=False, suffix=f"{file_extension}") |
| | temp_audio_path.write(audio_file.read()) |
| | temp_audio_path.close() |
| |
|
| | audio = AudioFileClip(temp_audio_path.name) |
| |
|
| | frame_width = 1280 |
| | frame_height = 720 |
| |
|
| | video_clips = [] |
| | total_segments = len(segments) |
| | for i, current_segment in enumerate(segments): |
| | start_time = current_segment["start"] |
| | end_time = current_segment["end"] |
| |
|
| | if i < total_segments - 1: |
| | next_segment = segments[i + 1] |
| | actual_end_time = next_segment["start"] |
| | else: |
| | actual_end_time = end_time |
| |
|
| | segment_duration = actual_end_time - start_time |
| |
|
| | image_path = images[min(i, len(images) - 1)] |
| |
|
| | image_clip = ImageClip(image_path) |
| | image_clip = image_clip.resize(height=frame_height).on_color( |
| | size=(frame_width, frame_height), |
| | color=(0, 0, 0), |
| | pos="center" |
| | ) |
| |
|
| | image_clip = image_clip.set_duration(segment_duration).set_start(start_time) |
| | video_clips.append(image_clip) |
| |
|
| | video = concatenate_videoclips(video_clips, method="compose") |
| | video = video.set_audio(audio) |
| |
|
| | video_filename = f"generated_video_{uuid.uuid4().hex}.mp4" |
| | video_path = os.path.join(video_dir, video_filename) |
| |
|
| | video.write_videofile(video_path, fps=30, codec="libx264", audio_codec="aac") |
| | os.remove(temp_audio_path.name) |
| |
|
| | return video_path |
| |
|
| | except Exception as e: |
| | print(f"Error generating video: {e}") |
| | return None |