import os, time, logging, requests import speech_recognition as sr from ctypes import * # ALSA 에러 억제 os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide" def py_error_handler(filename, line, function, err, fmt): pass ERROR_HANDLER_FUNC = CFUNCTYPE(None, c_char_p, c_int, c_char_p, c_int, c_char_p) c_error_handler = ERROR_HANDLER_FUNC(py_error_handler) try: asound = cdll.LoadLibrary('libasound.so.2') asound.snd_lib_error_set_handler(c_error_handler) except: pass logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s') logger = logging.getLogger(__name__) # ===== 설정 ===== OPENWEBUI_URL = "http://192.168.0.149:18789" API_KEY = "your-openwebui-api-key" # OpenWebUI → 설정 → API Key MODEL = "gemini-2.0-flash" # 오픈클로에서 쓰는 모델명 WAKE_WORD = "미나이" MIC_INDEX = 3 # ================ def stt_google(audio_data): """Google STT로 음성 → 텍스트""" recognizer = sr.Recognizer() try: return recognizer.recognize_google(audio_data, language='ko-KR') except: return None def send_to_openwebui(text): """텍스트를 OpenWebUI 채팅 API로 전송""" try: headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" } payload = { "model": MODEL, "messages": [{"role": "user", "content": text}] } # OpenAI 호환 엔드포인트 사용 res = requests.post( f"{OPENWEBUI_URL}/api/chat/completions", headers=headers, json=payload, timeout=30 ) response_text = res.json()["choices"][0]["message"]["content"] logger.info(f"AI 응답: {response_text}") return response_text except Exception as e: logger.error(f"전송 실패: {e}") return None def main(): recognizer = sr.Recognizer() recognizer.energy_threshold = 400 recognizer.pause_threshold = 1.0 mic = sr.Microphone(device_index=MIC_INDEX) logger.info(f"==== '{WAKE_WORD}' 대기 중 ====") while True: try: with mic as source: audio = recognizer.listen(source, timeout=None, phrase_time_limit=3) text = stt_google(audio) if not text: continue if WAKE_WORD in text: logger.info(f"웨이크워드 감지: {text}") logger.info("명령 녹음 중...") with mic as source: cmd_audio = recognizer.listen(source, timeout=5, phrase_time_limit=10) cmd_text = stt_google(cmd_audio) if cmd_text: logger.info(f"명령: {cmd_text}") send_to_openwebui(cmd_text) except Exception as e: logger.error(f"루프 오류: {e}") time.sleep(1) if __name__ == "__main__": main()