goversetv's picture
Update app.py
647764f verified
raw
history blame
6.47 kB
import gradio as gr
from deep_translator import GoogleTranslator
from gtts import gTTS
import pykakasi
import os
import webbrowser
from datetime import datetime
# ๋ฒ„์ „ ์ •๋ณด
__version__ = "1.7.10" # ๋ณ€๊ฒฝ ์‚ฌํ•ญ์— ๋”ฐ๋ผ ๋ฒ„์ „ ๊ฐฑ์‹ 
# Kakasi ์„ค์ • (๋กœ๋งˆ์ž ๋ณ€ํ™˜)
kakasi = pykakasi.kakasi()
conv = kakasi.convert
# ๋กœ๋งˆ์ž ๋ณ€ํ™˜ ํ•จ์ˆ˜
def to_romaji(japanese_text):
result = conv(japanese_text)
romaji = ''.join([item['hepburn'] for item in result])
return romaji
# ๊ฒ€์ƒ‰ ๋ฐ ๊ฒฐ๊ณผ ์ถœ๋ ฅ ํ•จ์ˆ˜
def search_and_update_history(keyword):
result, japanese_keyword = search(keyword)
if japanese_keyword:
audio_path = generate_audio_file(japanese_keyword)
return result, gr.update(value=audio_path, visible=True)
else:
return result, gr.update(visible=False)
# ๊ฒ€์ƒ‰ ํ•จ์ˆ˜
def search(keyword):
try:
translator = GoogleTranslator(source='ko', target='ja')
japanese_keyword = translator.translate(keyword)
url = f"https://www.irasutoya.com/search?q={japanese_keyword}"
romaji = to_romaji(japanese_keyword)
result_text = (
f"**๊ฒ€์ƒ‰์–ด:** {keyword}\n"
f"**์ผ๋ณธ์–ด ๋ฒˆ์—ญ:** {japanese_keyword} ({romaji})\n"
f"<a href='{url}' target='_blank'>๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ๋ณด๊ธฐ (์ƒˆ ํƒญ์—์„œ ์—ด๊ธฐ)</a>\n\n"
f"**์•ˆ๋‚ด:** ๋กœ๋งˆ์ž ํ‘œ๊ธฐ์™€ ์Œ์„ฑ์€ ์‹ค์ œ ๋ฐœ์Œ๊ณผ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค."
)
return result_text, japanese_keyword
except Exception as e:
return f"๋ฒˆ์—ญ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {e}", None
# ์ผ๋ณธ์–ด ์Œ์„ฑ ์ƒ์„ฑ ํ•จ์ˆ˜
def generate_audio_file(japanese_text):
try:
tts = gTTS(japanese_text, lang='ja')
file_path = "japanese_audio.mp3"
tts.save(file_path)
return file_path
except Exception as e:
return None
# Gradio ์ธํ„ฐํŽ˜์ด์Šค ์„ค์ •
with gr.Blocks(css="""
.container {
max-width: 50%; /* ๊ฐ€๋กœ ํญ์„ ์ ˆ๋ฐ˜์œผ๋กœ ์ค„์ž„ */
margin: auto;
padding: 10px;
}
.input-box {
width: 100%; /* ๊ฐ€๋กœ ๋„ˆ๋น„ ์ตœ๋Œ€ํ™” */
height: auto; /* ๋†’์ด๋ฅผ ์ž๋™์œผ๋กœ ์„ค์ • */
padding: 12px 20px; /* ํŒจ๋”ฉ ์ถ”๊ฐ€ */
border: 2px solid #ddd;
border-radius: 4px;
font-size: 18px;
box-sizing: border-box;
}
.result-output {
background-color: #fff;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
width: 100%;
margin-top: 15px;
}
.title {
font-size: 24px;
font-weight: bold;
color: #2C3E50;
margin-bottom: 10px;
text-align: center;
}
.btn-large {
font-size: 16px;
padding: 8px;
border-radius: 4px;
width: 100%;
margin-top: 5px;
box-sizing: border-box;
}
.btn-search {
background-color: #4CAF50;
color: white;
}
.btn-clear {
background-color: #f39c12;
color: white;
}
.creator-info {
font-size: 12px;
color: #7f8c8d;
text-align: center;
margin-top: 20px;
}
""") as demo:
with gr.Column(elem_classes="container"):
gr.Markdown(f"## Irasutoya ํ•œ๊ธ€ ๊ฒ€์ƒ‰๊ธฐ - ๋ฒ„์ „ {__version__}", elem_classes="title")
keyword_input = gr.Textbox(label="ํ•œ๊ธ€ ๊ฒ€์ƒ‰์–ด ์ž…๋ ฅ", placeholder="ํ•œ๊ธ€๋กœ ๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”", elem_classes="input-box")
search_button = gr.Button("๊ฒ€์ƒ‰", elem_classes="btn-large btn-search")
clear_button = gr.Button("์ง€์šฐ๊ธฐ", elem_classes="btn-large btn-clear")
result_output = gr.Markdown(elem_classes="result-output")
play_audio = gr.Audio(visible=False) # ์Œ์„ฑ ํŒŒ์ผ์„ ์žฌ์ƒํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ
search_button.click(
fn=search_and_update_history,
inputs=[keyword_input],
outputs=[result_output, play_audio],
)
keyword_input.submit(
fn=search_and_update_history,
inputs=[keyword_input],
outputs=[result_output, play_audio],
)
clear_button.click(
fn=lambda: ("", "", gr.update(visible=False)),
outputs=[keyword_input, result_output, play_audio],
)
# ์•ˆ๋‚ด ๋ฌธ๊ตฌ ์ถ”๊ฐ€
gr.Markdown("""
**โœจ ์ด๋ผ์Šคํ† ์•ผ(Irasutoya.com)** ๋Š” ์ผ๋ณธ์˜ ์ผ๋Ÿฌ์ŠคํŠธ๋ ˆ์ดํ„ฐ ๋ฏธ์ฆˆํƒ€๋‹ˆ ํƒ€์นด์‹œ(Takashi Mizutani)๊ฐ€ ์šด์˜ํ•˜๋Š” ๋ฌด๋ฃŒ ์ผ๋Ÿฌ์ŠคํŠธ ์‚ฌ์ดํŠธ์ž…๋‹ˆ๋‹ค.
๊ท€์—ฝ๊ณ  ๋‹จ์ˆœํ•œ ์Šคํƒ€์ผ์˜ ์ผ๋Ÿฌ์ŠคํŠธ๋ฅผ ์›น์‚ฌ์ดํŠธ, ๋ธ”๋กœ๊ทธ, ํ”„๋ ˆ์  ํ…Œ์ด์…˜, ์ธ์‡„๋ฌผ ๋“ฑ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ผ๋ณธ ๋‚ด์—์„œ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
**๐ŸŽฅ ์œ ํŠœ๋ธŒ ์‡ผ์ธ ์™€ ์˜์ƒ ์ œ์ž‘์— ํ•„์š”ํ•œ ์ด๋ฏธ์ง€๋ฅผ ์‰ฝ๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ์ง€๋งŒ,**
์ผ๋ณธ์–ด๋กœ ๋˜์–ด ์žˆ์–ด ๋ถˆํŽธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ํ•œ๊ธ€๋กœ ์ž…๋ ฅํ•ด๋„ ๋ฒˆ์—ญ๊ณผ ์ด๋ฏธ์ง€๋ฅผ ํ•œ ๋ฒˆ์— ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ํˆด์„ ๊ฐœ๋ฐœํ–ˆ์Šต๋‹ˆ๋‹ค.
**๐ŸŽ“ ์ด ํˆด์€ ์ด๋ฏธ์ง€ ๊ฒ€์ƒ‰๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ผ๋ณธ์–ด ๋ฐœ์Œ์„ ๋“ค์œผ๋ฉฐ ๊ฐ„๋‹จํ•œ ์ผ๋ณธ์–ด ๊ณต๋ถ€๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.**
์ด ํˆด์ด ๋„์›€์ด ๋˜์…จ๋‹ค๋ฉด, ์•„๋ž˜ ๋งํฌ๋ฅผ ํ†ตํ•ด ํ›„์›ํ•ด ์ฃผ์„ธ์š”. ์—ฌ๋Ÿฌ๋ถ„์˜ ํ›„์›์ด ๋” ๋‚˜์€ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ฐ ํฐ ํž˜์ด ๋ฉ๋‹ˆ๋‹ค. ๐Ÿ’–
**โš ๏ธ ์ด๋ผ์Šคํ† ์•ผ ์ผ๋Ÿฌ์ŠคํŠธ ์ด์šฉ ์ฃผ์˜ ์‚ฌํ•ญ:**
- ๊ฐœ์ธ, ๋ฒ•์ธ, ์ƒ์—…์  ์‚ฌ์šฉ ๋ชจ๋‘ ๋ฌด๋ฃŒ์ž…๋‹ˆ๋‹ค.
- ๋‹จ, ํ•œ ์ €์ž‘๋ฌผ๋‹น 20๊ฐœ๊นŒ์ง€๋งŒ ๋ฌด๋ฃŒ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, 21๊ฐœ ์ด์ƒ ์‚ฌ์šฉ ์‹œ ์œ ์ƒ์œผ๋กœ ์ „ํ™˜๋ฉ๋‹ˆ๋‹ค.
- ์ €์ž‘๊ถŒ ํ‘œ๊ธฐ ์˜๋ฌด๋Š” ์—†์œผ๋ฉฐ, ์ž์œ ๋กญ๊ฒŒ ํŽธ์ง‘ ๋ฐ ๊ฐ€๊ณต์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
- ์ด ์‚ฌ์ดํŠธ๋Š” ๋‹จ์ˆœํžˆ ์ด๋ผ์Šคํ† ์•ผ์˜ ์ด๋ฏธ์ง€๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ผ๋ณธ์–ด๋กœ ๋ฒˆ์—ญํ•ด ์ „๋‹ฌํ•˜๋Š” ๊ธฐ๋Šฅ๋งŒ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
- ๊ฒ€์ƒ‰๋œ ์ด๋ฏธ์ง€์˜ ์‚ฌ์šฉ ์กฐ๊ฑด์€ ์ด๋ผ์Šคํ† ์•ผ์˜ ๊ทœ์ •์„ ๋”ฐ๋ฅด์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.
""")
# ์ œ์ž‘์ž ์ •๋ณด ์„น์…˜ ์ถ”๊ฐ€
gr.Markdown("""
<div style="text-align: center;">
<a href="https://litt.ly/goverse" target="_blank" style="color: #2980b9; text-decoration: underline;">๊ณ ๋ฒ„์Šค์—๊ฒŒ ํ”ผ๋“œ๋ฐฑํ•˜๊ธฐ</a>
</div>
""")
gr.Markdown("์ œ์ž‘์ž: ๊ณ ๋ฒ„์ŠคTV", elem_classes="creator-info")
# ์•ฑ ์‹คํ–‰
demo.launch(share=False)