|
|
""" |
|
|
์ค๋์ค ์
๋ ฅ ์ปดํฌ๋ํธ - Voice Semantle ์คํ์ผ |
|
|
์ ๋๋ฉ์ด์
ํ ํ๋์ ํ
๋ง์ ์์ฑ ์
๋ ฅ ์ธํฐํ์ด์ค |
|
|
์ปค์คํ
๋ฒํผ์ผ๋ก Gradio Audio ์ปดํฌ๋ํธ ์ ์ด |
|
|
|
|
|
๐จโ๐ป ๋ด๋น: ๊ฐ๋ฐ์ A |
|
|
""" |
|
|
|
|
|
import gradio as gr |
|
|
|
|
|
|
|
|
class AudioInputComponent: |
|
|
"""Voice Semantle ์คํ์ผ ์ค๋์ค ์
๋ ฅ ์ปดํฌ๋ํธ""" |
|
|
|
|
|
|
|
|
MIC_BUTTON_HTML_TEMPLATE = """ |
|
|
<div class="mic-section"> |
|
|
<div class="mic-status" id="mic-status">Click the play button to start game</div> |
|
|
<button class="mic-btn" id="mic-btn" title="๋
น์ ์์"> |
|
|
<svg xmlns="http://www.w3.org/2000/svg" height="44" viewBox="0 0 64 64" width="44"> |
|
|
<path fill="#fff" d="M24 18 Q20 18 20 22 L20 42 Q20 46 24 46 L46 34 Q50 32 46 30 Z" stroke="#fff" stroke-width="2" stroke-linejoin="round" stroke-linecap="round"/> |
|
|
</svg> |
|
|
</button> |
|
|
</div> |
|
|
""" |
|
|
|
|
|
MIC_BUTTON_CSS_TEMPLATE = """ |
|
|
.mic-section { |
|
|
display: flex; |
|
|
flex-direction: column; |
|
|
align-items: center; |
|
|
gap: 16px; |
|
|
padding: 30px 0; |
|
|
width: 100%; |
|
|
} |
|
|
.mic-status { |
|
|
font-size: 13px; |
|
|
color: #5a7a9a; |
|
|
text-align: center; |
|
|
min-height: 20px; |
|
|
} |
|
|
.mic-btn { |
|
|
width: 80px; |
|
|
height: 80px; |
|
|
border-radius: 50%; |
|
|
border: 3px solid #4db8ff; |
|
|
background: linear-gradient(135deg, #4db8ff 0%, #5bc0eb 100%); |
|
|
color: white; |
|
|
cursor: pointer; |
|
|
display: flex; |
|
|
align-items: center; |
|
|
justify-content: center; |
|
|
transition: all 0.3s ease; |
|
|
box-shadow: 0 4px 16px rgba(77, 184, 255, 0.4); |
|
|
padding: 0 !important; |
|
|
} |
|
|
.mic-btn:hover { |
|
|
transform: scale(1.08); |
|
|
box-shadow: 0 6px 24px rgba(77, 184, 255, 0.5); |
|
|
} |
|
|
.mic-btn:active { |
|
|
transform: scale(0.95); |
|
|
} |
|
|
.mic-btn.recording { |
|
|
background: linear-gradient(135deg, #ff9f43 0%, #e08b2d 100%); |
|
|
border-color: #ff9f43; |
|
|
animation: pulse 1.5s infinite; |
|
|
} |
|
|
@keyframes pulse { |
|
|
0%, 100% { box-shadow: 0 0 0 0 rgba(255, 159, 67, 0.5); } |
|
|
50% { box-shadow: 0 0 0 15px rgba(255, 159, 67, 0); } |
|
|
} |
|
|
|
|
|
/* ๋คํฌ๋ชจ๋ */ |
|
|
.dark .mic-status { |
|
|
color: #818384; |
|
|
} |
|
|
""" |
|
|
|
|
|
|
|
|
MIC_BUTTON_JS = """ |
|
|
const micBtn = element.querySelector('#mic-btn'); |
|
|
const uploadLink = element.querySelector('#upload-link'); |
|
|
const statusText = element.querySelector('#mic-status'); |
|
|
|
|
|
// ์ค๋์ค wrapper ํ์ ํจ์ |
|
|
function showAudioWrapper() { |
|
|
const wrapper = document.querySelector('#audio-wrapper'); |
|
|
if (wrapper) { |
|
|
wrapper.style.display = 'block'; |
|
|
} |
|
|
} |
|
|
|
|
|
// ๋ง์ดํฌ ๋ฒํผ ํด๋ฆญ โ ์ค๋์ค ์ปดํฌ๋ํธ ํ์ + ๋
น์ ์์ |
|
|
micBtn.addEventListener('click', () => { |
|
|
showAudioWrapper(); |
|
|
statusText.textContent = 'Ready to play'; |
|
|
}); |
|
|
""" |
|
|
|
|
|
def __init__(self, validator): |
|
|
""" |
|
|
Args: |
|
|
validator: AudioValidator ์ธ์คํด์ค |
|
|
""" |
|
|
self.validator = validator |
|
|
self.audio_input = None |
|
|
self.submit_btn = None |
|
|
self.mic_button_html = None |
|
|
self.audio_wrapper = None |
|
|
|
|
|
def render(self): |
|
|
""" |
|
|
Wordle ์คํ์ผ ์ค๋์ค ์
๋ ฅ UI ๋ ๋๋ง |
|
|
|
|
|
Returns: |
|
|
tuple: (audio_input, submit_btn) |
|
|
""" |
|
|
|
|
|
self.mic_button_html = gr.HTML( |
|
|
value=self.MIC_BUTTON_HTML_TEMPLATE, |
|
|
css_template=self.MIC_BUTTON_CSS_TEMPLATE, |
|
|
js_on_load=self.MIC_BUTTON_JS, |
|
|
elem_id="mic-section", |
|
|
padding=False |
|
|
) |
|
|
|
|
|
|
|
|
self.audio_wrapper = gr.Column(elem_id="audio-wrapper") |
|
|
with self.audio_wrapper: |
|
|
self.audio_input = gr.Audio( |
|
|
label="Audio recording", |
|
|
type="filepath", |
|
|
sources=["microphone", "upload"], |
|
|
elem_id="audio-input" |
|
|
) |
|
|
|
|
|
|
|
|
self.submit_btn = gr.Button( |
|
|
"SUBMIT", |
|
|
variant="primary", |
|
|
size="lg", |
|
|
elem_id="verify-btn" |
|
|
) |
|
|
|
|
|
return self.audio_input, self.submit_btn |
|
|
|
|
|
def setup_events(self, validate_handler, inputs, outputs): |
|
|
""" |
|
|
์ด๋ฒคํธ ๋ฐ์ธ๋ฉ |
|
|
|
|
|
Args: |
|
|
validate_handler: ๊ฒ์ฆ ํธ๋ค๋ฌ ํจ์ |
|
|
inputs: ์
๋ ฅ ์ปดํฌ๋ํธ ๋ฆฌ์คํธ |
|
|
outputs: ์ถ๋ ฅ ์ปดํฌ๋ํธ ๋ฆฌ์คํธ |
|
|
""" |
|
|
|
|
|
self.submit_btn.click( |
|
|
fn=validate_handler, |
|
|
inputs=inputs, |
|
|
outputs=outputs |
|
|
) |
|
|
|