GCPのNatural languageとSpeechAPIを連携してPepperに感情分析させる

##概要
以前、[GCPと連携してPepperに音声ファイル分析機能を搭載](https://qiita.com/cuiyiming/items/fc2cfeccc88dff2463fb)で聞き取った音声の文字起こしの方法を紹介して、[GCPと連携してPepperに感情分析機能を搭載](https://qiita.com/cuiyiming/items/0ab093290f781f9a55be)で文章から感情を分析する方法を紹介しました。

今回の記事では、これらを連携して喋った言葉をそのまま感情分析するプログラムをご紹介いたします。前回の2記事同様、PythonSDKを用いて実装しています。


##ソースコード

```python:sample.py
# encoding:UTF-8
import sys
import time

#googleSpeechAPI用
import base64
from googleapiclient import discovery
import httplib2

import requests
from naoqi import (ALProxy, ALBroker, ALModule)

PEPPER_IP = "192.168.100.32"
WAVE_OUTPUT_FILENAME = "pepper_record.raw"

#音量調整
audio = ALProxy("ALAudioDevice",PEPPER_IP,9559)
audio.setOutputVolume(30)

#APIのURL情報
DISCOVERY_URL = ('https://{api}.googleapis.com/$discovery/rest?'
                 'version={apiVersion}')

#APIキーを設定
key = "AIzaSyDzK8sPP1z5V-vaf3AqOXVMW3QDG7kGdvg"

#インスタンスを生成
tts = ALProxy("ALTextToSpeech",PEPPER_IP,9559)

PepperModule = None
memory = None

class PepperModuleClass(ALModule):
    def __init__(self, name):
        ALModule.__init__(self, name)
        #
        self.BIND_PYTHON( self.getName(),"callback" );
        self.tts = ALProxy("ALTextToSpeech", PEPPER_IP, 9559)
        #
        print "PepperModule Initialyze"

    def startRecord(self):
        self.tts.say("何か話しかけてね")
        #
        # ファイルの保存先設定
        self.saveFile = open(WAVE_OUTPUT_FILENAME,"wb")
        self.pepperMicrophone = ALProxy("ALAudioDevice", PEPPER_IP, 9559)
        #
        # 16KHzのモノラル音声でFront(3)マイク１つのみを指定
        self.pepperMicrophone.setClientPreferences(self.getName(), 16000, 3, 0)
        #
        # 録音開始
        self.pepperMicrophone.subscribe(self.getName())

    def processRemote(self, inputChannels, inputSamples, timeStamp, inputBuff):
        # 録音バッファを保存
        self.saveFile.write(inputBuff)

    def stopRecord(self):
        # 録音終了
        self.pepperMicrophone.unsubscribe(self.getName())
        time.sleep(1)
        self.tts.say("分析中だよ")
        self.saveFile.close()


#APIの情報を返す関数
def get_speech_service():
    http = httplib2.Http()
    return discovery.build(
        'speech', 'v1', http=http, discoveryServiceUrl=DISCOVERY_URL, developerKey=key)

def SpeechAPI():
    #音声ファイルを開く
    with open(WAVE_OUTPUT_FILENAME, 'rb') as speech:
        speech_content = base64.b64encode(speech.read()) 

    #APIの情報を取得して、音声認識を行う
    service = get_speech_service()
    service_request = service.speech().recognize(
        body={
            'config': {
                'encoding': 'LINEAR16',
                'sampleRateHertz': 16000,
                'languageCode': 'ja-JP', #日本語に設定
                'enableWordTimeOffsets': 'false',
            },
            'audio': {
                'content': speech_content.decode('UTF-8')
                }
            })

    #SpeechAPIによる認識結果を保存
    response = service_request.execute()

    resText = ""
    #ペッパーに録音した文章を喋らせる。
    for i in response["results"]:
        #tts.say(i["alternatives"][0]["transcript"].encode("utf-8"))
        resText += i["alternatives"][0]["transcript"].encode("utf-8")

    return resText


def senti(text):
    #APIのurl情報
    url = 'https://language.googleapis.com/v1/documents:analyzeSentiment?key=' + key

    #各種設定
    header = {'Content-Type': 'application/json'}
    body = {
        "document": {
            "type": "PLAIN_TEXT",
            "language": "JA",
            "content": text
        },
        "encodingType": "UTF8"
    }

    #分析結果の格納
    response = requests.post(url, headers=header, json=body).json()

    #こちらが話した内容によってペッパーの反応を変更
    #ポジティブな内容のとき
    print(response["documentSentiment"]["score"])
    if response["documentSentiment"]["score"] >= 0.5:
        tts.say("なんだかすごく嬉しそうだね！")

    #普通の内容のとき
    elif response["documentSentiment"]["score"] < 0.5 and response["documentSentiment"]["score"] >= 0:
        tts.say("じゃあ何かいいことがあるといいね！")
    #ネガティブな内容のとき
    else:
        tts.say("なんだか元気がないぞーーー！！")

def main():
    myBroker = ALBroker("myBroker","0.0.0.0",0,PEPPER_IP,9559)

    global PepperModule
    PepperModule = PepperModuleClass("PepperModule")

    try:
        print "録音開始"
        PepperModule.startRecord()
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print "録音終了"
        PepperModule.stopRecord()
        myBroker.shutdown()
    text = SpeechAPI()
    senti(text)

if __name__ == "__main__":
    main()
```

keyとペッパーのIPアドレスを入れて、プログラムを実行するとペッパーが「何か話しかけてね」と喋ります。コントロール+cによって録音を終了させることができ、録音中に話した内容によってペッパーのその後の反応が変わります。

##まとめ
このプログラムを改変することで、様々なシチュエーションでの音声による感情分析が実装できそうです。また今回は音声の文字起こしもGCPを利用しましたが、[ペッパーが任意の言葉を認識するためのダイアログトピックの使い方](https://qiita.com/cuiyiming/items/021911eeb531a1b4582c)を利用することによって、SpeechAPIを使わないで行うことも可能です。

興味がある方がいらっしゃいましたら、こちらも是非お試しください。

by アトリエスタッフ