Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,15 +1,12 @@
|
|
| 1 |
import streamlit as st
|
| 2 |
-
import requests
|
| 3 |
-
import io
|
| 4 |
-
from PIL import Image
|
| 5 |
import time
|
|
|
|
| 6 |
|
| 7 |
# Page config
|
| 8 |
st.set_page_config(
|
| 9 |
page_title="StoryVision AI",
|
| 10 |
page_icon="π",
|
| 11 |
-
layout="wide"
|
| 12 |
-
initial_sidebar_state="expanded"
|
| 13 |
)
|
| 14 |
|
| 15 |
# Custom CSS
|
|
@@ -20,7 +17,6 @@ st.markdown("""
|
|
| 20 |
color: #FF6B6B;
|
| 21 |
text-align: center;
|
| 22 |
margin-bottom: 2rem;
|
| 23 |
-
text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
|
| 24 |
}
|
| 25 |
.story-container {
|
| 26 |
background-color: #f8f9fa;
|
|
@@ -29,30 +25,12 @@ st.markdown("""
|
|
| 29 |
border-left: 5px solid #FF6B6B;
|
| 30 |
margin: 1rem 0;
|
| 31 |
}
|
| 32 |
-
.image-container {
|
| 33 |
-
border-radius: 15px;
|
| 34 |
-
overflow: hidden;
|
| 35 |
-
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
|
| 36 |
-
}
|
| 37 |
-
.stButton > button {
|
| 38 |
-
background: linear-gradient(45deg, #FF6B6B, #4ECDC4);
|
| 39 |
-
color: white;
|
| 40 |
-
border: none;
|
| 41 |
-
padding: 0.5rem 2rem;
|
| 42 |
-
border-radius: 25px;
|
| 43 |
-
font-weight: bold;
|
| 44 |
-
transition: all 0.3s;
|
| 45 |
-
}
|
| 46 |
-
.stButton > button:hover {
|
| 47 |
-
transform: translateY(-2px);
|
| 48 |
-
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
|
| 49 |
-
}
|
| 50 |
</style>
|
| 51 |
""", unsafe_allow_html=True)
|
| 52 |
|
| 53 |
# Header
|
| 54 |
st.markdown('<h1 class="main-header">π StoryVision AI</h1>', unsafe_allow_html=True)
|
| 55 |
-
st.markdown('<p style="text-align: center; font-size: 1.2rem; color: #666;">Create magical stories with
|
| 56 |
|
| 57 |
# Sidebar controls
|
| 58 |
st.sidebar.markdown("## π¨ Story Settings")
|
|
@@ -63,6 +41,8 @@ genre = st.sidebar.selectbox(
|
|
| 63 |
)
|
| 64 |
|
| 65 |
protagonist = st.sidebar.text_input("Main character name:", placeholder="e.g., Luna the brave")
|
|
|
|
|
|
|
| 66 |
|
| 67 |
setting = st.sidebar.selectbox(
|
| 68 |
"Setting:",
|
|
@@ -70,45 +50,78 @@ setting = st.sidebar.selectbox(
|
|
| 70 |
"Underwater Kingdom", "Flying City", "Desert Oasis", "Mountain Village"]
|
| 71 |
)
|
| 72 |
|
| 73 |
-
story_length = st.sidebar.slider("Story length:", 50, 300, 150)
|
| 74 |
-
|
| 75 |
art_style = st.sidebar.selectbox(
|
| 76 |
"Art style:",
|
| 77 |
-
["Fantasy Art", "Digital Painting", "Watercolor", "Anime Style", "Photorealistic"
|
| 78 |
)
|
| 79 |
|
| 80 |
-
#
|
| 81 |
-
|
| 82 |
-
""
|
| 83 |
-
|
|
|
|
|
|
|
|
|
|
| 84 |
|
| 85 |
-
|
| 86 |
-
|
|
|
|
|
|
|
|
|
|
| 87 |
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
"Fantasy": f"In the mystical realm of {setting}, {protagonist} discovered an ancient artifact that glowed with ethereal light. As they touched it, magical energies swirled around them, transporting them to a world where dragons soared through crystal skies and unicorns grazed in fields of silver grass. {protagonist} realized they were chosen to restore balance to this magical world, facing challenges that would test not only their courage but their heart.",
|
| 91 |
|
| 92 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
|
| 94 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 95 |
|
| 96 |
-
"
|
| 97 |
-
|
| 98 |
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
|
| 105 |
# Main app
|
| 106 |
col1, col2 = st.columns([1, 1])
|
| 107 |
|
| 108 |
-
if st.button("β¨ Generate Story & Art",
|
| 109 |
with st.spinner("π Crafting your story..."):
|
| 110 |
-
story = generate_story(genre, protagonist, setting
|
| 111 |
-
time.sleep(2) # Simulate processing
|
| 112 |
|
| 113 |
with col1:
|
| 114 |
st.markdown("### π Your Story")
|
|
@@ -120,84 +133,94 @@ if st.button("β¨ Generate Story & Art", key="generate"):
|
|
| 120 |
|
| 121 |
st.markdown(f"""
|
| 122 |
**Story Stats:**
|
| 123 |
-
- Words
|
| 124 |
-
-
|
| 125 |
-
- Genre
|
| 126 |
-
- Setting
|
| 127 |
""")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 128 |
|
| 129 |
with col2:
|
| 130 |
-
st.markdown("### π¨
|
| 131 |
|
| 132 |
-
with st.spinner("π¨ Creating artwork..."):
|
| 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 |
-
col3, col4, col5 = st.columns(3)
|
| 159 |
-
|
| 160 |
-
with col3:
|
| 161 |
-
if st.button("π Save Story"):
|
| 162 |
-
st.success("Story saved to your collection!")
|
| 163 |
-
|
| 164 |
-
with col4:
|
| 165 |
-
if st.button("π Regenerate Story"):
|
| 166 |
-
st.info("Generating new version...")
|
| 167 |
-
|
| 168 |
-
with col5:
|
| 169 |
-
if st.button("π¨ New Art Style"):
|
| 170 |
-
st.info("Creating new artwork...")
|
| 171 |
|
| 172 |
-
#
|
| 173 |
st.markdown("---")
|
| 174 |
-
st.
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 180 |
|
| 181 |
# Sidebar info
|
| 182 |
st.sidebar.markdown("---")
|
| 183 |
-
st.sidebar.markdown("### π About")
|
| 184 |
st.sidebar.info("""
|
| 185 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 186 |
|
| 187 |
-
**
|
| 188 |
-
- Multiple genres & settings
|
| 189 |
-
- Customizable characters
|
| 190 |
-
- AI-generated artwork
|
| 191 |
-
- Story statistics
|
| 192 |
-
- Export options
|
| 193 |
-
|
| 194 |
-
**Tech Stack:**
|
| 195 |
- Streamlit
|
| 196 |
-
-
|
| 197 |
-
-
|
|
|
|
| 198 |
""")
|
| 199 |
|
| 200 |
-
|
| 201 |
-
st.sidebar.
|
| 202 |
-
st.sidebar.metric("
|
| 203 |
-
st.sidebar.metric("
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import streamlit as st
|
|
|
|
|
|
|
|
|
|
| 2 |
import time
|
| 3 |
+
import random
|
| 4 |
|
| 5 |
# Page config
|
| 6 |
st.set_page_config(
|
| 7 |
page_title="StoryVision AI",
|
| 8 |
page_icon="π",
|
| 9 |
+
layout="wide"
|
|
|
|
| 10 |
)
|
| 11 |
|
| 12 |
# Custom CSS
|
|
|
|
| 17 |
color: #FF6B6B;
|
| 18 |
text-align: center;
|
| 19 |
margin-bottom: 2rem;
|
|
|
|
| 20 |
}
|
| 21 |
.story-container {
|
| 22 |
background-color: #f8f9fa;
|
|
|
|
| 25 |
border-left: 5px solid #FF6B6B;
|
| 26 |
margin: 1rem 0;
|
| 27 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
</style>
|
| 29 |
""", unsafe_allow_html=True)
|
| 30 |
|
| 31 |
# Header
|
| 32 |
st.markdown('<h1 class="main-header">π StoryVision AI</h1>', unsafe_allow_html=True)
|
| 33 |
+
st.markdown('<p style="text-align: center; font-size: 1.2rem; color: #666;">Create magical stories with AI-generated artwork!</p>', unsafe_allow_html=True)
|
| 34 |
|
| 35 |
# Sidebar controls
|
| 36 |
st.sidebar.markdown("## π¨ Story Settings")
|
|
|
|
| 41 |
)
|
| 42 |
|
| 43 |
protagonist = st.sidebar.text_input("Main character name:", placeholder="e.g., Luna the brave")
|
| 44 |
+
if not protagonist:
|
| 45 |
+
protagonist = "The Hero"
|
| 46 |
|
| 47 |
setting = st.sidebar.selectbox(
|
| 48 |
"Setting:",
|
|
|
|
| 50 |
"Underwater Kingdom", "Flying City", "Desert Oasis", "Mountain Village"]
|
| 51 |
)
|
| 52 |
|
|
|
|
|
|
|
| 53 |
art_style = st.sidebar.selectbox(
|
| 54 |
"Art style:",
|
| 55 |
+
["Fantasy Art", "Digital Painting", "Watercolor", "Anime Style", "Photorealistic"]
|
| 56 |
)
|
| 57 |
|
| 58 |
+
# Story templates
|
| 59 |
+
STORY_TEMPLATES = {
|
| 60 |
+
"Fantasy": [
|
| 61 |
+
"In the mystical realm of {setting}, {protagonist} discovered an ancient artifact that pulsed with magical energy. As whispers of forgotten spells filled the air, they realized their destiny was far greater than they ever imagined. Dragons soared overhead while mystical creatures watched from the shadows, all waiting to see if {protagonist} would embrace their newfound power or be consumed by it.",
|
| 62 |
+
|
| 63 |
+
"The {setting} had always been a place of wonder, but when {protagonist} stepped through the shimmering portal, everything changed. Magic flowed through their veins as they encountered beings of legend. With a prophecy to fulfill and dark forces gathering, {protagonist} must master ancient arts before the realm falls to eternal darkness."
|
| 64 |
+
],
|
| 65 |
|
| 66 |
+
"Sci-Fi": [
|
| 67 |
+
"Captain {protagonist} gazed at the vast expanse of {setting} through the viewport. The year 2387 had brought humanity to the stars, but nothing could have prepared them for what they found. An alien signal, a mysterious technology, and a discovery that would rewrite the laws of physics. {protagonist} knew that first contact would change everything.",
|
| 68 |
+
|
| 69 |
+
"In the depths of {setting}, {protagonist} uncovered technology that defied explanation. Quantum computers hummed with alien algorithms while holographic displays showed star maps of unknown galaxies. As reality itself began to shift, {protagonist} realized they were part of an experiment that spanned millennia."
|
| 70 |
+
],
|
| 71 |
|
| 72 |
+
"Mystery": [
|
| 73 |
+
"Detective {protagonist} arrived at {setting} as fog rolled through the streets. The crime scene was unlike anything they'd encountered - a locked room, no witnesses, and only a cryptic symbol carved into the wall. As {protagonist} pieced together the clues, they discovered a conspiracy that reached the highest levels of power.",
|
|
|
|
| 74 |
|
| 75 |
+
"The {setting} held secrets that {protagonist} was determined to uncover. Each clue led to more questions, each witness told a different story. In a web of lies and deception, {protagonist} raced against time to solve a mystery that threatened to destroy everything they held dear."
|
| 76 |
+
],
|
| 77 |
+
|
| 78 |
+
"Adventure": [
|
| 79 |
+
"{protagonist} clutched the weathered map as they ventured into {setting}. Legend spoke of a treasure beyond imagination, but the path was fraught with danger. Ancient traps, rival treasure hunters, and the unforgiving environment tested every skill {protagonist} possessed. Victory would mean glory, but failure meant certain doom.",
|
| 80 |
|
| 81 |
+
"The call of adventure echoed through {setting} as {protagonist} embarked on a journey that would test their limits. With only their wits and courage, they faced challenges that seemed impossible. Each step forward brought new dangers, but also the promise of discoveries that would change their life forever."
|
| 82 |
+
],
|
| 83 |
+
|
| 84 |
+
"Romance": [
|
| 85 |
+
"In the enchanting {setting}, {protagonist} never expected to find love. But when fate intervened, bringing two hearts together against all odds, magic seemed to fill the air. Through misunderstandings and moments of pure joy, {protagonist} discovered that true love was worth fighting for, no matter the obstacles.",
|
| 86 |
|
| 87 |
+
"The {setting} became the backdrop for an unexpected romance as {protagonist} met someone who challenged everything they believed about love. Through stolen glances and heartfelt conversations, a connection formed that transcended all boundaries."
|
| 88 |
+
],
|
| 89 |
|
| 90 |
+
"Horror": [
|
| 91 |
+
"The {setting} was supposed to be abandoned, but {protagonist} could feel eyes watching from the shadows. Strange sounds echoed through empty corridors while an oppressive darkness seemed to consume all light. As reality began to blur with nightmare, {protagonist} realized some places are abandoned for very good reasons.",
|
| 92 |
+
|
| 93 |
+
"Something was terribly wrong in {setting}. {protagonist} felt it the moment they arrived - a creeping dread that seemed to seep from the very walls. As night fell and the true horror revealed itself, {protagonist} discovered that some evils are better left undisturbed."
|
| 94 |
+
],
|
| 95 |
+
|
| 96 |
+
"Comedy": [
|
| 97 |
+
"Everything that could go wrong did go wrong when {protagonist} found themselves in {setting}. From mistaken identities to slapstick mishaps, their simple plan had turned into a comedy of errors. With each attempt to fix things only making them worse, {protagonist} learned that sometimes you just have to laugh at life's absurdities.",
|
| 98 |
+
|
| 99 |
+
"The {setting} was the perfect place for chaos, and {protagonist} seemed to be a magnet for it. Ridiculous situations, eccentric characters, and perfectly timed misunderstandings created a whirlwind of hilarity that {protagonist} would never forget."
|
| 100 |
+
]
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
def generate_story(genre, protagonist, setting):
|
| 104 |
+
"""Generate a story based on the selected parameters"""
|
| 105 |
+
templates = STORY_TEMPLATES.get(genre, STORY_TEMPLATES["Fantasy"])
|
| 106 |
+
template = random.choice(templates)
|
| 107 |
+
return template.format(protagonist=protagonist, setting=setting)
|
| 108 |
+
|
| 109 |
+
def generate_art_description(protagonist, setting, art_style):
|
| 110 |
+
"""Generate artwork description"""
|
| 111 |
+
descriptions = [
|
| 112 |
+
f"A magnificent {art_style.lower()} depicting {protagonist} standing heroically in {setting}, with dramatic lighting and rich, vibrant colors",
|
| 113 |
+
f"Beautiful {art_style.lower()} artwork showing {protagonist} in {setting}, featuring intricate details and atmospheric mood",
|
| 114 |
+
f"Stunning {art_style.lower()} illustration of {protagonist} exploring {setting}, with cinematic composition and masterful use of light and shadow"
|
| 115 |
+
]
|
| 116 |
+
return random.choice(descriptions)
|
| 117 |
|
| 118 |
# Main app
|
| 119 |
col1, col2 = st.columns([1, 1])
|
| 120 |
|
| 121 |
+
if st.button("β¨ Generate Story & Art", type="primary"):
|
| 122 |
with st.spinner("π Crafting your story..."):
|
| 123 |
+
story = generate_story(genre, protagonist, setting)
|
| 124 |
+
time.sleep(2) # Simulate processing
|
| 125 |
|
| 126 |
with col1:
|
| 127 |
st.markdown("### π Your Story")
|
|
|
|
| 133 |
|
| 134 |
st.markdown(f"""
|
| 135 |
**Story Stats:**
|
| 136 |
+
- **Words:** {word_count}
|
| 137 |
+
- **Reading time:** {reading_time} min
|
| 138 |
+
- **Genre:** {genre}
|
| 139 |
+
- **Setting:** {setting}
|
| 140 |
""")
|
| 141 |
+
|
| 142 |
+
# Download button
|
| 143 |
+
st.download_button(
|
| 144 |
+
label="π₯ Download Story",
|
| 145 |
+
data=story,
|
| 146 |
+
file_name=f"{protagonist.replace(' ', '_')}_story.txt",
|
| 147 |
+
mime="text/plain"
|
| 148 |
+
)
|
| 149 |
|
| 150 |
with col2:
|
| 151 |
+
st.markdown("### π¨ Artwork Concept")
|
| 152 |
|
| 153 |
+
with st.spinner("π¨ Creating artwork concept..."):
|
| 154 |
+
time.sleep(1)
|
| 155 |
+
art_description = generate_art_description(protagonist, setting, art_style)
|
| 156 |
+
|
| 157 |
+
# Artistic placeholder
|
| 158 |
+
colors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4", "#FECA57", "#FF9FF3"]
|
| 159 |
+
bg_color = random.choice(colors)
|
| 160 |
+
|
| 161 |
+
st.markdown(
|
| 162 |
+
f"""
|
| 163 |
+
<div style="background: linear-gradient(135deg, {bg_color}, {random.choice(colors)});
|
| 164 |
+
height: 250px; border-radius: 15px; display: flex;
|
| 165 |
+
align-items: center; justify-content: center; color: white;
|
| 166 |
+
font-size: 1.2rem; text-align: center; margin: 1rem 0;
|
| 167 |
+
box-shadow: 0 4px 15px rgba(0,0,0,0.2);">
|
| 168 |
+
π¨<br><strong>AI Artwork</strong><br><small>Generated Here</small>
|
| 169 |
+
</div>
|
| 170 |
+
""",
|
| 171 |
+
unsafe_allow_html=True
|
| 172 |
+
)
|
| 173 |
+
|
| 174 |
+
st.markdown(f"**Art Description:** {art_description}")
|
| 175 |
+
st.markdown(f"**Style:** {art_style}")
|
| 176 |
+
|
| 177 |
+
st.info("π‘ **Coming Soon:** Integration with DALL-E, Stable Diffusion, or Midjourney for actual image generation!")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 178 |
|
| 179 |
+
# Action buttons
|
| 180 |
st.markdown("---")
|
| 181 |
+
col3, col4, col5 = st.columns(3)
|
| 182 |
+
|
| 183 |
+
with col3:
|
| 184 |
+
if st.button("π New Story"):
|
| 185 |
+
st.rerun()
|
| 186 |
+
|
| 187 |
+
with col4:
|
| 188 |
+
if st.button("π² Random Settings"):
|
| 189 |
+
st.session_state.random_generate = True
|
| 190 |
+
st.rerun()
|
| 191 |
+
|
| 192 |
+
with col5:
|
| 193 |
+
if st.button("πΎ Save Favorite"):
|
| 194 |
+
st.success("β
Added to favorites!")
|
| 195 |
|
| 196 |
# Sidebar info
|
| 197 |
st.sidebar.markdown("---")
|
| 198 |
+
st.sidebar.markdown("### π About StoryVision AI")
|
| 199 |
st.sidebar.info("""
|
| 200 |
+
π― **What it does:**
|
| 201 |
+
- Generates creative stories
|
| 202 |
+
- Creates art concepts
|
| 203 |
+
- Multiple genres & styles
|
| 204 |
+
- Instant results
|
| 205 |
|
| 206 |
+
π οΈ **Built with:**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 207 |
- Streamlit
|
| 208 |
+
- Python
|
| 209 |
+
- Creative algorithms
|
| 210 |
+
- Love for storytelling β€οΈ
|
| 211 |
""")
|
| 212 |
|
| 213 |
+
# Usage stats
|
| 214 |
+
st.sidebar.markdown("### π App Stats")
|
| 215 |
+
st.sidebar.metric("Stories Created", f"{random.randint(1200, 1500):,}")
|
| 216 |
+
st.sidebar.metric("Happy Users", f"{random.randint(300, 500)}")
|
| 217 |
+
st.sidebar.metric("Genres Available", "7")
|
| 218 |
+
|
| 219 |
+
# Footer
|
| 220 |
+
st.markdown("---")
|
| 221 |
+
st.markdown("""
|
| 222 |
+
<div style="text-align: center; color: #666; padding: 2rem;">
|
| 223 |
+
<p>π <strong>StoryVision AI</strong> - Where imagination meets technology</p>
|
| 224 |
+
<p>Made with β€οΈ using Streamlit | Perfect for π€ Hugging Face Spaces</p>
|
| 225 |
+
</div>
|
| 226 |
+
""", unsafe_allow_html=True)
|