LoginSignup
5
3

More than 5 years have passed since last update.

SORACOMで早口言葉練習(音声認識)

Posted at

スマホやパソコンだけでなく、IoTデバイスでもクラウドサービスの音声認識使ってみたいよね、ってことで『早口言葉の練習』をお題にして、Raspberry Piで音声認識をやってみた。
音声認識は、APIで使えるクラウドサービスRECAIUS、通信は、WiFi環境がなくても使えるSORACOMを使った。

環境

  • Raspberry Pi 2 Model B + LCDディスプレイ( KOOKYE LCD touch screen )
    • Python, Requests, PyAudio, Tkinter
  • 3G USBドングル ( AK-020 ) + SORACOM SIM
  • USBマイク ( MM-MCUSB16 )
  • USBマウス

環境_01.JPG

音声認識はRECAIUS

RECAIUS Developersのサイトでユーザ登録するとAPIが翌月末まで使えるIDとパスワードが発行されるので、それを使う(繰り返し登録することで延長可)。
https://developer.recaius.io

通信はSORACOM

RECAIUSはクラウドで音声認識するので、Raspberry Piで録音した音声ファイルを送ると、認識した結果がテキストで帰ってくる。
今回は、WiFi環境がなくても使えるように、SORACOMを使った。

音声認識の仕組み.jpg

実行スクリプト

以下の2つのスクリプトをデスクトップに用意しておき、順に実行する(アイコンを右クリックして"開く")。

  • connect_air.sh : SORACOM接続実行スクリプト
  • suiko.sh : 早口言葉練習「スイコ」実行スクリプト

画面_01.JPG

connect_air.sh
#!/bin/sh

sudo /usr/local/sbin/connect_air.sh

/usr/local/sbin/connect_air.shは、SORACOM公式のやり方
各種デバイスで SORACOM Air を使用する
でget。

suiko.sh
#!/bin/sh

cd /home/pi/recaius/python-recaius

./suiko.py

suiko.pyの中身は後述。

動作

  • suiko.shを実行するとGUIが立ち上がる

動作1_01.JPG

  • スタートボタンをクリックすると録音開始し、2秒後に録音停止する
    • この2秒間でお題の早口言葉を言う!

動作2_01.JPG

  • 録音停止後、RECAIUSにSORACOM経由で音声ファイルを送信する

動作3_01.JPG

  • 音声認識されたテキストファイルを受信して表示する(赤字のところ)
    • 早口言葉が正しく言えてたら(認識されていたら)お題と同じになる!

動作4_01.JPG

ぜんぜん言えてない・・・

コード

suiko.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from recaius.asr import RecaiusASR
from settings import ASR_ID, ASR_PASSWORD

import pyaudio
import wave

import sys
import Tkinter

import threading

def ClickStart(event):
  Button1.configure(state=u'disabled')
  Label4.configure(fg='blue', text=u'録音中...')
  Label4.pack()

  t_recording = threading.Thread(target=Recording)
  t_recording.start()


def Recording():
  CHUNK = 4096
  FORMAT = pyaudio.paInt16 #
  CHANNELS = 1             #
  RATE = 16000             #
  RECORD_SECONDS = 2       #
  WAVE_OUTPUT_FILENAME = "output.wav"

  p = pyaudio.PyAudio()

  stream = p.open(format=FORMAT,
                  channels=CHANNELS,
                  rate=RATE,
                  input=True,
                  frames_per_buffer=CHUNK)

  print("* recording")

  frames = []

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

  print("* done recording")

  stream.stop_stream()
  stream.close()
  p.terminate()

  print("* transrating")

  wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
  wf.setnchannels(CHANNELS)
  wf.setsampwidth(p.get_sample_size(FORMAT))
  wf.setframerate(RATE)
  wf.writeframes(b''.join(frames))
  wf.close()

  print("* done transrating")

  Label4.configure(fg='blue', text=u'認識中...辛抱強く待つのじゃ')
  Label4.pack()

  t_recognition = threading.Thread(target=Recognition)
  t_recognition.start()

def Recognition():
  rec = RecaiusASR(ASR_ID, ASR_PASSWORD)
  rec.set_lang('ja_JP')

  uuid = rec.login()

  # speech recognition from wave file
  result = rec.recognize(uuid, 'output.wav')

  rec.logout(uuid)

  print(result)
  if(result == ''):
    Label4.configure(fg='red', text=u'??? 認識できませんでした')
    Label4.pack()
  else:
    Label4.configure(fg='red', text=result)
    Label4.pack()

  Button1.configure(state=u'normal')

