(Qiitaの記事と同様のものを、カノニカルを設定して投稿しています。)
先日、VTuber Chat TrendsというWebアプリケーションをリリースしました。こちらは、VTuberの皆さんの、過去のYouTube Live内チャットで発言された内容をもとに、どのようなキーワードが頻出したかをトレンド情報として閲覧できるものとなっています。良かったらご利用ください。
VTuber Chat Trends を公開しました!VTuberのライブ配信内チャットで話題になったワードを解析し、公開していますhttps://t.co/sBt5hDUdMj(現在対応しているVTuberは #にじさんじ #ホロライブ #のりプロ など)#VTuber #VTuberChatTrends
— フォースアップ (@4thapp) April 25, 2021
本記事では、中でどんなことをやっているのかを簡単にまとめます。(途中、自然言語処理や、Webアプリケーションに関する用語が出てきます。各用語についての説明は割愛いたしますのでご了承ください)。
おもに、チャットデータの解析を担当しています。やっていることは以下のとおり。
Python3で実装し、GCPのCompute Engine(仮想マシン)で動作させています。徹底的にコストを抑えるために、スペックはf1-microとしています。(本来であれば、すべてAzureに揃えたかったし、仮想マシンよりコンテナとかで運用したかった。)
残念ながら、この世の全VTuberの配信を解析することは、我々の経済的に無理であるため、あらかじめ解析の対象とする配信者をマスタデータとして保持しておき、定期的にチャンネル情報・配信情報を取得しています。(2021/4/25現在、約160名の方に対応しています)。取得したデータはAzure Table Storageへ格納します。Table Storageは、NoSQLデータベースであるCosmosDBと同じようなサービスですが、「できるだけコストを抑えたい」「高いSLAは求めていない」といった点から、Table Storageをデータベースとして利用しています。
また、新しい配信が行われた場合は、(2)の解析が必要ですが、仮想マシンリソースの関係上、一度に複数の配信の解析ができないため、Azure Queue Storageを使用して、解析リクエストの順番待ちをさせています。
VTuber Chat Trendsの要となる部分です。
基本的には、配信内の単位時間当たりの出現頻度が多いワードをトレンドワードとしました。1回の配信を100区間に分割し、区間ごとに頻度集計しています。よって、配信全体での出現頻度は低くても、瞬間的に頻出した場合は上位のトレンドとなるようにしています。
上図の場合、「うまぴょい」のほうが「草」よりも上位となります。
本記事ではさきほどからワードという言葉を使っていますが、今回は、基本的に形態素解析の結果のみを使用し、形態素の単位をワードの単位としました。
しかし、より自然にトレンドワードを抜き出すのであれば、形態素解析の結果をもとにN-gramをとったり、構文解析等をして、基本句を単位としたほうがいいのかなぁと考えています。一応試してみたりもしたのですが、ここでも仮想マシンのリソースの関係上、メモリ不足に陥ってしまったため、今回は断念しました。ここらへんは、今後スペック問題が解決できそうなら、改善したいです。もうちょっとちゃんと自然言語処理させたい。
(2021/5/28追記: 現在は、gensimを併用し、頻出のフレーズを取りやすくしています。)
形態素解析器には、Sudachiを採用しました。新語の観点から、MeCab+NEologdとも迷いましたが、YouTubeチャットを解析させると、NEologdでは不自然な形態素の区切りが目立ったため、Sudachiを採用しました。
多くのVTuberの配信チャット内では、特有の挨拶などの未知語が数多く出現し、そのままだと形態素解析に支障が出るため、Sudachi用のユーザ辞書を作成しました。現状は完全手動で作成しています。
こんにちワニノコ,5687,5687,-32768,こんにちワニノコ,感動詞,一般,*,*,*,*,コンニチワニノコ,こんにちワニノコ,*,*,*,*,*
こんばんワニノコ,5687,5687,-32768,こんばんワニノコ,感動詞,一般,*,*,*,*,コンバンワニノコ,こんばんワニノコ,*,*,*,*,*
おつみと,5687,5687,-32768,おつみと,感動詞,一般,*,*,*,*,オツミト,おつみと,*,*,*,*,*
おつみとー,5687,5687,-32768,おつみとー,感動詞,一般,*,*,*,*,オツミトー,おつみと,*,*,*,*,*
わたくせ,5146,5146,-32768,わたくせ,名詞,普通名詞,一般,*,*,*,ワタクセ,わたくせ,*,*,*,*,*
なお、形態素解析をする前に、以下の前処理を行っています。
~
など)をー
に正規化形態素解析後は、以下の後処理を行っています。
形態素解析の結果をもとに、先述の「なにをもってトレンドワードとするか」に従って頻度解析し、結果を、Azure Blob Storageへ格納しています。
ユーザクライアントからのWebAPIリクエスト処理や、定期ツイート処理を担当しています。やっていることは以下のとおり。
メインは、Azure Functionsを使って実装しました。ランタイムはNode.js、コードの記述にはTypeScriptを使用しました。
HTTPリクエストをトリガーとして、Blob StorageやTable Storageから、各種情報を取得し、レスポンスする、きわめてシンプルな関数です。
Azure Functionsには、トリガーとは別にバインドという概念があり、コード内で各種Storageのクライアントライブラリをインポートしなくてもデータを取得できるため、できるだけシンプルなコードとするために、バインドを活用するようにしました。しかし、やりたいことによっては、バインドだと実現不可能な場合がある(例:Table Storage出力バインディングは、既存エンティティの書き換えには対応していない)ため、結局、クライアントライブラリも混在する形となりました。
WebAPIの利用にあっては、ユーザクライアント⇔Azure Functions間で直接やり取りする構造にはせず、あいだにAzure CDNをかませ、一定時間はキャッシュさせるようにしました。
Azure FunctionsのTimerトリガーを使って、最近の配信を解析結果を定期的にツイートさせるようにしました。おそらく、Twitter APIを使ってツイートするのが一般的ですが、とりあえずお手軽に動作させたかったため、Azure Logic Appsを併用して、ツイート処理ができるようにしました。Twitter APIへの申請は不要となりますが、投稿クライアント名が「Microsoft Azure Logic Apps」になるので少しダサい。
いずれは、きちんとTwitter API申請したいです。
(2021/5/5追記) Logic Appsを使用する方法を廃止し、Twitter APIを使用する方法へ変更しました。
なお、リリース直後、この定期ツイート処理をまわしていると、あるタイミングから以下のようなエラーがTwitterから返ってくるようになり、ツイートできなくなってしまいました。
{
"status": 403,
"message": "This request looks like it might be automated. To protect our users from spam and other malicious activity, we can't complete this action right now. Please try again later.\r\nclientRequestId: hogehoge\r\nserviceRequestId: hogehoge",
"error": {
"message": "This request looks like it might be automated. To protect our users from spam and other malicious activity, we can't complete this action right now. Please try again later."
},
"source": "twitter-je.azconn-je.p.azurewebsites.net"
}
Webブラウザからも、ツイート、フォロー、リツイートなどをしようとすると「このリクエストはコンピュータによる自動的なものと判断されました」というエラーが表示され、スパムとして扱われロックされてしまっていることが分かりました。最初のエラーから24時間経過後も、状況が変わらなかったため、Twitterの異議申し立てフォームから、問い合わせを行いました。(問い合わせ後、自動メールに対する返信も実施)。幸い、問い合わせから約36時間後に、以下のようなメールが来て、ロックも解除していただけました。
ご利用のアカウントのロックが解除されました。ご不便をおかけして申し訳ありませんでした。
手短に状況を説明いたしますと、Twitterでは、スパムを自動生成するTwitterアカウントを検出して削除するシステムを採用しています。今回、システムがこちらのアカウントをスパムアカウントと誤認識した可能性があります。このような誤認識は、Twitterルールに違反する自動化の挙動の見られるアカウントに対して起こることがあります。
誤認識をお詫びいたしますとともに、またのTwitterのご利用をお待ちしております。
Webのフロントエンドです。フレームワークにはNuxt.js、Vuetifyを使用し、SSRやSPAではなくSSG(Static Site Generation; 静的サイト生成)の方式でビルドしています。
基本的に中でやっていることは、APIリクエストして、返ってきたデータを加工・表示しているだけです。
SSGですので、静的ホスティングサービスを利用すればリリースできます。NetlifyやHerokuあたりが有名でしょうか。今回は、なるべくリソースをAzureに統一させたかったということもあり、Azure Static Web Appsを利用しました。まだプレビュー版ですので、本番運用には向かないのですが、プレビュー版の間は無料で利用できるため、お世話になろうと思いました。
現状、Static Appsは、GitHub Actions等のCI/CDでのデプロイにしか対応していませんので、VTuber Chat Trendsもユーザクライアント部分についてはデプロイを自動化させました。
各配信のページには、トレンドワードを上位から順に表示させています。(順位については、「なにをもってトレンドワードとするか」のセクションで述べたとおりです)。
各ワードには、どのような言い回しをされたかの情報や、配信内のどのタイミングで頻出したかのグラフを出しています。
グラフ表示には、Google Chartsを使用しました。最初はChart.jsを採用しようとしたのですが、グラフ内をクリックした際の制御がどうしても上手くいかず、乗り換えました。個人的に、描画されるグラフの見た目はChart.jsのほうがきれいだったのですが。。。
せっかくなのでnuxt/i18nライブラリを使ってi18nに対応させ、日本語だけでなく英語でも利用できるようにしています。(といっても、トレンドワードは日本語のままです)。使い方や利用規約のページは未対応ですが、基本的なUI部分は英語でも表示可能です。翻訳が非常に怪しいため、誤り等ありましたら教えていただけますと幸いです。
ページ右下から切り替え可能です。
Nuxt.jsの魅力の1つに、簡単にPWA(Progressive Web Apps)に対応できる点が挙がると思っています。VTuber Chat Trendsも、より利用者に気軽に使っていただけるよう、PWAに対応させています。スマホブラウザからサイトを表示した際に、「インストールはいかが?」といった旨のメッセージが表示されます。インストールすると、今後はブラウザでなくても、ホーム画面からサイトを表示できます。
VTuberの配信内チャットのトレンドワードを解析し、閲覧できるサイトを作成しました。現状は、形態素解析した結果のヒストグラムをとって並び替えてトレンド情報として格納し、ユーザはブラウザから閲覧する、というシンプルな構造になっています。前半の解析処理については、まだまだ改善すべきと思っておりますが、維持費とご相談という状態です。
なお、お気づきの方もいらっしゃるとは思いますが、今回作成したものは、別にVTuberに特化させる必要はなく、YouTube Live上の配信であれば汎用的に対応できます。しかし、VTuberというドメインに限定させた理由は以下のとおりです。
以上、ご覧いただきありがとうございました。
VTuber Chat Trendsは下記よりご利用ください。
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント