slliac commited on
Commit
aaf5130
ยท
verified ยท
1 Parent(s): bc49e86

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +194 -138
app.py CHANGED
@@ -53,210 +53,266 @@ def text2audio(text):
53
  return None
54
 
55
 
56
- # Apply custom CSS for kid-friendly UI
57
- st.set_page_config(page_title="Magic Picture Storyteller", page_icon="๐Ÿง™โ€โ™‚๏ธ")
58
 
59
  st.markdown("""
60
  <style>
61
- /* Colorful, rounded child-friendly design */
62
- @import url('https://fonts.googleapis.com/css2?family=Comic+Neue:wght@700&display=swap');
 
 
 
 
 
 
 
 
 
 
63
 
64
  .stApp {
65
- background: linear-gradient(135deg, #ffcce6, #b3ecff);
66
- font-family: 'Comic Neue', cursive;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  }
68
 
69
  h1 {
70
- color: #6a3e8c;
71
  font-size: 2.5rem;
72
  text-align: center;
73
- text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
74
- background: rgba(255,255,255,0.7);
75
- padding: 15px;
76
- border-radius: 20px;
77
- margin-bottom: 20px;
78
- border: 3px dashed #ff9933;
79
  }
80
 
81
- .uploadfile {
82
- background: rgba(255,255,255,0.7);
83
- padding: 20px;
84
- border-radius: 20px;
85
- border: 3px solid #ff6b6b;
86
- margin-bottom: 20px;
87
  }
88
 
89
- /* Align play button to the right */
90
- .play-button-container {
91
- display: flex;
92
- justify-content: flex-end;
93
- margin: 15px 0;
94
  }
95
 
96
- .stButton > button {
97
- background-color: #6adb9d;
98
- color: white;
99
- font-size: 1.5rem;
100
- border-radius: 30px;
101
- padding: 10px 25px;
102
- font-family: 'Comic Neue', cursive;
103
- font-weight: bold;
104
- border: none;
105
- box-shadow: 0 4px 0 #489d73;
106
- transition: all 0.2s;
107
  }
108
 
109
- .stButton > button:hover {
110
- background-color: #5bc28d;
111
- transform: translateY(2px);
112
- box-shadow: 0 2px 0 #489d73;
 
 
 
113
  }
114
 
115
- .stButton > button:active {
116
- transform: translateY(4px);
117
- box-shadow: none;
118
  }
119
 
120
- .output-box {
121
- background: rgba(255, 255, 255, 0.8);
122
- padding: 15px;
123
- border-radius: 20px;
124
- margin: 15px 0;
125
- border: 3px solid #7678ed;
126
  }
127
 
128
- .step-title {
129
- background-color: #ff9e7d;
130
- color: white;
131
- padding: 8px 15px;
132
- border-radius: 15px;
133
- font-size: 1.2rem;
134
- margin-bottom: 10px;
135
- display: inline-block;
136
  }
137
 
138
- /* Green response box aligned to the right */
139
- .response-box {
140
- background: rgba(106, 219, 157, 0.9);
141
- padding: 15px;
142
- border-radius: 20px;
143
- margin: 15px 0;
144
- border: 3px solid #489d73;
145
- max-width: 85%;
146
- margin-left: auto; /* This pushes the box to the right */
147
- box-shadow: 3px 3px 10px rgba(0,0,0,0.1);
148
  }
149
 
150
- .story-text {
151
- font-size: 1.3rem;
152
- line-height: 1.6;
153
- color: #333;
154
  }
155
 
156
- /* Custom file uploader */
157
- .stFileUploader > div > div {
158
- background: #ffea8c;
159
- border: 2px dashed #ffaa44;
160
- border-radius: 20px;
161
- padding: 10px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  }
163
 
164
  /* Audio player styling */
165
  audio {
166
  width: 100%;
167
- border-radius: 30px;
168
- background: #ffcc66;
 
 
 
 
 
 
169
  }
170
 
171
- /* Fun floating animation for welcome screen */
172
- @keyframes float {
173
- 0% { transform: translateY(0); }
174
- 50% { transform: translateY(-10px); }
175
- 100% { transform: translateY(0); }
176
  }
177
 
178
- .float-animation {
179
- animation: float 3s infinite ease-in-out;
180
  }
181
 
182
- /* Fun emoji decorations */
183
- .emoji-decoration {
184
- font-size: 2rem;
185
- margin: 0 5px;
186
- display: inline-block;
187
- animation: wiggle 2s infinite;
 
 
 
 
 
 
188
  }
189
 
190
- @keyframes wiggle {
191
- 0%, 100% { transform: rotate(-5deg); }
192
- 50% { transform: rotate(5deg); }
193
  }
194
  </style>
195
  """, unsafe_allow_html=True)
196
 
197
- # App header with kid-friendly design
198
- st.markdown(
199
- "<h1><span class='emoji-decoration'>๐Ÿง™โ€โ™‚๏ธ</span> Magic Picture Storyteller <span class='emoji-decoration'>๐ŸŽจ</span></h1>",
200
- unsafe_allow_html=True)
201
 
202
- # File uploader with kid-friendly styling
203
- st.markdown("<h3>๐Ÿ“ท Let's pick a picture!</h3>", unsafe_allow_html=True)
204
- uploaded_file = st.file_uploader("Choose a fun picture...", key="upload")
 
205
 
206
  if uploaded_file is not None:
207
  bytes_data = uploaded_file.getvalue()
208
  with open(uploaded_file.name, "wb") as file:
209
  file.write(bytes_data)
210
 
211
- st.image(uploaded_file, caption="Your magical picture!", use_column_width=True)
 
212
 
213
  # Stage 1: Image to Text
214
- st.markdown("<div class='step-title'>๐Ÿ” Finding the magic in your picture...</div>", unsafe_allow_html=True)
215
- scenario = img2text(uploaded_file.name)
216
- # Display result in green box aligned to the right
217
- st.markdown(f"<div class='response-box'><p class='story-text'>{scenario}</p></div>", unsafe_allow_html=True)
218
 
219
  # Stage 2: Text to Story
220
- st.markdown("<div class='step-title'>๐Ÿ“ Creating a magical story...</div>", unsafe_allow_html=True)
221
- story = text2story(scenario)
222
- # Display result in green box aligned to the right
223
- st.markdown(f"<div class='response-box'><p class='story-text'>{story}</p></div>", unsafe_allow_html=True)
224
 
225
  # Stage 3: Story to Audio data
226
- st.markdown("<div class='step-title'>๐Ÿ”Š Let's hear the story!</div>", unsafe_allow_html=True)
227
- audio_data = text2audio(story)
228
-
229
- # Play button container for right alignment
230
- st.markdown("<div class='play-button-container'>", unsafe_allow_html=True)
231
- # Using columns to align button to the right
232
- col1, col2 = st.columns([3, 1])
233
- with col2:
234
- # Play button with kid-friendly design
235
- if st.button("๐Ÿ”Š Play My Story!"):
236
- if audio_data:
237
- st.audio(audio_data['audio'],
238
- format="audio/wav",
239
- start_time=0,
240
- sample_rate=audio_data['sampling_rate'])
241
- else:
242
- st.error("Oops! The magical voice got lost!")
243
- st.markdown("</div>", unsafe_allow_html=True)
244
 
245
  # Cleanup: Remove the temporary file
246
  if os.path.exists(uploaded_file.name):
247
  os.remove(uploaded_file.name)
248
  else:
249
- # Fun welcome screen for kids
250
  st.markdown("""
251
- <div style="text-align: center; padding: 30px;" class="float-animation">
252
- <div style="font-size: 80px; margin-bottom: 20px;">๐Ÿง™โ€โ™‚๏ธ</div>
253
- <h2 style="color: #6a3e8c;">Pick a picture to start the magic!</h2>
254
- <p style="font-size: 1.2rem;">The wizard is waiting to tell you a story!</p>
255
- <div style="margin-top: 30px;">
256
- <span class="emoji-decoration">๐ŸŒˆ</span>
257
- <span class="emoji-decoration">โญ</span>
258
- <span class="emoji-decoration">๐Ÿฆ„</span>
259
- <span class="emoji-decoration">๐ŸŽญ</span>
 
 
260
  </div>
261
  </div>
262
  """, unsafe_allow_html=True)
 
53
  return None
54
 
55
 
56
+ # Apply custom CSS for modern, stylish kid-friendly UI
57
+ st.set_page_config(page_title="StoryMagic", page_icon="โœจ", layout="wide")
58
 
