아마존에서 제공하는 Alexa를 raspberry pi에 올려보자

https://github.com/ewenchou/alexa-client

위 URL을 따라가서 지시에 따라 alexa client를 사용해보도록 한다.


test_ask.py 파일은 영어로 된 wav파일을 요청하면 그에 맞는 alexa의 대답을 영어로된 wav파일로 반환해준다.

여기서 입력과 출력을 한글로 변경해보도록 하자.


먼저 한글 음성, 영어 음성을 각각 text로 변환시켜줄 STT와 텍스트를 음성으로 변환 시켜줄 TTS 그리고 번역이 필요하다.

각 부분에 대해 사용할 것은 다음과 같다.

STT : Google Cloud Speech API

TTS : Naver 음성합성 API

번역 : Naver 기계번역 API


Google Cloud Speech API

위 주소의 지시를 따라 debian에서 Google Cloud SDK 환경을 설치한다. 환경이 준비 되었다면 다음 URL을 따라서 Google Cloud Speech API를 사용하는 법에 대해 배워 보고, 제대로 작동되는지 예제를 다뤄보라.

https://cloud.google.com/speech/docs/getting-started


Naver API

TTS 설명 및 예시


Translation 설명 및 예시

https://developers.naver.com/docs/labs/translator/


이제 준비가 다 되었다. 한글로 말하면 한글로 대답해주는 나만의 korean Alexa를 python 코드로 구현해 보자.


korean Alexa

def transcribe_file_kor(speech_file):
    """Transcribe the given audio file."""
    
    speech_client = speech.Client()

    with io.open(speech_file, 'rb') as audio_file:
        content = audio_file.read()
        audio_sample = speech_client.sample(
            content=content,
            source_uri=None,
            encoding='LINEAR16',
            sample_rate_hertz=16000)

    alternatives = audio_sample.recognize('ko-KR')
    for alternative in alternatives:
		return alternative.transcript
		
def transcribe_file_eng(speech_file):
    """Transcribe the given audio file."""
    
    speech_client = speech.Client()

    with io.open(speech_file, 'rb') as audio_file:
        content = audio_file.read()
        audio_sample = speech_client.sample(
            content=content,
            source_uri=None,
            encoding='LINEAR16',
            sample_rate_hertz=16000)

    alternatives = audio_sample.recognize('en-US')
    for alternative in alternatives:
		return alternative.transcript

 이 코드는 Google Cloud Speech API를 사용하여 각각 한글로 된 음성파일을 한글 텍스트로, 영어로 된 음성파일을 영어 텍스트로 변환 시켜주는 코드이다. 



def translateKorToEng(korean_string):
	client_id = "YOUR_CLIENT_ID"
	client_secret = "YOUR_CLIENT_SECRET"
	encText = urllib.parse.quote(korean_string.encode("utf-8"))
	data = "source=ko&target=en&text=" + encText
	url = "https://openapi.naver.com/v1/language/translate"
	request = urllib.request.Request(url)
	request.add_header("X-Naver-Client-Id",client_id)
	request.add_header("X-Naver-Client-Secret",client_secret)
	response = urllib.request.urlopen(request, data=data.encode("utf-8"))
	rescode = response.getcode()
	if(rescode==200):
		response_body = json.loads(response.read().decode('utf-8'))
		translated_eng_str = response_body["message"]["result"]["translatedText"]
		return translated_eng_str
	else:
		print("Error Code:" + rescode)
		

def translateEngToKor(english_string):
	client_id = "YOUR_CLIENT_ID"
	client_secret = "YOUR_CLIENT_SECRET"
	encText = urllib.parse.quote(english_string.encode("utf-8"))
	data = "source=en&target=ko&text=" + encText
	url = "https://openapi.naver.com/v1/language/translate"
	request = urllib.request.Request(url)
	request.add_header("X-Naver-Client-Id",client_id)
	request.add_header("X-Naver-Client-Secret",client_secret)
	response = urllib.request.urlopen(request, data=data.encode("utf-8"))
	rescode = response.getcode()
	if(rescode==200):
		response_body = json.loads(response.read().decode('utf-8'))
		translated_kor_str = response_body["message"]["result"]["translatedText"]
		return translated_kor_str
	else:
		print("Error Code:" + rescode) 

 위 코드는 Naver 기계번역 API를 이용하여 한글을 영어로, 영어를 한글로 번역해주는 코드이다. client_id, client_secret 변수에는 자신이 할당 받은 id 와 secret을 적어 넣으면 된다.



