SparrowTale / app.py
abhinav0231's picture
Update app.py
eb6e516 verified
import subprocess
import sys
# Install spaCy model
def ensure_spacy():
try:
import spacy
spacy.load("en_core_web_sm")
except:
subprocess.run([sys.executable, "-m", "spacy", "download", "en_core_web_sm"])
ensure_spacy()
import streamlit as st
import os
import time
import glob
from llm import generate_story
from chunker import process_story_for_multimedia, save_multimedia_data
from image_generation import generate_all_images_from_file
from tts import generate_all_audio_from_file
from movie import Video
# --- Page Configuration ---
st.set_page_config(
page_title="Smart Cultural Storyteller",
page_icon="🎬",
layout="wide",
initial_sidebar_state="collapsed"
)
# --- Helper Functions ---
def cleanup_files():
"""Removes old generated files to keep the space clean for a new run."""
print("--- Cleaning up old files... ---")
# Directories for generated assets
for directory in ["generated_images", "generated_audio", "temp_uploads"]:
if os.path.exists(directory):
for f in glob.glob(os.path.join(directory, '*.*')):
try:
os.remove(f)
except OSError as e:
st.error(f"Error removing file {f}: {e}")
# JSON files, temp files, and final video from the root directory
for f in glob.glob("multimedia_*.json") + glob.glob("temp_*.*") + glob.glob("*.mp4"):
if os.path.exists(f):
os.remove(f)
# --- UI Layout ---
st.title("SparrowTale - 🎬 Smart Cultural Storyteller")
st.markdown("Craft beautiful, culturally rich stories with the power of AI. Provide a prompt, upload a document or audio, and watch your story come to life!")
# Use session state to store the video path and prevent re-runs
if 'video_path' not in st.session_state:
st.session_state.video_path = None
# Center the main content for a cleaner look
col1, col2, col3 = st.columns([1, 3, 1])
with col2:
with st.container(border=True):
# Input widgets
user_prompt = st.text_area("πŸ“ **Enter your story idea...**", height=150, placeholder="A wise old turtle who teaches a village about patience...")
col_style, col_gender = st.columns(2)
with col_style:
story_style = st.selectbox(
"🎨 **Choose a Story Style**",
("Mythical & Folklore", "Historical & Realistic", "Futuristic & Sci-Fi", "Ancient Indian Knowledge")
)
with col_gender:
gender = st.selectbox(
"πŸ—£οΈ **Choose a Narrator Voice**",
("Female", "Male")
)
# File and Audio Uploaders
doc_file = st.file_uploader("πŸ“„ **Upload a document for context (optional)**", type=['txt', 'pdf'])
audio_file = st.file_uploader("🎀 **Upload an audio prompt (optional)**", type=['wav', 'mp3'])
# Generate Button
generate_button = st.button("✨ **Generate Story Video**", use_container_width=True, type="primary")
# --- Generation Logic ---
if generate_button:
# Validate inputs
if not user_prompt and not doc_file and not audio_file:
st.error("Please provide a story idea, a document, or an audio prompt to begin.")
else:
# 1. Cleanup previous run's files
cleanup_files()
st.session_state.video_path = None # Reset video path
# 2. Handle file uploads
doc_path, audio_path = None, None
temp_dir = "temp_uploads"
os.makedirs(temp_dir, exist_ok=True)
if doc_file:
doc_path = os.path.join(temp_dir, doc_file.name)
with open(doc_path, "wb") as f:
f.write(doc_file.getbuffer())
if audio_file:
audio_path = os.path.join(temp_dir, audio_file.name)
with open(audio_path, "wb") as f:
f.write(audio_file.getbuffer())
st.info("Audio file uploaded. The text prompt will be ignored.")
user_prompt = "Transcribe and use the story from the audio file."
# 3. Main generation pipeline
with st.spinner("This might take a few minutes... The AI is dreaming up your story... πŸŒ™"):
progress_bar = st.progress(0, text="Initializing...")
try:
# A. Generate the story text
progress_bar.progress(5, text="Step 1/5: Generating the story script...")
story_text = generate_story(user_prompt, story_style, audio_path, doc_path)
# B. Chunk the story
progress_bar.progress(20, text="Step 2/5: Designing the storyboard...")
multimedia_data = process_story_for_multimedia(story_text)
save_multimedia_data(multimedia_data, "multimedia_data.json")
# C. Generate images
progress_bar.progress(40, text="Step 3/5: Painting the scenes...")
generate_all_images_from_file("multimedia_data.json", output_json_path="multimedia_data_with_images.json")
# D. Generate audio narration
progress_bar.progress(60, text="Step 4/5: Recording the narration...")
generate_all_audio_from_file(
"multimedia_data_with_images.json",
target_language="English", # This could be made a dropdown too
gender=gender.lower(),
output_json_path="multimedia_data_final.json"
)
# E. Stitch everything into a video using your optimized class
progress_bar.progress(80, text="Step 5/5: Directing the final movie...")
video_creator = Video()
final_video_path = "story_video.mp4"
success = video_creator.create_video_from_json(
"multimedia_data_final.json",
output_filename=final_video_path
)
if success:
st.session_state.video_path = final_video_path
progress_bar.progress(100, text="Completed!")
st.success("Your story video has been created!")
else:
st.error("Video creation failed. Please check the logs.")
except Exception as e:
st.error(f"An unexpected error occurred: {e}")
# Display the video if it has been generated
if st.session_state.video_path and os.path.exists(st.session_state.video_path):
st.video(st.session_state.video_path)
with open(st.session_state.video_path, "rb") as file:
st.download_button(
label="πŸ“₯ **Download Video**",
data=file,
file_name="my_story_video.mp4",
mime="video/mp4",
use_container_width=True
)
# --- Footer ---
st.markdown("---")
st.markdown("Built with ❀️ by Abhinav")