102 lines
3.6 KiB
Python
102 lines
3.6 KiB
Python
import os
|
|
import time
|
|
import logging
|
|
import requests
|
|
import speech_recognition as sr
|
|
import pygame
|
|
from ctypes import *
|
|
|
|
# smart_mic.py 맨 위 import 아래 추가
|
|
import os
|
|
# 불필요한 로그 억제
|
|
os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide"
|
|
from ctypes import *
|
|
|
|
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
|
|
|
|
|
|
|
|
# ALSA 에러 로그 숨기기
|
|
ERROR_HANDLER_FUNC = CFUNCTYPE(None, c_char_p, c_int, c_char_p, c_int, c_char_p)
|
|
def py_error_handler(filename, line, function, err, fmt): pass
|
|
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__)
|
|
|
|
# [환경 설정]
|
|
# VM_IP 자리에 오픈클로 VM의 실제 IP를 넣으세요.
|
|
OPENCLAW_API_URL = "http://192.168.0.149:18789/api/v1/chat"
|
|
WAKE_WORD = "애미나이"
|
|
MIC_INDEX = 3 # 현재 확인된 장치 번호
|
|
|
|
def send_to_openclaw(audio_data):
|
|
"""녹음된 명령어를 오픈클로로 슛!"""
|
|
try:
|
|
# 파일 저장 확인을 위해 ls -al 에서 보일 이름을 고정합니다.
|
|
filename = "cmd.wav"
|
|
with open(filename, "wb") as f:
|
|
f.write(audio_data.get_wav_data())
|
|
|
|
logger.info(f">>> {filename} 생성 완료! 오픈클로 전송 시작...")
|
|
|
|
with open(filename, "rb") as f:
|
|
files = {'file': (filename, f, 'audio/wav')}
|
|
response = requests.post(OPENCLAW_API_URL, files=files, timeout=20)
|
|
|
|
logger.info(f"오픈클로 서버 응답: {response.status_code}")
|
|
except Exception as e:
|
|
logger.error(f"전송 실패: {e}")
|
|
|
|
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}' 대기 중 (포트 18789) ====")
|
|
|
|
while True:
|
|
try:
|
|
with mic as source:
|
|
# 호출어 인식 단계
|
|
audio = recognizer.listen(source, timeout=None, phrase_time_limit=3)
|
|
|
|
try:
|
|
text = recognizer.recognize_google(audio, language='ko-KR')
|
|
|
|
# "에미나이", "애미나이" 모두 대응
|
|
if "미나이" in text:
|
|
logger.info(f"[{text}] 감지됨! 명령을 말씀하세요...")
|
|
|
|
# 스피커로 "네" 출력 (연결된 스피커가 있다면)
|
|
# play_feedback("네")
|
|
|
|
with mic as source:
|
|
logger.info("명령 녹음 중 (5초)...")
|
|
# 호출어 감지 후 5초간 집중 녹음
|
|
cmd_audio = recognizer.listen(source, timeout=5, phrase_time_limit=10)
|
|
|
|
# 녹음 끝나면 바로 전송 및 파일 생성
|
|
send_to_openclaw(cmd_audio)
|
|
|
|
except sr.UnknownValueError:
|
|
continue
|
|
except Exception as e:
|
|
logger.error(f"루프 오류: {e}")
|
|
time.sleep(1)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|