def koreanTextToSpeech(korean_string):
	client_id = "YOUR_CLIENT_ID"
	client_secret = "YOUR_CLIENT_SECRET"
	encText = urllib.parse.quote(korean_string.encode("utf-8"))
	data = "speaker=mijin&speed=0&text=" + encText;
	url = "https://openapi.naver.com/v1/voice/tts.bin"
	request = urllib.request.Request(url)
	request.add_header("X-Naver-Client-Id",client_id)
	request.add_header("X-Naver-Client-Secret",client_secret)
	response = urllib.request.urlopen(request, data=data.encode('utf-8'))
	rescode = response.getcode()
	if(rescode==200):
		print("TTS mp3")
		response_body = response.read()
		with open('response_audio_file_path.mp3', 'wb') as f:
			f.write(response_body)
	else:
		print("Error Code:" + rescode)

 위 코드는 한국어 TTS코드로 Naver 음성합성 API를 이용하여 한글 텍스트 파일을 요청하면 한국어 음성파일을 반환하는 코드이다. 마찬가지로 자신의 client_id 와 client_secret을 넣어주면 된다. "output_audio_file_path.mp3" 에는 음성파일을 반환받기 원하는 경로와 파일명을 정해주면 된다.



def askToAlexa():
    alexa = AlexaClient()
    input = 'your_request_audio_path.wav'
    save_to = 'your_response_audio_path.mp3'
    alexa.ask(input, save_to=save_to)
    print "Response from Alexa saved to {}".format(save_to) 

 마지막으로 영어 음성파일을 Alexa에게 전달하고 그에 대한 답변을 음성파일로 받는 함수이다.  input과 save_to에 각각 자신의 요청파일과 반환받기 원하는 파일의 경로와 파일명을 넣으면 된다. 


이제 조각 들을 모두 모았으니 하나로 합쳐보자!


# -*- coding: utf-8 -*-
import io
import sys
import os
import json
from six.moves import urllib
from alexa_client import AlexaClient
from google.cloud import speech

def transcribe_file_kor(speech_file):
    """Transcribe the given audio file."""
    
    speech_client = speech.Client()

    with io.open(speech_file, 'rb') as audio_file:
        content = audio_file.read()
        audio_sample = speech_client.sample(
            content=content,
            source_uri=None,
            encoding='LINEAR16',
            sample_rate_hertz=16000)

    alternatives = audio_sample.recognize('ko-KR')
    for alternative in alternatives:
		return alternative.transcript
		
def transcribe_file_eng(speech_file):
    """Transcribe the given audio file."""
    
    speech_client = speech.Client()

    with io.open(speech_file, 'rb') as audio_file:
        content = audio_file.read()
        audio_sample = speech_client.sample(
            content=content,
            source_uri=None,
            encoding='LINEAR16',
            sample_rate_hertz=16000)

    alternatives = audio_sample.recognize('en-US')
    for alternative in alternatives:
		return alternative.transcript
		
		
def translateKorToEng(korean_string):
	client_id = "YOUR_CLIENT_ID"
	client_secret = "YOUR_CLIENT_SECRET"
	encText = urllib.parse.quote(korean_string.encode("utf-8"))
	data = "source=ko&target=en&text=" + encText
	url = "https://openapi.naver.com/v1/language/translate"
	request = urllib.request.Request(url)
	request.add_header("X-Naver-Client-Id",client_id)
	request.add_header("X-Naver-Client-Secret",client_secret)
	response = urllib.request.urlopen(request, data=data.encode("utf-8"))
	rescode = response.getcode()
	if(rescode==200):
		response_body = json.loads(response.read().decode('utf-8'))
		translated_eng_str = response_body["message"]["result"]["translatedText"]
		return translated_eng_str
	else:
		print("Error Code:" + rescode)
		

