말해봐요, 알파곰 - (2) 음성인식 Classification, STT 게임 API 개발 (Flask)

Vincent·2023년 5월 29일
0

말해봐요, 알파곰

목록 보기
3/3

Classification

import numpy as np
import librosa
import tensorflow as tf
from flask_cors import CORS, cross_origin
from flask import Flask, request, jsonify
import ffmpeg
import warnings
import speech_recognition as sr
warnings.filterwarnings('ignore')
r=sr.Recognizer()
app = Flask(__name__)
app.config['DEBUG'] = True
CORS(app)

# 리턴값 딕셔너리
checkDict = { 0 : "응",
            1 : "아니",
            }

wordDict = { 0 : "냠냠",
            1 : "드르륵",
            2 : "보글보글",
            3 : "사각사각",
            4 : "송송",
            5 : "주르륵",
            6 : "탁탁",
            7 : "툭툭",
            8 : "팔팔",
            9 : "풀풀",
            10 : "휘휘" }

birdDict = { 0 : "까마귀", 
            1 : "꿩", 
            2 : "뱁새", 
            3 : "오리", 
            4 : "참새", 
            5 : "황새" }

사용자의 음성이 들어오고 Flask 환경에 올라와있는 모델은 그것을 판단하여 진행되고 있는 게임에 따라 그에 맞는 값을 돌려준다. 앞선 글에서 새 이름 분류 모델에 관해 다뤘으므로 그의 연장선에 있는 코드를 다뤄보겠다.

@app.route('/api/ai/sky/bird', methods=["POST"])
@cross_origin()
def sky_bird():
    model = tf.keras.models.load_model('../bird_determine_model220928.h5')
    # 받아온 오디오 데이터
    file = request.files['audio_data']
    path='./audio.wav'
    file.save(path)

    audio_input = ffmpeg.input('./audio.wav')
    audio_cut = audio_input.audio.filter('atrim', duration=1)
    audio_output = ffmpeg.output(audio_cut, './audio_output.wav')
    ffmpeg.run(audio_output)

    path='./audio_output.wav'

들어오는 음성 데이터를 모델에 통과 시키기 위한 적절한 길이인 1초로 자른다.

    wav, sr = librosa.load(path, sr=16000)
    
    mfcc = librosa.feature.mfcc(wav, sr=16000, n_mfcc=100, n_fft=400, hop_length=160)
    # mfcc = sklearn.preprocessing.scale(mfcc, axis=1)
    pad2d = lambda a, i: a[:, 0:i] if a.shape[1] > i else np.hstack((a, np.zeros((a.shape[0], i-a.shape[1]))))
    padded_mfcc = pad2d(mfcc, 110)
    padded_mfcc = np.expand_dims(padded_mfcc, 0)

    result = model.predict(padded_mfcc)

    # 판별 완료된 음성 파일 삭제
    os.remove('./audio.wav')
    os.remove('./audio_output.wav')

    # 어떤 결과를 리턴시켜야 하나(까마귀 : 0, 꿩 : 1, 뱁새 : 2, 오리 : 3, 참새 : 4, 황새 : 5)
    for key, val in birdDict.items():
        if key == np.argmax(result) :
            return jsonify(answer = val)

앞선 시리즈에서 다룬 분류 예측 확인 과정 코드와 동일하다.

STT

파이썬 음성 인식 라이브러리인 SpeechRecognition을 이용하였다.
그리고 Google Speech Recognition을 활용하여 speech를 text로 바꾼다.

@app.route("/api/ai/stt", methods=["POST"])
def sttcheck():
    r = sr.Recognizer()
    file = request.files['audio_data']
    path='./audio.wav'
    file.save(path)

    audio_input = ffmpeg.input('./audio.wav')
    audio_cut = audio_input.audio.filter('atrim', duration=5)
    audio_output = ffmpeg.output(audio_cut, './audio_output.wav')
    ffmpeg.run(audio_output)

    path='./audio_output.wav'

stt도 들어온 음성 데이터를 검증을 위해 5초 길이로 자른다.

    try:
        transcript = ''
        while not transcript:
            with sr.AudioFile(path) as source:
                audio = r.record(source)
                transcript=r.recognize_google(audio, language="ko-KR")
    
        os.remove('./audio.wav')
        os.remove('./audio_output.wav')

        return jsonify(answer=transcript)

    except:
        os.remove('./audio.wav')
        os.remove('./audio_output.wav')

        return jsonify(answer='failed')

if __name__ == '__main__':
    app.run(host="0.0.0.0", port="5678",  debug=True)

아무 데이터도 들어오지 않았을 때 recognizer을 계속 작동시키고, 정상적으로 음성을 인식했을 경우 audio를 text로 변환한 내용을 transcript에 담고, 그것을 정답과 비교한 결과를 반환한다.
한국어를 말할 것이기 때문에 language="ko-KR"로 설정하였고 try, except를 이용하여 예외 처리도 해줬다. 제대로 인식하지 못했을 시 다시 말해달라고 하기 위함이다.

profile
Frontend & Artificial Intelligence

0개의 댓글