goversetv commited on
Commit
30d363f
โ€ข
1 Parent(s): 498b704

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +141 -97
app.py CHANGED
@@ -1,105 +1,149 @@
1
  import gradio as gr
 
 
 
 
2
  import webbrowser
3
- from datetime import datetime
4
 
5
- # ๊ธ€๋กœ๋ฒŒ ๋ณ€์ˆ˜ ์ดˆ๊ธฐํ™”
6
- search_history = [] # ๊ฒ€์ƒ‰ ๊ธฐ๋ก์„ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ๋ฆฌ์ŠคํŠธ
7
 
8
- # ๊ฒ€์ƒ‰ ํ•จ์ˆ˜ ์ •์˜
9
- def search_and_update_history(keyword):
10
- if not keyword:
11
- return "๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”.", ""
12
-
13
- # ์ผ๋ณธ์–ด๋กœ ๋ฒˆ์—ญ๋œ ํ‚ค์›Œ๋“œ ์ƒ์„ฑ (์ด ๋ถ€๋ถ„์€ ์‹ค์ œ ๋ฒˆ์—ญ API ์‚ฌ์šฉ ๋˜๋Š” ๋Œ€์ฒด ๋กœ์ง์œผ๋กœ ์ˆ˜์ • ๊ฐ€๋Šฅ)
14
- japanese_keyword = keyword # ์ด ๋ถ€๋ถ„์€ ๋‹จ์ˆœํ™”๋œ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.
15
- url = f"https://www.irasutoya.com/search?q={japanese_keyword}"
16
-
17
- # ๊ฒ€์ƒ‰ ๊ธฐ๋ก ์ €์žฅ
18
- save_search_history(keyword, japanese_keyword, url)
19
-
20
- # ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜
21
- return f"๊ฒ€์ƒ‰์–ด: {keyword}\n์ผ๋ณธ์–ด: {japanese_keyword}\n\n[์ผ๋Ÿฌ์ŠคํŠธ ๋ณด๋Ÿฌ๊ฐ€๊ธฐ]({url})", url
22
-
23
- # ๊ฒ€์ƒ‰ ๊ธฐ๋ก ์ €์žฅ ํ•จ์ˆ˜
24
- def save_search_history(keyword, japanese_keyword, url):
25
- timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
26
- search_history.append((timestamp, keyword, japanese_keyword, url))
27
-
28
- # ๊ฒ€์ƒ‰ ๊ธฐ๋ก ์กฐํšŒ ํ•จ์ˆ˜
29
- def load_search_history():
30
- return [f"{record[0]} - {record[1]}: {record[2]} (๋งํฌ: {record[3]})" for record in search_history]
31
-
32
- # ๊ฒ€์ƒ‰ ๊ธฐ๋ก ์žฌ๊ฒ€์ƒ‰ ํ•จ์ˆ˜
33
- def replay_history(selected_item):
34
- if not selected_item:
35
- return "๊ฒ€์ƒ‰ ๊ธฐ๋ก์„ ์„ ํƒํ•˜์„ธ์š”.", ""
36
- keyword = selected_item.split(" - ")[1].split(":")[0]
37
- return search_and_update_history(keyword)
38
-
39
- # ์•ˆ๋‚ด ๋ฌธ๊ตฌ ์ถ”๊ฐ€
40
- def get_info_text():
41
- return """
42
- **์ด๋ผ์Šคํ† ์•ผ(Irasutoya.com)**๋Š” ์ผ๋ณธ์˜ ์ผ๋Ÿฌ์ŠคํŠธ๋ ˆ์ดํ„ฐ์ธ ๋ฏธ์ฆˆํƒ€๋‹ˆ ํƒ€์นด์‹œ(Takashi Mizutani)๊ฐ€ ์šด์˜ํ•˜๋Š” ๋ฌด๋ฃŒ ์ผ๋Ÿฌ์ŠคํŠธ ์‚ฌ์ดํŠธ์ž…๋‹ˆ๋‹ค.
43
- ์ด ์‚ฌ์ดํŠธ๋Š” ๊ท€์—ฝ๊ณ  ๋‹จ์ˆœํ•œ ์Šคํƒ€์ผ์˜ ์ผ๋Ÿฌ์ŠคํŠธ๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ, ์ฃผ๋กœ ์›น์‚ฌ์ดํŠธ, ํ”„๋ ˆ์  ํ…Œ์ด์…˜, ๋ธ”๋กœ๊ทธ ํฌ์ŠคํŠธ, ์ธ์‡„๋ฌผ ๋“ฑ์—์„œ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋Š” ๋‹ค์–‘ํ•œ ์ฃผ์ œ์˜ ์ด๋ฏธ์ง€๋ฅผ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
44
- ์ด๋ผ์Šคํ† ์•ผ์˜ ์ผ๋Ÿฌ์ŠคํŠธ๋Š” ํŠนํžˆ ์ผ๋ณธ ๋‚ด์—์„œ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์œผ๋ฉฐ, ๊ณต๊ณต๊ธฐ๊ด€, ๊ธฐ์—…, ๊ฐœ์ธ ๋ธ”๋กœ๊ทธ ๋“ฑ ๋‹ค์–‘ํ•œ ๊ณณ์—์„œ ์‰ฝ๊ฒŒ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
45
-
46
- **์ฃผ์˜ ์‚ฌํ•ญ:** ์ด ์‚ฌ์ดํŠธ๋Š” ๋‹จ์ˆœํžˆ ๊ฒ€์ƒ‰์ด ํŽธํ•˜๋„๋ก ์ผ๋ณธ์–ด๋กœ ๋ฒˆ์—ญํ•ด์„œ ์ „๋‹ฌํ•˜๋Š” ๊ธฐ๋Šฅ ์™ธ์—๋Š” ๋‹ค๋ฅธ ๊ธฐ๋Šฅ์ด ์—†์Šต๋‹ˆ๋‹ค.
47
-
48
- - **์‚ฌ์šฉ ๋ฐฉ๋ฒ•**:
49
- 1. ๊ฒ€์ƒ‰ ์ฐฝ์— ํ•œ๊ธ€๋กœ ํ‚ค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
50
- 2. ๊ฒ€์ƒ‰ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.
51
- 3. ์ž๋™์œผ๋กœ ์ผ๋ณธ์–ด๋กœ ๋ฒˆ์—ญ๋œ ๊ฒ€์ƒ‰์–ด๋กœ ์ด๋ผ์Šคํ† ์•ผ ์‚ฌ์ดํŠธ๊ฐ€ ์—ด๋ฆฌ๋ฉฐ, ์›ํ•˜๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ด๋ฏธ์ง€๋ฅผ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
52
-
53
- **์ €์ž‘๊ถŒ ์•ˆ๋‚ด**:
54
- ๊ฐœ์ธ, ๋ฒ•์ธ, ์ƒ์—…์  ์‚ฌ์šฉ ๋ชจ๋‘ ๋ฌด๋ฃŒ๋กœ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. ๋‹จ, ์ €์ž‘๋ฌผ๋‹น 20๊ฐœ๊นŒ์ง€ ๊ฐ€๋Šฅํ•˜๋ฉฐ, 21์ ๋ถ€ํ„ฐ๋Š” ์œ ๋ฃŒ๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
55
- ์ €์ž‘๊ถŒ ํ‘œ๊ธฐ ์˜๋ฌด๋Š” ์—†์œผ๋ฉฐ, ์ž์œ ๋กญ๊ฒŒ ํŽธ์ง‘ ๊ฐ€๊ณต์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
56
-
57
- **์ผ๋ณธ์–ด ํ•™์Šต**:
58
- ์ผ๋ณธ์–ด ๋ฐœ์Œ ๋“ฃ๊ธฐ ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ๊ฐ„๋‹จํžˆ ์ผ๋ณธ์–ด ๊ณต๋ถ€๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค!
59
- """
60
 