def translateEngToKor(english_string):
	client_id = "YOUR_CLIENT_ID"
	client_secret = "YOUR_CLIENT_SECRET"
	encText = urllib.parse.quote(english_string.encode("utf-8"))
	data = "source=en&target=ko&text=" + encText
	url = "https://openapi.naver.com/v1/language/translate"
	request = urllib.request.Request(url)
	request.add_header("X-Naver-Client-Id",client_id)
	request.add_header("X-Naver-Client-Secret",client_secret)
	response = urllib.request.urlopen(request, data=data.encode("utf-8"))
	rescode = response.getcode()
	if(rescode==200):
		response_body = json.loads(response.read().decode('utf-8'))
		translated_kor_str = response_body["message"]["result"]["translatedText"]
		return translated_kor_str
	else:
		print("Error Code:" + rescode)
	
	
	
def koreanTextToSpeech(korean_string):
	client_id = "YOUR_CLIENT_ID"
	client_secret = "YOUR_CLIENT_SECRET"
	encText = urllib.parse.quote(korean_string.encode("utf-8"))
	data = "speaker=mijin&speed=0&text=" + encText;
	url = "https://openapi.naver.com/v1/voice/tts.bin"
	request = urllib.request.Request(url)
	request.add_header("X-Naver-Client-Id",client_id)
	request.add_header("X-Naver-Client-Secret",client_secret)
	response = urllib.request.urlopen(request, data=data.encode('utf-8'))
	rescode = response.getcode()
	if(rescode==200):
		print("TTS mp3")
		response_body = response.read()
		with open('korean_alexa.mp3', 'wb') as f:
			f.write(response_body)
	else:
		print("Error Code:" + rescode)
	
	
"""This test will send a pre-generated audio file in the `tests` directory
to AVS, and saves it as `/tmp/test1.mp3`."""
def askToAlexa():
    alexa = AlexaClient()
    input = 'after_srate_conv.wav'  #'{}/1.wav'.format(TESTS_PATH)
    save_to = 'response_alexa.mp3'
    alexa.ask(input, save_to=save_to)
    print "Response from Alexa saved to {}".format(save_to)


if __name__ == '__main__':

	# 환경 변수 설정
	os.system("export GOOGLE_APPLICATION_CREDENTIALS=\"Your_Google_Service_Account_Key_Path.json\"")
	
	# 인코딩 설정
	reload(sys)
	sys.setdefaultencoding('utf-8')
	
	# 녹음
	os.system("arecord -D plughw:1,0 -f S16_LE -c1 -r16000 -d 3 input.wav")
	print("recording complete!")
	
	# STT 한글
	input_kor_str = transcribe_file_kor('input.wav')
	print(input_kor_str)
	
	# 한글을 영어로 번역
	input_eng_str = translateKorToEng(unicode(input_kor_str))
	print(input_eng_str)
	
	# 영어 TTS
	os.system("espeak -w before_srate_conv.wav \""+input_eng_str+"\"")
	os.system("sox before_srate_conv.wav -r 16000 after_srate_conv.wav")
	print("TTS and srate convert completed")
	
        # alexa
	askToAlexa()
	
	# 영어음성 STT
	os.system("sox response_alexa.mp3 -r 16000 response_alexa_converted.wav")
	output_eng_str = transcribe_file_eng('response_alexa_converted.wav')
	print(output_eng_str)
	
	# 영어문장을 한글로 번역
	output_kor_str = translateEngToKor(output_eng_str).encode("utf-8")
	print(output_kor_str)
	
	# 한글 TTS
	koreanTextToSpeech(unicode(output_kor_str))
	
	# 한글 음성 출력
	os.system("mpg321 korean_alexa.mp3") 

자 이제 한글로 얘기하면 한글로 대답해주는 코드가 완성되었다. 미국 대통령이 누군지 물어보자.







Open API와 python을 연동해보자