59
  st.markdown("""
60
  <style>
61
+ /* Modern, stylish kid-friendly design */
62
+ @import url('https://fonts.googleapis.com/css2?family=Quicksand:wght@400;600;700&display=swap');
63
+
64
+ :root {
65
+ --primary-color: #6C63FF;
66
+ --secondary-color: #41B883;
67
+ --accent-color: #FF6B6B;
68
+ --background-light: #F7F9FC;
69
+ --text-dark: #2E3A59;
70
+ --shadow: 0 10px 20px rgba(0,0,0,0.08);
71
+ --border-radius: 16px;
72
+ }
73
 
74
  .stApp {
75
+ background: linear-gradient(135deg, #F4F9FF, #EEFAFF);
76
+ font-family: 'Quicksand', sans-serif;
77
+ color: var(--text-dark);
78
+ }
79
+
80
+ .main .block-container {
81
+ max-width: 1000px;
82
+ padding-top: 2rem;
83
+ padding-bottom: 2rem;
84
+ }
85
+
86
+ /* Modern headers */
87
+ h1, h2, h3 {
88
+ font-family: 'Quicksand', sans-serif;
89
+ font-weight: 700;
90
+ color: var(--primary-color);
91
  }
92
 
93
  h1 {
 
94
  font-size: 2.5rem;
95
  text-align: center;
96
+ margin-bottom: 0;
 
 
 
 
 
97
  }
98
 
99
+ h2 {
100
+ font-size: 1.8rem;
101
+ margin-bottom: 1rem;
 
 
 
102
  }
103
 
104
+ h3 {
105
+ font-size: 1.4rem;
106
+ margin-bottom: 0.8rem;
 
 
107
  }
108
 
109
+ /* Subtitle */
110
+ .subtitle {
111
+ text-align: center;
112
+ color: #6B7897;
113
+ font-size: 1.2rem;
114
+ margin-bottom: 2rem;
 
 
 
 
 
115
  }
116
 
117
+ /* Card containers */
118
+ .stCard {
119
+ background: white;
120
+ border-radius: var(--border-radius);
121
+ padding: 1.5rem;
122
+ box-shadow: var(--shadow);
123
+ margin-bottom: 1.5rem;
124
  }
125
 
126
+ /* Accent borders for stages */
127
+ .css-nahz7x, .css-ocqkz7, .css-4z1n4l {
128
+ border-left: 5px solid var(--primary-color) !important;
129
  }
130
 
131
+ .css-1r6slb0, .css-1ubpcwi {
132
+ border-left: 5px solid var(--secondary-color) !important;
 
 
 
 
133
  }
134
 
135
+ .css-pkbazv, .css-5rimss {
136
+ border-left: 5px solid var(--accent-color) !important;
 
 
 
 
 
 
137
  }
138
 
139
+ /* Custom file uploader */
140
+ .stFileUploader > div > div {
141
+ background: var(--background-light);
142
+ border: 2px dashed #D0D8E6;
143
+ border-radius: 12px;
144
+ padding: 20px;
145
+ transition: all 0.3s ease;
 
 
 
146
  }
147
 
148
+ .stFileUploader > div > div:hover {
149
+ border-color: var(--primary-color);
 
 
150
  }
151
 
152
+ /* Uploaded image styling */
153
+ .stImage img {
154
+ border-radius: 12px;
155
+ box-shadow: var(--shadow);
156
+ }
157
+
158
+ /* Stage icons */
159
+ .stage-icon {
160
+ font-size: 1.6rem;
161
+ margin-right: 10px;
162
+ vertical-align: middle;
163
+ }
164
+
165
+ /* Response styling */
166
+ .stText {
167
+ font-size: 1.1rem;
168
+ line-height: 1.7;
169
+ background: var(--background-light);
170
+ padding: 1rem;
171
+ border-radius: 12px;
172
+ border-left: 4px solid var(--secondary-color);
173
+ margin: 1rem 0;
174
+ box-shadow: 0 5px 15px rgba(0,0,0,0.05);
175
+ }
176
+
177
+ /* Button styling */
178
+ .stButton > button {
179
+ background: var(--secondary-color) !important;
180
+ color: white !important;
181
+ border: none !important;
182
+ border-radius: 50px !important;
183
+ padding: 0.6rem 1.5rem !important;
184
+ font-size: 1.1rem !important;
185
+ font-weight: 600 !important;
186
+ font-family: 'Quicksand', sans-serif !important;
187
+ transition: all 0.3s ease !important;
188
+ box-shadow: 0 5px 15px rgba(65, 184, 131, 0.3) !important;
189
+ }
190
+
191
+ .stButton > button:hover {
192
+ background: #37A574 !important;
193
+ transform: translateY(-3px) !important;
194
+ box-shadow: 0 8px 20px rgba(65, 184, 131, 0.4) !important;
195
+ }
196
+
197
+ .stButton > button:active {
198
+ transform: translateY(0) !important;
199
+ }
200
+
201
+ /* Column styling for button positioning */
202
+ [data-testid="column"]:last-child .stButton {
203
+ display: flex;
204
+ justify-content: flex-end;
205
  }
206
 
207
  /* Audio player styling */
208
  audio {
209
  width: 100%;
210
+ border-radius: 50px;
211
+ height: 40px;
212
+ }
213
+
214
+ /* Emoji animation */
215
+ @keyframes bounce {
216
+ 0%, 100% { transform: translateY(0); }
217
+ 50% { transform: translateY(-15px); }
218
  }
219
 
220
+ .emoji {
221
+ font-size: 1.8rem;
222
+ display: inline-block;
223
+ animation: bounce 2s infinite;
224
+ margin: 0 8px;
225
  }
226
 
227
+ .emoji:nth-child(2) {
228
+ animation-delay: 0.2s;
229
  }
230
 
231
+ .emoji:nth-child(3) {
232
+ animation-delay: 0.4s;
233
+ }
234
+
235
+ .emoji:nth-child(4) {
236
+ animation-delay: 0.6s;
237
+ }
238
+
239
+ /* Welcome message */
240
+ .welcome-message {
241
+ text-align: center;
242
+ padding: 3rem 1.5rem;
243
  }
244
 
245
+ .welcome-icon {
246
+ font-size: 4rem;
247
+ margin-bottom: 1rem;
248
  }
249
  </style>
250
  """, unsafe_allow_html=True)
