englishstories / app.py
englissi's picture
Update app.py
a4ad2c0 verified
raw
history blame
4.77 kB
import os
from gtts import gTTS
import gradio as gr
# ์Šคํ† ๋ฆฌ ๋ฐ์ดํ„ฐ (ํ…์ŠคํŠธ + ์ด๋ฏธ์ง€ URL ํฌํ•จ)
image_base_url = "https://huggingface.co/spaces/englissi/englishstories/resolve/main/image/"
stories = [
{"text": "Sam has a cat.", "image": f"{image_base_url}1.webp"},
{"text": "The cat is fat and tan.", "image": f"{image_base_url}2.webp"},
{"text": "Sam and the cat nap on a mat.", "image": f"{image_base_url}3.webp"},
{"text": "Ben has a red pen.", "image": f"{image_base_url}4.webp"},
{"text": "He pets a hen in a den.", "image": f"{image_base_url}5.webp"},
{"text": "Tim sits and grins.", "image": f"{image_base_url}6.webp"},
{"text": "A big pig digs in the mud.", "image": f"{image_base_url}7.webp"},
{"text": "Dot the dog jogs and hops.", "image": f"{image_base_url}8.webp"},
{"text": "Gus the pup has a cup.", "image": f"{image_base_url}9.webp"},
{"text": "Fun in the sun is the best!", "image": f"{image_base_url}10.webp"}
]
# ์Œ์„ฑ ํŒŒ์ผ ์ƒ์„ฑ ํ•จ์ˆ˜ (gTTS ์ด์šฉ)
def generate_audio(text, filename="story.mp3"):
try:
repeated_text = " ".join([text] * 3) # 3๋ฒˆ ๋ฐ˜๋ณตํ•ด์„œ ์ฝ๊ธฐ
tts = gTTS(repeated_text, lang='en')
tts.save(filename)
except Exception as e:
print("TTS ์ƒ์„ฑ ์˜ค๋ฅ˜:", e)
return filename
# ์Šคํ† ๋ฆฌ ํ…์ŠคํŠธ๋ฅผ HTML ์Šคํƒ€์ผ๋กœ ํฌ๊ฒŒ ํ‘œ์‹œํ•˜๊ณ  ์ค‘์•™ ์ •๋ ฌํ•˜๋Š” ํ•จ์ˆ˜
def format_story_text(text):
return f"""
<div style='
font-size:4em;
font-weight:bold;
text-align:center;
color:#FF4500;
font-family:sans-serif;
margin: 20px 0;
'>
{text}
</div>
"""
# ์ดˆ๊ธฐ ์Šคํ† ๋ฆฌ ๋กœ๋”ฉ ํ•จ์ˆ˜
def init_story():
index = 0
story = stories[index]
text = story["text"]
image = story["image"]
audio_file = generate_audio(text, filename="story.mp3")
return index, text, image, audio_file
# "๋‹ค์Œ" ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ํ˜ธ์ถœ๋˜๋Š” ํ•จ์ˆ˜
def next_story(current_index):
new_index = (current_index + 1) % len(stories)
story = stories[new_index]
text = story["text"]
image = story["image"]
audio_file = generate_audio(text, filename="story.mp3")
return new_index, format_story_text(text), image, audio_file, text
# "์žฌ์ƒ" ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ํ˜ธ์ถœ๋˜๋Š” ํ•จ์ˆ˜
def play_story(current_text):
audio_file = generate_audio(current_text, filename="story.mp3")
return audio_file
# ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ ์„ค์ •
init_index, init_text, init_image, init_audio = init_story()
# Gradio ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌ์„ฑ
with gr.Blocks(title="๐Ÿ“š ๊ท€์—ฌ์šด ์Šคํ† ๋ฆฌ ์•ฑ") as demo:
gr.Markdown(
"<div style='text-align:center; font-size:2em; font-weight:bold;'>๐ŸŽˆ ์žฌ๋ฏธ์žˆ๋Š” ์˜์–ด ์Šคํ† ๋ฆฌ ํƒ€์ž„! ๐Ÿ“–</div>",
unsafe_allow_html=True
)
gr.Markdown(
"<div style='text-align:center; font-size:1.2em;'>๐Ÿฑ ๊ท€์—ฌ์šด ์ด์•ผ๊ธฐ์™€ ํ•จ๊ป˜ ์˜์–ด๋ฅผ ๋ฐฐ์›Œ๋ณด์•„์š”! <br> "
"๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ๋‹ค์Œ ์ด์•ผ๊ธฐ๋กœ ๋„˜์–ด๊ฐ€๊ณ , ์Œ์„ฑ์„ ๋“ค์œผ๋ฉฐ ๋”ฐ๋ผ ์ฝ์–ด๋ณด์„ธ์š”! ๐ŸŽต</div>",
unsafe_allow_html=True
)
# ์ƒํƒœ๊ฐ’: ํ˜„์žฌ ์Šคํ† ๋ฆฌ ์ธ๋ฑ์Šค์™€ ํ˜„์žฌ ์Šคํ† ๋ฆฌ ํ…์ŠคํŠธ ์ €์žฅ
state_index = gr.State(value=init_index)
state_text = gr.State(value=init_text)
# UI ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ
story_text = gr.Markdown(value=format_story_text(init_text), label="์Šคํ† ๋ฆฌ")
story_image = gr.Image(
value=init_image, label="์ด๋ฏธ์ง€", type="filepath", width=400, height=400,
container=True
)
audio_output = gr.Audio(value=init_audio, label="๐ŸŽง ์Œ์„ฑ ์žฌ์ƒ", type="filepath", autoplay=True)
with gr.Row():
next_button = gr.Button("๐Ÿ‘‰ ๋‹ค์Œ ์ด์•ผ๊ธฐ", elem_id="next-btn")
play_button = gr.Button("๐Ÿ”Š ๋‹ค์‹œ ๋“ฃ๊ธฐ", elem_id="play-btn")
# "๋‹ค์Œ" ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ
next_button.click(
fn=next_story,
inputs=[state_index],
outputs=[state_index, story_text, story_image, audio_output, state_text]
)
# "์žฌ์ƒ" ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ
play_button.click(
fn=play_story,
inputs=[state_text],
outputs=[audio_output]
)
# CSS ์Šคํƒ€์ผ ์ถ”๊ฐ€ (๊ท€์—ฌ์šด ํ…Œ๋งˆ)
demo.css = """
body {
background-color: #FFFAF0; /* ๋”ฐ๋œปํ•œ ํฌ๋ฆผ์ƒ‰ ๋ฐฐ๊ฒฝ */
}
#next-btn {
background-color: #FFD700; /* ๋…ธ๋ž€์ƒ‰ ๋ฒ„ํŠผ */
font-size: 1.5em;
font-weight: bold;
border-radius: 20px;
padding: 10px;
}
#play-btn {
background-color: #90EE90; /* ์—ฐํ•œ ์ดˆ๋ก์ƒ‰ ๋ฒ„ํŠผ */
font-size: 1.5em;
font-weight: bold;
border-radius: 20px;
padding: 10px;
}
img {
border-radius: 10px; /* ๋‘ฅ๊ทผ ํ…Œ๋‘๋ฆฌ */
border: 5px solid #FFFFFF; /* ํฐ์ƒ‰ ํ…Œ๋‘๋ฆฌ */
}
"""
# ์•ฑ ์‹คํ–‰
demo.launch()