시작하기전
이번에는 사소한 코드 변경, stt 모듈 병합 등 코드 리팩토링을 또 신나게 했다~ 뭔가 기능을 추가하면 추가할 수록 이전에는 괜찮아보였던 부분이 맘에 안들어서 계속해서 수정했다..
아무튼 이번에는 이전에 말했던 speech recognition의 다른 api들을 사용할 수 있도록 추가했다.
(단 api를 내가 발급받지 않아서, 기능만 넣어두고 라디오버튼은 막아놨다.)
아마 이제 당분간 버전 4에서 찔끔찔끔씩 올릴 것 같다. 이제 메인이 아니다보니, 조금씩 추가하고픈 기능이 있을 때만 추가할 것이다. 프로젝트 회고는 이전 버전 4.0.0의 마지막에 짧게 작성해 놓았다.
Ver 4.0.1
Ver 4.0.1 특징
- 코드 리팩토링
- speech recognition api 추가
- 호출명령어 추가(비서)
1. 호출명령어 추가
우선 우리가 보통 애플의 시리, 삼성의 빅스비, 케이티의 지니 등과 같이 음성비서등을 부를 때 모두 시리야, 하이 빅스비, 오케이 구글, 지니야, 기가지니 등등 다양한 호출 명령어를 지정해줬다. 이 명령어를 통해서 프로그램을 실행시키고 작동시키는 것 같아 내 프로젝트에도 추가해줬다. 항상 음성비서들을 쓰면서 아니 왜 이름을 내가 지정할 수 없게 해놓는거지? 라는 생각이 들었다.(지금도 기본값외 지정된 거 말고는 사용자가 임의로 설정 불가. 내가 알기론) 그런데 프로젝트를 진행하다보니, 사용자가 이름을 지정하면 그 호출어를 제일 잘 알아들어야하는데, 어렵기 때문에 쉬운 것들로 정해놓은 거 아닌가 라는 생각이들었다.
암튼 말이 길었다. 나는 쉬운 단어 "비서야"라는 단어로 프로그램을 호출한다. 즉 서버를 켠 후, 모델을 고르고 start를 눌러놓으면 그 때부터 비서는 항상 대기 상태이고, "비서"라는 말을 하는 순간부터 메인 코드에 들어가서 작동된다.
(다만 이렇게 하면 이제 음성인식을 못했습니다 라는 경고를 못띄우게 됐다. 왜냐면 stt모듈들이 전부 녹음을 하는 시간이 정해져있어서 무한정대기가 불가능하기 때문에 항상 녹음을 실행하는데 저 에러를 설정하게 되면 몇초마다 음성을 인식하지 못했다는 경고가 뜨게된다. ->한마디로 이전버전들에 있던 try except 부분을 뺌, 음성을 인식하지 못했다는 알림이 나타나지 않음)
if __name__ == '__main__':
# 서버에서 받아온 모델,타입을 설정해줌.
sst_model.init(sys.argv[1], sys.argv[2])
while(1):
print(var_s.context, var_s.context_utt_label)
user_input = sst_model.load_stt_model()
if('비서야' in user_input):
tts_model.speak("안녕하세요, 무엇을 도와드릴까요?")
while(1):
user_input = sst_model.load_stt_model()
# 현재 날씨 기능을 제외하고는 지니 일상대화 api 이용.
if(user_input==0):break
if system_order(user_input) != 1: get_conversation(user_input)
if(user_input==0):break
2. 코드 리팩토링
이전에 voice_module 폴더안에 나뉘어졌던, 3개의 STT 모듈인 (stt_speech_recognition, stt_whisper, stt_erti)를 하나의 파일 stt_module에 넣어줬다. 또한 main함수를 조금 간단하게 하고자, 이 stt_module에서 프로그램 종료등과 호출 등 전부 진행했다. 이제 사용자의 입력을 받는 부분은 추후에 다른 api나 모듈들을 추가해도 조금만 손보면 바로 적용할 수 있을 것이다. 우선 새로운 메인함수는 위에 있고 예전 메인함수를 잠깐 다시 보여주면 아래와 같다.
def select_module(selected_model):
if selected_model == 'speech_recognition':
recorder = module1
elif selected_model == 'etri':
recorder = module2
elif selected_model == 'whisper':
recorder = module3
print("medium 이상을 권장합니다.")
return recorder
if __name__ == '__main__':
# 서버에서 클릭한 값들을 받아옴
if len(sys.argv) == 3:
selected_model = sys.argv[1]
model_version = sys.argv[2]
var_s.stt_recorder= select_module(selected_model)
var_s.type=model_version
while True:
speak("안녕하세요, 무엇을 도와드릴까요?")
user_input = var_s.stt_recorder(var_s.type)
if '종료' in user_input:
var_s.context_utt_label.append('user')
speak("다음에 또 뵙겠습니다.")
# db에 대화기록 업데이트
get_db_connection()
create_table()
add_log(var_s.context, var_s.context_utt_label)
break
var_s.context_utt_label.append('user')
# 현재 날씨 기능을 제외하고는 지니 일상대화 api 이용.
if system_order(user_input) != 1:
get_conversation(user_input)
딱봐도 짧아진게 보인다. 사용자가 입력한 모델, 타입에 대한 처리를 stt_module.py에서 처리하게 바꿨고, 호출어를 통해 실행되도록 바꿨으며, 종료처리 및 db 저장도 stt_module에서 이뤄진다. 한마디로 모든 음성->텍스트 에 관한 stt에 관한 처리는 stt_module.py에서 이뤄진다.
import urllib3
import json
import base64
import torch
import whisper
import warnings
warnings.filterwarnings("ignore", category=UserWarning, module="torch.functional")
import speech_recognition as sr
# personal function
import variable_storage as var_s
import voice_module.stt_module as sst_model
import voice_module.tts_module as tts_model
from utils.api_token_list import etri_accessKey
from utils.make_db import shutdown
# 음성을 sst 모델에 넣기위하여 wav 파일로 저장
# 각 모델마다 지원형식(mp3,wav..)가 다르지만, wav는 모두 지원.
def record():
recognizer = sr.Recognizer()
microphone = sr.Microphone()
with microphone as source:
print("인식중...")
recognizer.adjust_for_ambient_noise(source)
audio = recognizer.listen(source, timeout=30)
print("녹음이 완료되었습니다.")
with open("./mp3/tmp.wav", "wb") as f:
f.write(audio.get_wav_data())
return recognizer,audio
# speech_recognition 라이브러리의 다양한 api들을 지원.
# google cloud, openai는 사전 api 발급이 필요
# vosk, whisper은 사전 설치가 필요
# google은 기본적으로 사용 가능
def stt_speech_recognition():
recognizer,audio = record()
if(var_s.model_type=='google'):recognizers=recognizer.recognize_google
elif(var_s.model_type=='Google_cloud_api'):recognizers=recognizer.recognize_google_cloud
elif(var_s.model_type=='Vosk'):recognizers= recognizer.recognize_vosk
elif(var_s.model_type=='whisper_local'):recognizers= recognizer.recognize_whisper
elif(var_s.model_type=='Whisper_api'):recognizers= recognizer.recognize_whisper_api
text = recognizers(audio, language="ko-KR")
return text
# ETRI api 발급 필요
def stt_etri_api():
record()
file = open("./mp3/tmp.wav", "rb")
audioContents = base64.b64encode(file.read()).decode("utf8")
file.close()
requestJson = {"argument": {"language_code": "korean","audio": audioContents }}
http = urllib3.PoolManager()
response = http.request(
"POST",
"http://aiopen.etri.re.kr:8000/WiseASR/Recognition",
headers={"Content-Type": "application/json; charset=UTF-8","Authorization": etri_accessKey},
body=json.dumps(requestJson)
)
text = json.loads(response.data.decode("utf-8", errors='ignore'))['return_object']['recognized']
return text
# local에 설치된 whisper 필요(speech_regonition에 있는 whisper과 다르게 모델 타입 선택 가능)
def stt_whisper():
record()
model = whisper.load_model(var_s.model_type)
result = model.transcribe("./mp3/tmp.wav",fp16=False)
text=result["text"]
return text
# sst모델을 사용하기 위한 초기설정 한번만 실행되면 됨.
# variable_storage에 영구적으로 sst모델과 타입이 저장됨.
def init(selected_model,select_type):
if(selected_model=='Speech recognition'): var_s.stt_model=stt_speech_recognition
elif(selected_model=='ETRI'): var_s.stt_model=stt_etri_api
elif(selected_model=='Whisper'): var_s.stt_model=stt_whisper
var_s.model_type=select_type
return 0
def load_stt_model():
# 선택한 모델에 따라 sst 진행
try:
text = var_s.stt_model()
# 인식된 음성을 출력
print(f"인식된 음성 명령: {text}")
# 대화기록에 내용, 발화자 추가(genie 대화에)
var_s.context.append(text)
var_s.context_utt_label.append('user')
if('종료' in text):
shutdown()
tts_model.speak("프로그램을 종료합니다.")
return 0
else: return text
except:
return load_stt_model()
3. Speech recognition api 추가
젤 처음 버전 1.0.0에서 시작할 때 설명했었는데, speech recognition은 파이썬 라이브러리로 STT를 쉽게 구현할 수 있도록 만들어진 라이브러리이다. 이 라이브러리에는 다양한 API를 이용한 STT를 수행하는데, 우리는 간단하게 함수 하나만 써서 이것들을 불러올 수 있다. 뭐 버전에는 아래와 같이 다양한 것들이 있고 설명 또한 공식 Github에 나와있다.
나는 내 프로젝트에 이중에서, 우선 Google Cloud Speech API랑, Vosk API, OpenAI whisper, Whisper API를 추가로 선택할 수있도록 추가했다.
그런데 Google Cloud Speech도 api발급이 필요하고, Openai whisper도 api발급이 필요해서..그냥 speech recognition 호출함수만 추가해놓고 서버를 켜면 선택할수 없도록 우선 막아놨다. 그리고 OpenAI whisper은 이상한게, 내가 한 것 처럼 로컬에 설치한 whisper을 불러오라고 하는데, 내가 이전 버전들에서 사용하던 whisper은 아직도 잘되는데 이 speech recognition으로 불러온 whisper은 작동을 안한다. 그리고 버전을 선택하는 것도 없어서.. 잘 모르겠다
사실 저 api들 모두 설명이 자세하게 나와있지 않아서 추가만 해보고 사용해보지 못해서 다시 제대로 사용될 때 다른 api들도 추가해서 업데이트 해오도록 하겠다~
암튼 이전에는 whisper을 선택했을 때만 추가로 tiny,base 등 버전 선택을 하도록 만들었는데 speech recognition을 선택할 떄도 추가로 api를 선택할 수 있도록 수정해놓았다.
# speech_recognition 라이브러리의 다양한 api들을 지원.
# google cloud, openai는 사전 api 발급이 필요
# vosk, whisper은 사전 설치가 필요
# google은 기본적으로 사용 가능
def stt_speech_recognition():
recognizer,audio = record()
if(var_s.model_type=='google'):recognizers=recognizer.recognize_google
elif(var_s.model_type=='Google_cloud_api'):recognizers=recognizer.recognize_google_cloud
elif(var_s.model_type=='Vosk'):recognizers= recognizer.recognize_vosk
elif(var_s.model_type=='whisper_local'):recognizers= recognizer.recognize_whisper
elif(var_s.model_type=='Whisper_api'):recognizers= recognizer.recognize_whisper_api
text = recognizers(audio, language="ko-KR")
return text
요약
- speech recognition 다른 api 호출할 수 있도록 추가(사전 발급 및 설치 필요)
- 코드 리팩토링
- 버그 수정
- 호출어(비서) 설정
'프로젝트 > 음성비서' 카테고리의 다른 글
Speech recognition 라이브러리 api 추가하기 (0) | 2023.11.03 |
---|---|
업데이트 할 내용(Latest. Ver 4.0.1) (0) | 2023.11.03 |
Voice secretary 버전 3.0.1 (0) | 2023.11.03 |
Voice secretary 버전 3.0.0 (2) | 2023.11.02 |
Voice secretary 버전 2.0.0 (0) | 2023.11.02 |