Spaces:
Sleeping
Sleeping
import gradio as gr | |
from langchain.llms import OpenAI as LangChainOpenAI | |
from langchain.prompts import PromptTemplate | |
from langchain.chains import LLMChain | |
from openai import OpenAI | |
import os | |
import re | |
from pathlib import Path | |
from moviepy.editor import * | |
import requests | |
import tempfile | |
# Initialize OpenAI client | |
client = OpenAI() | |
# Create a prompt template | |
template = """ | |
You are a creative story writer. Given a topic, write a short story of about 150 words. | |
Divide the story into 3 paragraphs. Each paragraph should be a distinct part of the story. | |
Topic: {topic} | |
Story: | |
""" | |
prompt = PromptTemplate(template=template, input_variables=["topic"]) | |
# Create an LLMChain | |
llm = LangChainOpenAI(temperature=0.7) | |
story_chain = LLMChain(llm=llm, prompt=prompt) | |
def generate_image(prompt): | |
try: | |
response = client.images.generate( | |
model="dall-e-3", | |
prompt=prompt, | |
size="1024x1024", | |
quality="standard", | |
n=1, | |
) | |
return response.data[0].url | |
except Exception as e: | |
print(f"Error generating image: {e}") | |
return None | |
def generate_speech(text, filename): | |
try: | |
response = client.audio.speech.create( | |
model="tts-1", | |
voice="alloy", | |
input=text | |
) | |
response.stream_to_file(filename) | |
return filename | |
except Exception as e: | |
print(f"Error generating speech: {e}") | |
return None | |
def download_image(url, filename): | |
try: | |
response = requests.get(url) | |
with open(filename, 'wb') as f: | |
f.write(response.content) | |
return filename | |
except Exception as e: | |
print(f"Error downloading image: {e}") | |
return None | |
def create_video(paragraphs, image_files, audio_files, output_file): | |
clips = [] | |
for paragraph, image_file, audio_file in zip(paragraphs, image_files, audio_files): | |
try: | |
audio_clip = AudioFileClip(audio_file) if audio_file else None | |
duration = audio_clip.duration if audio_clip else 5 # Default duration if no audio | |
if image_file: | |
image_clip = ImageClip(image_file).set_duration(duration) | |
else: | |
image_clip = ColorClip(size=(1024, 1024), color=(0,0,0)).set_duration(duration) | |
text_clip = TextClip(paragraph, fontsize=30, color='white', bg_color='black', | |
size=(1024, 200), method='caption').set_position(('center', 'bottom')).set_duration(duration) | |
composite_clip = CompositeVideoClip([image_clip, text_clip]) | |
if audio_clip: | |
composite_clip = composite_clip.set_audio(audio_clip) | |
clips.append(composite_clip) | |
except Exception as e: | |
print(f"Error creating clip: {e}") | |
if clips: | |
final_clip = concatenate_videoclips(clips) | |
final_clip.write_videofile(output_file, fps=24) | |
return output_file | |
return None | |
def generate_story_with_video(topic): | |
try: | |
# Generate the story | |
story = story_chain.run(topic) | |
except Exception as e: | |
print(f"Error generating story: {e}") | |
story = "Failed to generate story." | |
# Split the story into paragraphs | |
paragraphs = re.split(r'\n\n', story.strip()) | |
# Ensure we have exactly 3 paragraphs | |
paragraphs = paragraphs[:3] | |
while len(paragraphs) < 3: | |
paragraphs.append("...") | |
temp_dir = tempfile.mkdtemp() | |
image_files = [] | |
audio_files = [] | |
for i, paragraph in enumerate(paragraphs): | |
# Generate and download image | |
image_url = generate_image(paragraph) | |
if image_url: | |
image_file = os.path.join(temp_dir, f"image_{i}.png") | |
image_files.append(download_image(image_url, image_file)) | |
else: | |
image_files.append(None) | |
# Generate audio | |
audio_file = os.path.join(temp_dir, f"audio_{i}.mp3") | |
audio_files.append(generate_speech(paragraph, audio_file)) | |
# Create video | |
output_file = os.path.join(temp_dir, "story_video.mp4") | |
video_file = create_video(paragraphs, image_files, audio_files, output_file) | |
# Read the video file if it was created | |
video_data = None | |
if video_file and os.path.exists(video_file): | |
with open(video_file, "rb") as f: | |
video_data = f.read() | |
return story, video_data, image_files, audio_files | |
# Create the Gradio interface | |
def gradio_interface(topic): | |
story, video_data, image_files, audio_files = generate_story_with_video(topic) | |
outputs = [story] | |
if video_data: | |
outputs.append(video_data) | |
else: | |
outputs.append(None) | |
outputs.append("Failed to generate video.") | |
for i in range(3): | |
if i < len(image_files) and image_files[i]: | |
outputs.append(image_files[i]) | |
else: | |
outputs.append(None) | |
if i < len(audio_files) and audio_files[i]: | |
outputs.append(audio_files[i]) | |
else: | |
outputs.append(None) | |
return outputs | |
iface = gr.Interface( | |
fn=gradio_interface, | |
inputs=gr.Textbox(lines=2, placeholder="Enter a topic for the story..."), | |
outputs=[ | |
gr.Textbox(label="Generated Story"), | |
gr.Video(label="Story Video"), | |
gr.Image(label="Image 1", type="filepath"), | |
gr.Audio(label="Audio 1", type="filepath"), | |
gr.Image(label="Image 2", type="filepath"), | |
gr.Audio(label="Audio 2", type="filepath"), | |
gr.Image(label="Image 3", type="filepath"), | |
gr.Audio(label="Audio 3", type="filepath"), | |
], | |
title="Story Generator with Video, Images, and Audio", | |
description="Enter a topic, and the AI will generate a short story with a video, images, and audio narration. If any part fails, you'll still see the successful parts." | |
) | |
# Launch the Gradio app | |
iface.launch() |