Leverages データ戦略ブログ

インハウスデータ組織のあたまのなか

「AI文字起こし妖精さん」について

レバレジーズのデータ戦略室で室長をしている阪上です。今回はレバレジーズの運営するメディアの取材における課題について紹介したいと思います。

課題

レバレジーズが運営しているメディアで取材が数多く行われているのですが、取材音声の文字起こしをこれまで人手のみで行なっていました。1時間の取材の場合、1時間以上に文字起こしに時間がかかったりするため、記事を書く上での重要な情報資源ながら、人に対する負担が大きい状態でした。そこで、現場の悩みを解決したいと思いました。

仕組みの説明

まず、求められる要件を以下の通りです。

求められる要件

  • 文字起こしをして欲しい。
  • Googleドライブにアップロードしたら自動で文字起こしされ、結果もGoogleドライブに返して欲しい。
  • 文字起こし結果を一定の文字数で改行して欲しい
  • 朝の8時から夜の21時までは処理を受け付けて欲しい、1~2時間以内に処理結果が欲しい
  • 様々なファイル形式で処理したい
  • 完了したら通知もして欲しい

それでは要件を一つずつクリアしていきます。
(基本的にPythonやらGCPやらを使います) f:id:DataStrategyOffice:20210714191242p:plain

要件1:「文字起こしをして欲しい。」

解決策:文字起こし用のAPIは色々なものがあるのですが、過去に活用した実績があることからGCPSpeech-to-TextAPIを採用しました。比較的、安価に文字起こしをすることができます。

発話のタイムスタンプが返されたり、話者分離もできたり、識別の性能を高めるヒント機能があったりするのが魅力的です。
なお、文字起こし自体はGCEでインスタンスを立ち上げ、処理依頼がくればAPI実行用ファイルをキックし、GCSに置いておいた音声ファイルを文字起こしするようにしています。

要件2:「Googleドライブにアップロードしたら自動で文字起こしされ、結果もGoogleドライブに返して欲しい。」

解決策:Googleドライブのファイルをダウンロードしたり、アップロードしたりできるPythonのライブラリとしてpydriveを採用しました。認証の設定をGCPの管理画面で設定さえすれば、かなり簡単な記述でGoogleドライブにアクセスできるようになります。

要件3:「文字起こし結果を一定の文字数で改行して欲しい」

解決策:Speech-to-Textを使って返される結果(下図)に発話のタイムスタンプがあるのですが、その発話のタイムスタンプをもとに、指定の秒数単位で改行されるようにしました。

以下はサンプルデータとしてドンキホーテのテーマソングの冒頭部を文字起こししたものです。このようなタイプスタンプ付きの文字起こし結果をデータフレーム形式にして指定の秒数で改行するように前処理しました。 f:id:DataStrategyOffice:20210714191933p:plain

要件4:「様々なファイル形式で処理したい」

解決策:FFmpegを使って様々な音声ファイルないし動画ファイルに対してWAVファイルになるように変換をしています。Pythonのsubprocessモジュールを使って、FFmpegを直接実行しています。FFmpegでは他にも、Cloud-Speech-To-Text-APIをうまく動作させるために、サンプリング周波数を44100に変えたり、モノラルにしたりする機能があります。後述しますが、ハイパスフィルターなどの機能も使うことで文字起こし精度を高めています。

要件5:「完了したら通知もして欲しい」

解決策:Slackの通知をIncoming-Webhookという外部ツールからSlackにメッセージを投稿する方法を使ってできるようにしました。Pythonjson形式で文言を作って送るだけなので非常に簡単です。 ただ、無機質な投稿になるとなんだか寂しいので、「AI文字起こし妖精さん」という名前を今回のツールに付けることにしました。妖精さんが夜中に勝手に仕事をしてくれるイメージで命名しました。 f:id:DataStrategyOffice:20210714192120p:plain なぜか皆さん、通知にスタンプを押してくれます。それなりの頻度で通知が飛んでいくので、飽きがこないように季節に応じて通知内容をいじっていたりしますが、それも利用者の皆さんに喜ばれているようです。

やっていることまとめ

  • Linuxサーバで定期実行
  • pydriveでGoogleドライブから音声ファイルを取得
  • FFmpegで音声ファイルの処理
  • GCSのバケットに音声ファイルをアップロード
  • GCEで文字起こしAPIを定期実行
  • GCSに吐き出された文字起こし結果を前処理し、Googleドライブにアップロード
  • Slackで通知を飛ばす

精度低い問題

実際に文字起こしをしてみた結果、以下の2つの精度上の問題がありました。

1つ目の問題は「出現頻度の低そうなフレーズの音声認識が低い」、
2つ目の問題は「音声にノイズが多くて音声をそもそも認識できない」 となります。

まず1つ目の問題に関しては、API音声認識の際のヒントを指定できるtypes.SpeechContext関数のphrasesオプションを使いました。

5,000件まで登録できるので、できる限りたくさん登録しておくと良いと思います。かなり具体的な表現を記さない限り反映されない印象です。実際、「1 フレーズあたりの文字数」が100文字までとあるので、かなり具体的な表現を登録していくスタイル前提なのではないかと思います。私はこの作業を通じて、自然言語処理における形態素解析エンジンの辞書登録を思い浮かべました。

なお、この機能を使って「派遣」というキーワードが「発見」になってしまうケースはかなり緩和できたかなと思います。

続いて、2つ目の問題についてですが、録音環境によってノイズが多く、そもそも音声として認識されない問題となります。
この際、まずは問題の所在を明らかにしたいので、Audacityというオープンソースの音声解析ソフトを使ってみました。
文字起こしがうまくいった音声とうまくいかなった音声の比較をAudacityで行なったのですが、音声波形を可視化することで違いがありました。

文字起こしができているケース
f:id:DataStrategyOffice:20210714192512p:plain

文字起こしができていないケース f:id:DataStrategyOffice:20210714192602p:plain

色々な音声で比較したのですが、文字起こしができていない音声に共通して音声波形が密に繋がっているケースが観察されました。実際に音声を聞いてみると音割れに近い状態でした。

一度割れてしまった音声を元に戻すことはなかなか難しいのですが、試行錯誤の結果、ハイパスフィルターやローパスフィルターという音声のノイズ除去の手段を使い、閾値の上限と下限を調整することで音声認識できるケースがあることがわかりました。 そのため、FFmpegでの音声処理の際はハイパス・ローパスフィルターを調整することで、可能な限り音声認識率を上げています。

最後に

以上は音声文字起こしの取り組みになりますが、このツールはすでに500件以上の文字起こし処理を行い、かなり活用してもらえています。1記事あたりの文字起こしにかかる工数を減らすことに成功しています。

長期的に、さらなる精度向上を目指したいと思います。

参考情報

https://cloud.google.com/speech-to-text/quotas?hl=ja#content