Spaces:
Runtime error
Runtime error
File size: 8,031 Bytes
cc05f1f 11cf154 5ae4c06 8d272f9 5ae4c06 7ad7fe5 b093de7 b69138c 7ad7fe5 fa5d44d 5ae4c06 7ad7fe5 11cf154 8d272f9 5ae4c06 11cf154 8d272f9 11cf154 8d272f9 cc05f1f 8d272f9 cc05f1f 11cf154 cc05f1f 5ae4c06 cc05f1f c0f3d5f 5ae4c06 19f646c 7ad7fe5 19f646c fa5d44d 19f646c 5ae4c06 11cf154 5ae4c06 11cf154 5ae4c06 8d272f9 5ae4c06 8d272f9 a4ad2c0 3bd37b5 7896be3 3bd37b5 c43a73a bd65f6a 3bd37b5 7ad7fe5 afce848 bd65f6a 8f78a85 7ad7fe5 9b0ebaa 3bd37b5 9b0ebaa 7ad7fe5 9b0ebaa 7ad7fe5 afce848 bd65f6a 22e18da 7ad7fe5 9b0ebaa 3bd37b5 9b0ebaa 7ad7fe5 9b0ebaa e5625ca 9b0ebaa |
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 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
import os
import time
import gradio as gr
from gtts import gTTS
import hashlib # π΅ νμΌλͺ
μ κ³ μ νκ² νκΈ° μν΄ μΆκ°
# π λ¨λͺ¨μ(Short Vowel) μ€ν 리 λ°μ΄ν° (ν
μ€νΈ + μ΄λ―Έμ§ URL ν¬ν¨)
image_base_url = "https://huggingface.co/spaces/englissi/englishstories/resolve/main/image/"
short_vowel_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"}
]
# π μ₯λͺ¨μ(Long Vowel) μ€ν 리 λ°μ΄ν°
long_vowel_stories = [
{"text": "Kate ate a big cake.", "image": f"{image_base_url}11.webp"},
{"text": "The train is late today.", "image": f"{image_base_url}12.webp"},
{"text": "I see a green tree.", "image": f"{image_base_url}13.webp"},
{"text": "He likes to read a book.", "image": f"{image_base_url}14.webp"},
{"text": "The kite is flying high.", "image": f"{image_base_url}15.webp"},
{"text": "The light is very bright.", "image": f"{image_base_url}16.webp"},
{"text": "The rose is red.", "image": f"{image_base_url}17.webp"},
{"text": "We saw a boat on the lake.", "image": f"{image_base_url}18.webp"},
{"text": "He is cute and kind.", "image": f"{image_base_url}19.webp"},
{"text": "A baby bird flew away.", "image": f"{image_base_url}20.webp"}
]
# π gTTSλ₯Ό μ¬μ©νμ¬ μμ± νμΌ μμ± (κ³ μ ν νμΌλͺ
+ μΊμ± μμ€ν
μΆκ°)
cached_audio = {} # κ°μ λ¬Έμ₯μ λν΄ APIλ₯Ό μ¬λ¬ λ² νΈμΆνμ§ μλλ‘ μ μ₯
def generate_audio(text):
try:
# π΅ μ΄λ―Έ μμ±λ μμ±μ΄ μμΌλ©΄ μ¬μ¬μ© (429 μ€λ₯ λ°©μ§)
if text in cached_audio:
return cached_audio[text]
# π΅ κ³ μ ν νμΌλͺ
μμ±
hash_key = hashlib.md5(text.encode()).hexdigest()[:10] # ν΄μ μ 10μ리 μ¬μ©
filename = f"audio_{hash_key}.mp3"
# π΅ gTTSλ₯Ό μ¬μ©νμ¬ μμ± μμ±
tts = gTTS(text=text, lang="en")
tts.save(filename)
print(f"β
μμ± νμΌ μμ± μλ£: {filename}")
# π΅ μμ±λ νμΌ μΊμ±
cached_audio[text] = filename
# π΅ μμ² μ νμ νΌνκΈ° μν΄ 1.5μ΄ λκΈ°
time.sleep(1.5)
return filename
except Exception as e:
print(f"β οΈ μμ± μμ± μ€ν¨: {e}")
return None
# π "λ€μ" λ²νΌ ν΄λ¦ μ νΈμΆλλ ν¨μ (HTML ν¬ν¨)
def next_story(current_index, story_list):
new_index = (current_index + 1) % len(story_list)
story = story_list[new_index]
text = f"<div class='story-text'>{story['text']}</div>"
image = story["image"]
audio_file = generate_audio(story["text"])
return new_index, text, image, audio_file, story["text"]
# π "μ¬μ" λ²νΌ ν΄λ¦ μ νΈμΆλλ ν¨μ (Gradio μ΅μ λ²μ μ λ§κ² μμ )
def play_story(current_text):
return generate_audio(current_text)
# π μ΄κΈ° λ°μ΄ν° μ€μ
init_index_short, init_text_short, init_image_short, init_audio_short = 0, short_vowel_stories[0]["text"], short_vowel_stories[0]["image"], generate_audio(short_vowel_stories[0]["text"])
init_index_long, init_text_long, init_image_long, init_audio_long = 0, long_vowel_stories[0]["text"], long_vowel_stories[0]["image"], generate_audio(long_vowel_stories[0]["text"])
# π Gradio UI ꡬμ±
with gr.Blocks(title="π κ·μ¬μ΄ μ€ν 리 μ±") as demo:
gr.HTML("""
<style>
body {
background-color: #FFFAF0; /* λ°λ»ν ν¬λ¦Όμ λ°°κ²½ */
font-family: 'Comic Sans MS', cursive, sans-serif;
}
h1 {
color: #FF6347;
text-align: center;
font-size: 3em;
font-weight: bold;
margin-top: 20px;
}
p {
text-align: center;
font-size: 1.2em;
color: #6B4226;
}
.story-text {
font-size: 2em;
font-weight: bold;
text-align: center;
color: #FF4500;
padding: 20px;
border-radius: 15px;
background: #FFF3E0;
display: inline-block;
box-shadow: 4px 4px 10px rgba(0,0,0,0.2);
}
.btn-custom {
font-size: 1.5em;
font-weight: bold;
border-radius: 20px;
padding: 10px 20px;
margin: 5px;
border: none;
cursor: pointer;
box-shadow: 3px 3px 8px rgba(0,0,0,0.2);
}
.next-btn {
background-color: #FFD700; /* λ
Έλμ λ²νΌ */
}
.play-btn {
background-color: #90EE90; /* μ°ν μ΄λ‘μ λ²νΌ */
}
.story-image img {
width: 300px !important;
height: 300px !important;
border-radius: 15px;
border: 5px solid #FFFFFF;
box-shadow: 4px 4px 10px rgba(0,0,0,0.2);
display: block;
margin: auto;
}
</style>
""")
gr.HTML("<h1>π μ¬λ―Έμλ μμ΄ μ€ν 리 νμ! π</h1>")
gr.HTML("<p>π± κ·μ¬μ΄ μ΄μΌκΈ°μ ν¨κ» μμ΄λ₯Ό λ°°μ보μμ! <br> λ²νΌμ λλ¬ λ€μ μ΄μΌκΈ°λ‘ λμ΄κ°κ³ , μμ±μ λ€μΌλ©° λ°λΌ μ½μ΄λ³΄μΈμ! π΅</p>")
with gr.Tabs():
with gr.TabItem("Short Vowel (λ¨λͺ¨μ)"):
state_index_short = gr.State(value=init_index_short)
state_text_short = gr.State(value=init_text_short)
story_text_short = gr.HTML(value=f"<div class='story-text'>{init_text_short}</div>")
story_image_short = gr.Image(value=init_image_short, width=300, height=300)
audio_output_short = gr.Audio(value=init_audio_short, autoplay=False)
with gr.Row():
next_button_short = gr.Button("π λ€μ μ΄μΌκΈ°", elem_classes=["btn-custom", "next-btn"])
play_button_short = gr.Button("π λ€μ λ£κΈ°", elem_classes=["btn-custom", "play-btn"])
next_button_short.click(
fn=next_story,
inputs=[state_index_short, gr.State(value=short_vowel_stories)],
outputs=[state_index_short, story_text_short, story_image_short, audio_output_short, state_text_short]
)
play_button_short.click(
fn=play_story,
inputs=[state_text_short],
outputs=[audio_output_short]
)
with gr.TabItem("Long Vowel (μ₯λͺ¨μ)"):
state_index_long = gr.State(value=init_index_long)
state_text_long = gr.State(value=init_text_long)
story_text_long = gr.HTML(value=f"<div class='story-text'>{init_text_long}</div>")
story_image_long = gr.Image(value=init_image_short, width=300, height=300)
audio_output_long = gr.Audio(value=init_audio_long, autoplay=False)
with gr.Row():
next_button_long = gr.Button("π λ€μ μ΄μΌκΈ°", elem_classes=["btn-custom", "next-btn"])
play_button_long = gr.Button("π λ€μ λ£κΈ°", elem_classes=["btn-custom", "play-btn"])
next_button_long.click(
fn=next_story,
inputs=[state_index_long, gr.State(value=long_vowel_stories)],
outputs=[state_index_long, story_text_long, story_image_long, audio_output_long, state_text_long]
)
play_button_long.click(
fn=play_story,
inputs=[state_text_long],
outputs=[audio_output_long]
)
# π μ± μ€ν
demo.launch()
|