""" 오디오 입력 컴포넌트 - Voice Semantle 스타일 애니메이션풍 하늘색 테마의 음성 입력 인터페이스 커스텀 버튼으로 Gradio Audio 컴포넌트 제어 👨‍💻 담당: 개발자 A """ import gradio as gr class AudioInputComponent: """Voice Semantle 스타일 오디오 입력 컴포넌트""" # 마이크 버튼 HTML 템플릿 MIC_BUTTON_HTML_TEMPLATE = """
Click the play button to start game
""" 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; } """ # JavaScript: 커스텀 버튼 클릭 시 Gradio Audio 컴포넌트 직접 제어 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) """ # 마이크 섹션 시각적 요소 (Gradio 6 html_template + js_on_load) 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 ) # Gradio Audio 컴포넌트 (CSS로 처음에는 숨김) 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" ) # 검증 버튼 (Gradio Button으로 이벤트 처리) 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 )