61
- # Gradio ์ธํ„ฐํŽ˜์ด์Šค ๋นŒ๋“œ
62
- with gr.Blocks() as app:
63
- # UI ์š”์†Œ ๋ฐฐ์น˜
64
- with gr.Row():
65
- gr.Markdown("# Irasutoya ํ•œ๊ธ€ ๊ฒ€์ƒ‰๊ธฐ")
66
 
67
- with gr.Row():
68
- keyword_input = gr.Textbox(placeholder="ํ•œ๊ธ€๋กœ ๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”.")
69
- search_button = gr.Button("๊ฒ€์ƒ‰")
70
-
71
- result_output = gr.Markdown()
72
- history_output = gr.Dropdown(label="๊ฒ€์ƒ‰ ๊ธฐ๋ก", choices=[])
73
- history_button = gr.Button("๊ฒ€์ƒ‰ ๊ธฐ๋ก ์žฌ๊ฒ€์ƒ‰")
74
-
75
- # ์•ˆ๋‚ด ๋ฌธ๊ตฌ ์ถ”๊ฐ€
76
- with gr.Row():
77
- gr.Markdown(get_info_text())
78
-
79
- with gr.Row():
80
- support_button = gr.Button("๊ณ ๋ฒ„์Šค ํ›„์›ํ•˜๊ธฐ")
81
- support_button.click(lambda: webbrowser.open("https://litt.ly/goverse"))
82
-
83
- # ๊ฒ€์ƒ‰ ๋ฒ„ํŠผ ํด๋ฆญ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ
84
- search_button.click(
85
- search_and_update_history,
86
- inputs=[keyword_input],
87
- outputs=[result_output]
88
- )
89
-
90
- # ๊ฒ€์ƒ‰ ๊ธฐ๋ก ๋“œ๋กญ๋‹ค์šด ์—…๋ฐ์ดํŠธ
91
- search_button.click(
92
- load_search_history,
93
- inputs=[],
94
- outputs=[history_output]
95
- )
96
-
97
- # ๊ฒ€์ƒ‰ ๊ธฐ๋ก ์„ ํƒ์‹œ ์žฌ๊ฒ€์ƒ‰
98
- history_button.click(
99
- replay_history,
100
- inputs=[history_output],
101
- outputs=[result_output]
102
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
  # ์•ฑ ์‹คํ–‰
105
- app.launch()
 
1
  import gradio as gr
2
+ from deep_translator import GoogleTranslator
3
+ from gtts import gTTS
4
+ import pykakasi
5
+ import os
6
  import webbrowser
 
7
 
8
+ # ํ˜„์žฌ ๋ฒ„์ „ ์ •๋ณด
9
+ __version__ = "1.6.1"
10
 
11
+ # Kakasi ์„ค์ • (๋กœ๋งˆ์ž ๋ณ€ํ™˜)
12
+ kakasi = pykakasi.kakasi()
13
+ conv = kakasi.convert
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
+ # ๋กœ๋งˆ์ž ๋ณ€ํ™˜ ํ•จ์ˆ˜
16
+ def to_romaji(japanese_text):
17
+ result = conv(japanese_text)
18
+ romaji = ''.join([item['hepburn'] for item in result])
19
+ return romaji
20
 
21
+ # ๊ฒ€์ƒ‰ ๋ฐ ๊ฒฐ๊ณผ ์ถœ๋ ฅ ํ•จ์ˆ˜
22
+ def search_and_update_history(keyword):
23
+ result, japanese_keyword = search(keyword)
24
+
25
+ if japanese_keyword:
26
+ audio_path = generate_audio_file(japanese_keyword)
27
+ return result, gr.update(value=audio_path, visible=True)
28
+ else:
29
+ return result, gr.update(visible=False)
30
+
31
+ # ๊ฒ€์ƒ‰ ํ•จ์ˆ˜
32
+ def search(keyword):
33
+ try:
34
+ translator = GoogleTranslator(source='ko', target='ja')
35
+ japanese_keyword = translator.translate(keyword)
36
+
37
+ url = f"https://www.irasutoya.com/search?q={japanese_keyword}"
38
+ romaji = to_romaji(japanese_keyword)
39
+ result_text = (
40
+ f"**๊ฒ€์ƒ‰์–ด:** {keyword}\n"
41
+ f"**์ผ๋ณธ์–ด ๋ฒˆ์—ญ:** {japanese_keyword} ({romaji})\n"
42
+ f"<a href='{url}' target='_blank'>๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ๋ณด๊ธฐ (์ƒˆ ํƒญ์—์„œ ์—ด๊ธฐ)</a>\n\n"
43
+ f"**์•ˆ๋‚ด:** ๋กœ๋งˆ์ž ํ‘œ๊ธฐ์™€ ์Œ์„ฑ์€ ์‹ค์ œ ๋ฐœ์Œ๊ณผ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค."
44
+ )
45
+ return result_text, japanese_keyword
46
+ except Exception as e:
47
+ return f"๋ฒˆ์—ญ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {e}", None
48
+
49
+ # ์ผ๋ณธ์–ด ์Œ์„ฑ ์ƒ์„ฑ ํ•จ์ˆ˜
50
+ def generate_audio_file(japanese_text):
51
+ try:
52
+ tts = gTTS(japanese_text, lang='ja')
53
+ file_path = "japanese_audio.mp3"
54
+ tts.save(file_path)
55
+ return file_path
56
+ except Exception as e:
57
+ return None
58
+
59
+ # Gradio ์ธํ„ฐํŽ˜์ด์Šค ์„ค์ •
60
+ with gr.Blocks(css="""
61
+ .container {
62
+ max-width: 100%;
63
+ margin: auto;
64
+ padding: 10px;
65
+ }
66
+ .input-box {
67
+ padding: 10px;
68
+ border: 2px solid #ddd;
69
+ border-radius: 4px;
70
+ font-size: 16px;
71
+ width: 100%;
72
+ }
73
+ .result-output {
74
+ background-color: #fff;
75
+ padding: 10px;
76
+ border: 1px solid #ddd;
77
+ border-radius: 4px;
78
+ font-size: 16px;
79
+ width: 100%;
80
+ margin-top: 15px;
81
+ }
82
+ .title {
83
+ font-size: 24px;
84
+ font-weight: bold;
85
+ color: #2C3E50;
86
+ margin-bottom: 10px;
87
+ text-align: center;
88
+ }
89
+ .btn-large {
90
+ font-size: 16px;
91
+ padding: 8px;
92
+ border-radius: 4px;
93
+ width: 100%;
94
+ margin-top: 5px;
95
+ }
96
+ .btn-search {
97
+ background-color: #4CAF50;
98
+ color: white;
99
+ }
100
+ .btn-clear {
101
+ background-color: #f39c12;
102
+ color: white;
103
+ }
104
+ .creator-info {
105
+ font-size: 12px;
106
+ color: #7f8c8d;
107
+ text-align: center;
108
+ margin-top: 20px;
109
+ }
110
+ """) as demo:
111
+
112
+ with gr.Column(elem_classes="container"):
113
+ gr.Markdown(f"## Irasutoya ํ•œ๊ธ€ ๊ฒ€์ƒ‰๊ธฐ - ๋ฒ„์ „ {__version__}", elem_classes="title")
114
+
115
+ keyword_input = gr.Textbox(label="ํ•œ๊ธ€ ๊ฒ€์ƒ‰์–ด ์ž…๋ ฅ", placeholder="ํ•œ๊ธ€๋กœ ๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”", elem_classes="input-box")
116
+ search_button = gr.Button("๊ฒ€์ƒ‰", elem_classes="btn-large btn-search")
117
+ clear_button = gr.Button("์ง€์šฐ๊ธฐ", elem_classes="btn-large btn-clear")
118
+
119
+ result_output = gr.Markdown(elem_classes="result-output")
120
+ play_audio = gr.Audio(visible=False) # ์Œ์„ฑ ํŒŒ์ผ์„ ์žฌ์ƒํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ
121
+
122
+ search_button.click(
123
+ fn=search_and_update_history,
124
+ inputs=[keyword_input],
125
+ outputs=[result_output, play_audio],
126
+ )
127
+
128
+ keyword_input.submit(
129
+ fn=search_and_update_history,
130
+ inputs=[keyword_input],
131
+ outputs=[result_output, play_audio],
132
+ )
133
+
134
+ clear_button.click(
135
+ fn=lambda: ("", "", gr.update(visible=False)),
136
+ outputs=[keyword_input, result_output, play_audio],
137
+ )
138
+
139
+ # ์ œ์ž‘์ž ์ •๋ณด ์„น์…˜ ์ถ”๊ฐ€
140
+ gr.Markdown("""
141
+ <div style="text-align: center;">
142
+ <a href="https://litt.ly/goverse" target="_blank" style="color: #2980b9; text-decoration: underline;">๊ณ ๋ฒ„์ŠคTV</a>
143
+ </div>
144
+ """)
145
+
146
+ gr.Markdown("์ œ์ž‘์ž: ๊ณ ๋ฒ„์ŠคTV", elem_classes="creator-info")
147
 
148
  # ์•ฑ ์‹คํ–‰
149
+ demo.launch(share=False)