読者です 読者をやめる 読者になる 読者になる

StatsFragments

Python, R, Rust, 統計, 機械学習とか

R で Google Speech API を使ってこっそりがんばりたい

この記事は R Advent Calendar 2014 (ATND) の26日目の記事です。


こういう話がある。

すばらしいパッケージだ。特に yeah::zoi はよい。これを使えば今日も一日頑張れそうな気がする。

library(yeah)
yeah::zoi()

しかし、この関数は 周りに人がいる場合は 利用に若干のさしさわりがある。テキストで表示したら?とも思うが、ただの代替テキスト表示ではなんか味気ないし、パッケージに新しい関数が追加された場合に即座に楽しめない。なんとかする方法はないだろうか、、、?

少し考えた結果、Google音声認識 API である Google Speech API を使うことにした。音声ファイルを認識 -> テキスト化して表示すれば、周りに人がいる場合もこっそり何度でも楽しめるし、新しい関数が追加されてもすぐに追従することが可能だ。

Google Speech API 利用手順

Google Speech API を利用するには、以下2つの手続きが必要。

Chromium Dev group への参加

Chromium Dev group へアクセスしてグループに join する。これをやっておかないと、Google Developer Console の API 一覧に Speech API が表示されない。

参考: Google Speech API V2 - Stack Overflow

Google Developer Console での API 有効化 & KEY 取得

手順は以下に記載されている。

.flac ファイルの準備

Google Speech API へは .flac ファイルを送る必要があるようだ。ffmpeg でも何でも 好きなものを使って変換する。

ffmpeg -i zoi.wav -vn -ac 1 -ar 16000 -acodec flac zoi.flac

補足 R のライブラリパスは .Library で確認できる。この中から yeah/sounds/ ディレクトリを探す。

.Library
# [1] "/Library/Frameworks/R.framework/Resources/library"

プログラム

上記リンクに記載されている Python のサンプルプログラムを参考に。 まず Google Speech API からレスポンスを取得するところまで。

library(jsonlite)
library(httr)

fname <- 'zoi.flac'
apikey = '<your API key>'

url <- paste0('https://www.google.com/speech-api/v2/',
              'recognize?xjerr=1&client=chromium&lang=ja-JP',
              '&maxresults=10&pfilter=0&xjerr=1&key=', apikey)

r <- POST(url, content_type('audio/x-flac; rate=16000'), body = upload_file(fname))

返り値は json 形式になる。が、レスポンス中の json データには root が 2つあるため、{httr} が内部で利用している {jsonlite} ではパースに失敗してエラーになってしまう。

content(r, encoding = 'utf-8')
# Error in parseJSON(txt) : parse error: trailing garbage
#                          {"result":[]} {"result":[{"alternative":[{"tr
#                      (right here) ------^

中身を表示したければ、明示的に type = 'text' を指定して文字列としてパース & 表示する。音声が聞けないのは やはりちょっと寂しい、、、。が、そのぶん認識結果の候補が 複数 出てくるので たくさんがんばれる気がする。

txt <- content(r, type = 'text', encoding = 'utf-8')

# ※出力は適当に整形
txt 
# [1] "{\"result\":[]}\n
# {\"result\":[{\"alternative\":
# [{\"transcript\":\"今日も1日頑張るぞい\",\"confidence\":0.84639674},
#  {\"transcript\":\"今日も1日頑張るぞ\"},
#  {\"transcript\":\"今日も1日頑張るぞぃ\"},
#  {\"transcript\":\"今日も一日頑張るぞ\"},
#  {\"transcript\":\"今日も一日がんばるぞぃ\"},
#  {\"transcript\":\"今日も1日がんばるぞぃ\"},
#  {\"transcript\":\"今日も1日頑張るぞオイ\"},
#  {\"transcript\":\"今日も一日がんばるゾ\"},
#  {\"transcript\":\"今日も一日がんばるぞオイ\"},
#  {\"transcript\":\"今日も1日がんばるゾ\"}],
# \"final\":true}],\"result_index\":0}\n"

結果を data.frame として取得したければ、文字列置換で valid な json フォーマットにしてから jsonlite::fromJSON

library(stringr)
jobj <- fromJSON(paste0('[', stringr::str_replace(txt, c('\n'), c(",")), ']'))
jobj['result'][[1]][[2]]['alternative'][[1]][[1]]
#                  transcript confidence
# 1       今日も1日頑張るぞい  0.8463967
# 2         今日も1日頑張るぞ         NA
# 3       今日も1日頑張るぞぃ         NA
# 4        今日も一日頑張るぞ         NA
# 5    今日も一日がんばるぞぃ         NA
# 6     今日も1日がんばるぞぃ         NA
# 7     今日も1日頑張るぞオイ         NA
# 8      今日も一日がんばるゾ         NA
# 9  今日も一日がんばるぞオイ         NA
# 10      今日も1日がんばるゾ         NA

まとめ

Google Speech API を使うことによって、周りを気にせず がんばるぞい 可能な環境を構築することができた。