Google Cloud Speech-to-Textで音声認識

やりたいこと

Google Cloud Speech-to-Textを音声ファイル(.wav)にかけたい。

iOS/macOS標準のSpeechフレームワークでは日本語の認識精度が出なかったため、もっと精度が良いとされるCloud Speech-to-Textを試す。

結論

まずはいきなり結論から書くと、個人的所感としては、良さそう

そのまま字幕や書き起こしテキストとして使えるレベルではないが、Speechフレームワークだと何も結果が出ない区間もちゃんと結果を出してくれていて、ベターではあるという感じ。

認識結果の例

対象はこちらの動画の冒頭50秒ぐらいの音声。僕と友人のトークをスマホで録音しただけの音声なので音声認識対象としては難しい部類にはいると思う。

Cloud Speech-to-Textの結果:

さっそくあの話の続きから行こうと思うんですけど前回までのおさらいとしてゲストで来てくれてる梅ちゃんは個人アプリ開発者で貴重な数少ないその関係で食べていってる個人個人アプリ開発者ですとまぁ自分が欲しいとコンテンツを音声で読み上げてくれる長生きできるデパート山本確定申告向けの景品昔なんかこの俺 Podcast である前に教えてもらった後しかさんとかやってる音消すとしてとしてそうそうあれもすごい面白いけど遊んでもいい

Speechフレームワークの結果:

早速あの話の続きから行こうと思うんですけど何かまでのおさらいとしてえとゲストで来てくれてるうめちゃんは個人アプリ開発者で貴重な数少ないそのツール系で食べて言ってる個人から個人アプリが欲しいとコンテンツを音声で読み上げの確定申告の景品ここっての爆速でできる子の音と交わした後強いキャッシュであのーはいネクストステップステップ注がれます

もう一例、こちらの動画の冒頭50秒の音声でも試してみた。

Cloud Speech-to-Textの結果:

始まりました今日は初めての人に来てもらいましたか木村さんですよママさんはアプリ開発者なんだけどいい PKP パンチパンチキックパンチっていうゲームアプリを一人でデザインプログラム音楽何ですかねまあ後テキストに備え付け汚いですね本当は本当はないので本当とかなんか本当はそのゲームにまつわるもの全部全部一人でやって作ってね日本でもヒットしてアメリカにもなんか駄目だちょっと一回一回きっと今何10分ぐらい赤ちゃん寝てくれてさっき話したのがしまさんが ppkp パンチパンチキックパンチでアプリを作って日本とアメリカで言って

Speechフレームワークの結果:

はい始まりました今日は初めての人に来てもらいましたが木村さんです思うとまださんはアプリ開発者なんで0ピピ9品パンチパンチキックパンチって言うゲームアプリを1人でデザインプログラムほんととか学ぶものは全部全部1人でやってましてAAアメリカにも何か好き1度前貴ちゃん寝てくれてさっき話したのが島田さんアプリを作ってて日本

実装のハマりどころメモ

公式リポジトリの「Cloud Speech Nonstreaming gRPC Objective-C Sample」というサンプルをベースに試したのだけど、API Keyをつくってビルドするだけ、とはいかなかった。

なお、サンプルがObjective-CベースなのでここでもObjCベースで記載する。(Swiftサンプルもリポジトリにはあるがなんとなくあんまりメンテされてなさそうな気配がしたので試してすらいない)

音声ファイルを認識できるようにする

サンプルはiPhoneのマイクから録音した音声を認識する前提で実装されている。これを音声ファイル(.wav)から認識できるようにするには、以下のようにAVAudioFileとしてファイルを読み込み、

AVAudioFile *audioFile = [[AVAudioFile alloc] initForReading:audioFileUrl error:nil];
AVAudioPCMBuffer *pcmBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:audioFile.processingFormat frameCapacity:(AVAudioFrameCount)audioFile.length];
[audioFile readIntoBuffer:pcmBuffer error:nil];

AVAudioFileをNSDataに展開する。

こういうメソッドを用意しておいて、

- (NSData *)bufferToNSData:(AVAudioPCMBuffer *)buffer {
    return [[NSData alloc] initWithBytes:buffer.floatChannelData[0] length:buffer.frameLength * 4];
}

こうやって呼ぶ。

self.audioData = [self bufferToNSData:pcmBuffer];

ペイロードサイズの制限

最初に上のコードを実行してみたところ、こういうエラーになった。

Request payload size exceeds the limit: 10485760 bytes

ペイロードサイズの上限が10485760 bytesらしい。

このときに渡したwavファイルは2分強あったので、ちょっと短くしてまた試してみた。

1分の制限

適当に短くしたファイルを読み込んでAPIに送ると次のようなエラーが出た。

Sync input too long. For audio longer than 1 min use LongRunningRecognize with a 'uri' parameter.

なんと、Speechフレームワークと同じくこちらも1分の制限があるのか。(「まずサンプルを試そう」という一歩目なのでドキュメントはまだ読んでない)

オーディオフォーマットの制限

しかし、適当に短くしたファイルの再生時間を改めて見てみると30秒ぐらいしかなかった。

これはどうやらファイルフォーマットの指定が間違ってそうだとピンと来て、APIの設定を見直してみた。サンプルレートはちゃんと修正して指定していたのだが、ここが怪しい:

ここから先は

836字
文章やサンプルコードは多少荒削りかもしれませんが、ブログや書籍にはまだ書いていないことを日々大量に載せています。たったの400円で、すぐに購読解除してもその月は過去記事もさかのぼって読めるので、少しでも気になる内容がある方にはオトクかと思います。

技術的なメモやサンプルコード、思いついたアイデア、考えたこと、お金の話等々、頭をよぎった諸々を気軽に垂れ流しています。

最後まで読んでいただきありがとうございます!もし参考になる部分があれば、スキを押していただけると励みになります。 Twitterもフォローしていただけたら嬉しいです。 https://twitter.com/shu223/