먼저 API로는 OpenWeatherMap API를 사용하도록 합니다 

http://openweathermap.org/api


먼저 위 링크를 타고 가면 아래와 같은 페이지가 나오는데,

위 페이지에서 API key 를 클릭합니다.







회원가입을 해야 API key를 받을 수 있기 때문에 회원가입을 하고,



회원가입 후 다시 API key를 받으면,




위와 같이 자신의 키를 받을 수 있습니다. 키를 사용하기까지 키를 받고 나서 10~60분 정도 걸린다고 하니, 안된다고 화내지말고 기다립니다. 다시 API 탭으로 돌아가서 API를 선택합니다.






현재 날씨를 사용할 것이기 때문에 Current weather data의 API doc을 클릭해서 사용법을 알아봅니다.







API 문서에 여러 요청방법들이 있지만, city name을 이용해 요청하는 방법만을 알아보겠습니다.

API call 에 보면

api.openweathermap.org/data/2.5/weather?q={city name}



이라 설명이 나와있고 사실 이 뒤에 자신의 키를 더 입력해야 합니다. 또한 섭씨로 온도를 받기 위해 units=Metric 라는 요청을 추가합니다.

api.openweathermap.org/data/2.5/weather?units=Metric&q={city name}&APPID={your API key}


위 코드에서  {city name}  대신 Seoul을 입력하고 {your API key} 대신 자신의 API키를 넣어서 크롬 주소창에 입력하고 이동해보면, 아래와 같은 JSON 형식의 답변이 오게 됩니다.

{"coord":{"lon":126.98,"lat":37.57},"weather":[{"id":721,"main":"Haze","description":"haze","icon":"50n"},{"id":701,"main":"Mist","description":"mist","icon":"50n"}],"base":"stations","main":{"temp":7.9,"pressure":1020,"humidity":45,"temp_min":4,"temp_max":10},"visibility":10000,"wind":{"speed":2.1,"deg":220},"clouds":{"all":80},"dt":1490435400,"sys":{"type":1,"id":8514,"message":0.008,"country":"KR","sunrise":1490390873,"sunset":1490435317},"id":1835848,"name":"Seoul","cod":200}



Python 에서 API 요청하고 답변받기



python에서 API를 요청하고 답을 받으려면  httplib2 라이브러리가 필요하기 때문에, 콘솔창을 킨 후 다음 명령어를 입력합니다.

$ python -m pip install httplib2


라이브러리를 설치 했으니 lPython 콘솔에 다음과 같은 코드를 입력합니다.

import httplib2
import json

url = 'http://api.openweathermap.org/data/2.5/weather?units=Metric&q='
city = 'Seoul'
mykey = '&APPID=5e19e0a4433cbb1b0a6e5f0e5b784af2'

h = httplib2.Http()
myrequest = url+city+mykey
response, content = h.request(myrequest, 'GET')
result = json.loads(content.decode('utf-8'))


다시 lPython 콘솔에 result를 입력하면 다음과 같은 출력이 나옵니다.

{'base': 'stations',
 'clouds': {'all': 75},
 'cod': 200,
 'coord': {'lat': 37.57, 'lon': 126.98},
 'dt': 1490433600,
 'id': 1835848,
 'main': {'humidity': 65,
  'pressure': 1018,
  'temp': 281.16,
  'temp_max': 283.15,
  'temp_min': 277.15},
 'name': 'Seoul',
 'sys': {'country': 'KR',
  'id': 8519,
  'message': 0.0154,
  'sunrise': 1490390875,
  'sunset': 1490435315,
  'type': 1},
 'visibility': 9000,
 'weather': [{'description': 'haze', 'icon': '50d', 'id': 721, 'main': 'Haze'},
  {'description': 'mist', 'icon': '50d', 'id': 701, 'main': 'Mist'}],
 'wind': {'deg': 320, 'speed': 1.5}}

result는 dictionary 형식으로 저장되어 있으므로, 우리가 원하는 정보만을 빼서 사용하겠습니다.

