Project Log/[Toy Project]Tiger-Bot

[Toy Project]Tiger-Bot 만들기 - Talking [1]

Sergemeow 2025. 2. 25. 20:59

얼굴을 따라서 머리를 요리조리 움직이는게 귀엽지만 뭔가 아쉽다. 

 

서보모터가 하나 남아서 꼬리도 움직여줄까 싶긴한데 그건 나중에 기회가 되면 해보는걸로하고, 

 

웹캠에 마이크가 붙어있는걸 보고 음성에 음성으로 답변하는 기능을 추가해봐야겠다는 생각이 들었다. 

 

로직은 간단하게 될 듯 하다. 

 

1. 소리를 녹음해주는 함수를 선언하고

2. OpenAI의 API를 사용해서 Whisper 모듈로 녹음된 소리를 Text로 바꿔주는 함수 선언. Whisper는 제법 인식률이 높은 speech-to-text 모듈이라 실사용에 편할 것으로 추정

3. 역시 OpenAI의 GPT 모듈을 사용해서 Text를 매개변수로 받으면 GPT의 답변을 return하는 함수 선언.

4. Text를 음성으로 소리내주는 함수 선언.

5. 1~2를 반복해주는 반복문 작성. 특정 표현을 감지하면 3~4를 실행

 

바로 코드를 써보자

import openai
import pyaudio
import wave
import pyttsx3


# OpenAI API 키 설정
client = openai.OpenAI(api_key="")
# 오디오 설정
FORMAT = pyaudio.paInt16 # 16비트 오디오
CHANNELS = 1 # 모노
RATE = 44100 # 샘플링 레이트 (44.1kHz)
CHUNK = 1024 # 버퍼 크기
RECORD_SECONDS = 2 # 녹음 시간
OUTPUT_FILENAME = "recorded.wav"


# 마이크에서 오디오 녹음
def record_audio():
    audio = pyaudio.PyAudio()
    stream = audio.open(format=FORMAT, channels=CHANNELS,
    rate=RATE, input=True,
    frames_per_buffer=CHUNK)
    print("Input your voice...")
    frames = []

    for _ in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
        data = stream.read(CHUNK)
        frames.append(data)

    print("Recognizing your voice...")

    stream.stop_stream()
    stream.close()
    audio.terminate()

# WAV 파일 저장
    with wave.open(OUTPUT_FILENAME, 'wb') as wf:
        wf.setnchannels(CHANNELS)
        wf.setsampwidth(audio.get_sample_size(FORMAT))
        wf.setframerate(RATE)
        wf.writeframes(b''.join(frames))

# OpenAI Whisper API로 음성을 텍스트로 변환
def transcribe_audio(file_path):
    with open(file_path, "rb") as audio_file:
        transcript = client.audio.transcriptions.create(
            model="whisper-1",
            file=audio_file,
            language="ko"
        )
    return transcript.text

def gpt_answer(question):
    response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "system", "content": "You are a sarcastic, mean assistant."},
            {"role": "user", "content": question}
        ],
        max_tokens=100
    )
    responseContent = response.choices[0].message.content
    return responseContent


def text_to_speech(text):
    engine = pyttsx3.init()

    # 음성 속도 설정
    rate = engine.getProperty('rate')
    engine.setProperty('rate', rate +10) # 속도 조정

    # 음성 볼륨 설정
    volume = engine.getProperty('volume')
    engine.setProperty('volume', 1) # 0.0에서 1.0 사이

    # 음성 언어 설정
    voices = engine.getProperty('voices')
    engine.setProperty('voice', voices[0].id)
    # for voice in voices:
    # print(f"ID: {voice.id}, Name: {voice.name}, Lang: {voice.languages}")

    # 한국어 음성 선택
    for voice in voices:
        if 'Microsoft Heami Desktop - Korean' in voice.name:
            engine.setProperty('voice', voice.id)
            break

    engine.say(text)
    engine.runAndWait()


# 실행 구문들. 망둥어튀김이라고 말하고 이를 인식하면 질문 가능
while(True):
    record_audio()
    inputText = transcribe_audio(OUTPUT_FILENAME)
    print("Textified Speech:", inputText)
    if inputText == "망둥어튀김" or inputText == "망둥어 튀김":
        print("Bingo!!")
        text_to_speech("무슨 일이야?")
        record_audio()
        questionText = transcribe_audio(OUTPUT_FILENAME)
        gptAnswer = gpt_answer(questionText)
        print(gptAnswer)
        text_to_speech(gptAnswer)

 

GPT 엔진에게 답변을 구할 때 재밌게도 답변자의 페르소나를 설정할 수 있는데, 우선 재미를 위해 "Sarcastic, mean assistant"로 설정했다. 

 

테스트해본 결과 의도한대로 잘 동작은 하지만 한국어 음성이 좀 어색해서 아쉽긴하다. 

 

음성인식주기를 우선 2초로 설정했는데 2초마다 API 토큰을 사용하다보니 비용이 좀 걱정스러워서 테스트를 해보았다. 

 

세시간동안 켜둬서 끊임없이 주변 소리를 인식하도록 했는데 

대략 0.6$쯤 소모하는 것 같다. 하루 9시간 가동하면 중간중간 질문도 했을 때 2$, 한화로 3천원쯤 될텐데 재미로 켜두기엔 적지 않은 금액이긴하다.

 

다음으로는 몇가지 코드 개선을 해볼까한다. (질문에 대한 input 시간 늘리기, 답변에 대한 토큰 제한 - 현재의 토큰 제한은 토큰값보다 긴 답변을 받으면 중간에 잘라버린다)

 

 

 

테스트