File size: 7,201 Bytes
9147834
 
 
 
 
cc2ec1c
9147834
cc2ec1c
9147834
 
 
 
cc2ec1c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
db06c0a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
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")