result 에서 "main"키의 값인 dictionary에서 습도('humidity'), 기온('temp'), 최고기온('temp_max'), 최저기온('temp_min')을 사용하고, 'weather'키에서 날씨('main')을 사용하겠습니다.



서울시의 날씨, 기온, 습도를 나타내는 코드를 다음과 같이 짜보았습니다.

# -*- coding: utf-8 -*-
"""
Created on Sat Mar 25 18:22:28 2017

@author: newkyu
"""

import httplib2
import json

url = 'http://api.openweathermap.org/data/2.5/weather?units=Metric&q='
city = 'Seoul'
mykey = '&APPID=5e19e0a4433cbb1b0a6e5f0e5b784af2'

h = httplib2.Http()
myrequest = url+city+mykey
response, content = h.request(myrequest, 'GET')
result = json.loads(content.decode('utf-8'))

humidity = result['main']['humidity']
temp = result['main']['temp']
temp_max = result['main']['temp_max']
temp_min = result['main']['temp_min']
weather = result['weather'][0]['main']

print('Seoul\'s weather is',weather)
print('Current temperature : ', temp,'°C')
print('Max     temperature : ', temp_max,'°C')
print('Min     temperature : ', temp_min,'°C')
print('Current humidity    : ', humidity,'%')


출력 결과는 아래와 같이 나오게 됩니다.



여태까지 한 것을 통해 서울, 도쿄, 런던, 뉴욕, 파리, 시드니, 나이로비의 현재 날씨와 온도를

보여주는 코드를 짜보았습니다.

# -*- coding: utf-8 -*-
"""
Created on Sat Mar 25 18:22:28 2017

@author: newkyu
"""

import httplib2
import json

url = 'http://api.openweathermap.org/data/2.5/weather?units=Metric&q='
cities = ['Seoul','Tokyo','London','Newyork','Paris','Sydney','Nairobi']
mykey = '&APPID=5e19e0a4433cbb1b0a6e5f0e5b784af2'

h = httplib2.Http()
for city in cities:
    myrequest = url+city+mykey
    response, content = h.request(myrequest, 'GET')
    result = json.loads(content.decode('utf-8'))
    
    humidity = result['main']['humidity']
    temp = result['main']['temp']
    temp_max = result['main']['temp_max']
    temp_min = result['main']['temp_min']
    weather = result['weather'][0]['main']
    
    print(city,'\'s weather is ',weather,sep='')
    print('Current temperature : ', temp,'°C')
    print('Max     temperature : ', temp_max,'°C')
    print('Min     temperature : ', temp_min,'°C')
    print('Current humidity    : ', humidity,'%\n\n')

출력결과

Seoul's weather is Haze
Current temperature :  6.87 °C
Max     temperature :  9 °C
Min     temperature :  4 °C
Current humidity    :  70 %


Tokyo's weather is Clouds
Current temperature :  6.92 °C
Max     temperature :  9 °C
Min     temperature :  5 °C
Current humidity    :  57 %


London's weather is Clear
Current temperature :  11 °C
Max     temperature :  12 °C
Min     temperature :  10 °C
Current humidity    :  50 %


Newyork's weather is Rain
Current temperature :  7.93 °C
Max     temperature :  13 °C
Min     temperature :  3 °C
Current humidity    :  61 %


Paris's weather is Clear
Current temperature :  12.5 °C
Max     temperature :  13 °C
Min     temperature :  12 °C
Current humidity    :  50 %


Sydney's weather is Clear
Current temperature :  23 °C
Max     temperature :  23 °C
Min     temperature :  23 °C
Current humidity    :  73 %


Nairobi's weather is Clouds
Current temperature :  28.45 °C
Max     temperature :  29 °C
Min     temperature :  28 °C
Current humidity    :  32 %


잘 나오는 것을 확인할 수 있습니다. 이제 API에 요청하고 답변받고, python과 연동하는 방법도 알았으니, 다른 API를 통해 자신이 만들고 싶은 프로그램을 만들 수 있을 겁니다. 아래 링크로 가보면 여러 Open API 들이 많으므로 사용해보시기 바랍니다.


https://www.data.go.kr/

+ Recent posts