def ClickNext(event):
  global index
  index += 1
  index = index % 11

  if index == 0:
    Label2.configure(text=u'『 生麦 生米 生卵 』\n(なまむぎ なまごめ なまたまご)\n')
    Label2.pack()
  elif index == 1:
    Label2.configure(text=u'『 東京特許許可局 』\n(とうきょうとっきょ きょかきょく)\n')
    Label2.pack()
  elif index == 2:
    Label2.configure(text=u'『 青巻紙 赤巻紙 黄巻紙 』\n(あおまきがみ あかまきがみ きまきがみ)\n')
    Label2.pack()
  elif index == 3:
    Label2.configure(text=u'『 隣の客は よく柿食う 客だ 』\n(となりのきゃくは よくかきくう きゃくだ)\n')
    Label2.pack()
  elif index == 4:
    Label2.configure(text=u'『 庭には 二羽 鶏がいた 』\n(にわには にわ にわとりがいた)\n')
    Label2.pack()
  elif index == 5:
    Label2.configure(text=u'『 ジャズシャンソン歌手 』\n(じゃず しゃんそん かしゅ)\n')
    Label2.pack()
  elif index == 6:
    Label2.configure(text=u'『 新春シャンソンショー 』\n(しんしゅん しゃんそん しょー)\n')
    Label2.pack()
  elif index == 7:
    Label2.configure(text=u'『 除雪車除雪作業中 』\n(じょせつしゃ じょせつ さぎょうちゅう)\n')
    Label2.pack()
  elif index == 8:
    Label2.configure(text=u'『 李も桃も桃のうち 』\n(すももも ももも もものうち)\n')
    Label2.pack()
  elif index == 9:
    Label2.configure(text=u'『 竹藪に 竹立てかけた 』\n(たけやぶに たけ たてかけた)\n')
    Label2.pack()
  elif index == 10:
    Label2.configure(text=u'『 坊主が 屏風に 上手に 坊主の絵を描いた 』\n(ぼうずが びょうぶに じょうずに ぼうずのえをかいた)\n')
    Label2.pack()

  Label4.configure(text=u'')
  Label4.pack()

root = Tkinter.Tk()
root.title(u"SUIKO - スイコ")
root.geometry("{0}x{1}+0+0".format(root.winfo_screenwidth(), root.winfo_screenheight()))
root.configure(bg=u"White")
#root.overrideredirect(True)

Label1 = Tkinter.Label(fg='Blue', font=('FixedSys', '20'), text=u'\n2秒以内で言うのじゃ\n')
Label1.configure(bg=u"White")
Label1.pack()

# お題
index = 0
Label2 = Tkinter.Label(text=u'『 生麦 生米 生卵 』\n(なまむぎ なまごめ なまたまご)\n')
Label2.configure(font=('FixedSys', '14'))
Label2.configure(bg=u'White')
Label2.pack()

Button1 = Tkinter.Button(text=u'スタート')
Button1.bind("<Button-1>",ClickStart) 
Button1.pack()

# 空行
Label3 = Tkinter.Label(text=u'')
Label3.configure(bg=u"White")
Label3.pack()

# 結果
Label4 = Tkinter.Label(text=u'')
Label4.configure(font=('FixedSys', '14'))
Label4.configure(bg=u"White")
Label4.pack()

# 空行
Label5 = Tkinter.Label(text=u'')
Label5.configure(bg=u"White")
Label5.pack()

Button2 = Tkinter.Button(text=u'次のお題')
Button2.bind("<Button-1>",ClickNext) 
Button2.pack()

root.mainloop()

Maker Faire Tokyo 2016で展示した

つくるラボ

MFT_01.JPG

現状では、結果が表示されるまでに、10秒程度かかってしまう。
音声ファイルへの変換、音声ファイルの送信に時間がかかっている。
2秒間の録音後、音声ファイルへの変換を開始、変換完了後に送信を開始しているので、これを数ミリ秒区切りで、マルチスレッドで実行できるようにすれば、もう少し速くなるかもしれない。
ローカルで音声認識するリソースがなかったり、頻繁に音声認識を使わず、結果の表示までの時間をうまく隠せる使い方があれば、今回つくったような音声認識の環境が使えそう。

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3