251
 
252
+ # App header
253
+ st.title("โœจ StoryMagic")
254
+ st.markdown("<p class='subtitle'>Upload a picture and watch it transform into a magical story!</p>",
255
+ unsafe_allow_html=True)
256
 
257
+ # File uploader
258
+ with st.container():
259
+ st.subheader("Choose a picture")
260
+ uploaded_file = st.file_uploader("", key="upload")
261
 
262
  if uploaded_file is not None:
263
  bytes_data = uploaded_file.getvalue()
264
  with open(uploaded_file.name, "wb") as file:
265
  file.write(bytes_data)
266
 
267
+ # Display image
268
+ st.image(uploaded_file, use_column_width=True)
269
 
270
  # Stage 1: Image to Text
271
+ with st.container():
272
+ st.markdown("<h3><span class='stage-icon'>๐Ÿ”</span> Image Analysis</h3>", unsafe_allow_html=True)
273
+ scenario = img2text(uploaded_file.name)
274
+ st.text(scenario)
275
 
276
  # Stage 2: Text to Story
277
+ with st.container():
278
+ st.markdown("<h3><span class='stage-icon'>๐Ÿ“</span> Story Creation</h3>", unsafe_allow_html=True)
279
+ story = text2story(scenario)
280
+ st.text(story)
281
 
282
  # Stage 3: Story to Audio data
283
+ with st.container():
284
+ st.markdown("<h3><span class='stage-icon'>๐Ÿ”Š</span> Audio Narration</h3>", unsafe_allow_html=True)
285
+ audio_data = text2audio(story)
286
+
287
+ # Button right-aligned
288
+ col1, col2 = st.columns([3, 1])
289
+ with col2:
290
+ if st.button("๐Ÿ”Š Play Story"):
291
+ if audio_data:
292
+ st.audio(audio_data['audio'],
293
+ format="audio/wav",
294
+ start_time=0,
295
+ sample_rate=audio_data['sampling_rate'])
296
+ else:
297
+ st.error("Could not generate audio")
 
 
 
298
 
299
  # Cleanup: Remove the temporary file
300
  if os.path.exists(uploaded_file.name):
301
  os.remove(uploaded_file.name)
302
  else:
303
+ # Welcome message
304
  st.markdown("""
305
+ <div class="welcome-message">
306
+ <div class="welcome-icon">โœจ</div>
307
+ <h2>Welcome to StoryMagic!</h2>
308
+ <p style="font-size: 1.2rem; color: #6B7897; max-width: 500px; margin: 0 auto 30px;">
309
+ Upload any picture, and our magic wizard will turn it into an exciting story just for you!
310
+ </p>
311
+ <div>
312
+ <span class="emoji">๐Ÿš€</span>
313
+ <span class="emoji">๐Ÿฆ„</span>
314
+ <span class="emoji">๐Ÿ”ฎ</span>
315
+ <span class="emoji">๐ŸŒˆ</span>
316
  </div>
317
  </div>
318
  """, unsafe_allow_html=True)