Vtuberの配信動画などでよく見かける、話してる人の立ち絵が喋ると光ったり動くアレをDiscordじゃなくてMicrosoft Teamsでもやりたいですよね?というわけでそれっぽくできるような何かを作ってみました。
毎週Microsoft Teamsを使ってYoutubeで配信みたいなことをしてますが、手間をあんまりかけないことをモットーにしてるので、ゲストにあまり負担をかけないようにいつも音声のみなんですが、とはいっても絵的には誰が話してるかとかちょっとでも有ったほうが賑やかでいいなぁと思ってたわけです。
よくある配信だとみんなDiscordを使って喋ってて、Discord + Discord StreamKit Overlay VoiceWidget + OBS(とカスタムCSS)みたいな構成なんですよね。
なら何かしらこの仕組みが流用できるような構成にしてあげると使いまわしがしやすいな?ということで、以下の2つを作りました。
- OBSから参照する、Discord StreamKitみたいなHTMLを返してあげるサーバー
- Microsoft Teamsの話者の状態をサーバーに通知するブラウザ拡張(Chrome Extension)
通知する方法はWebSocketsでいいかと思ってさっと使えそうなSignalRで。将来的に(しないと思うけど)パブリックサーバー化してもどうとでもなりそうな構成です。
サーバー側
サーバー側に求められる機能はざっくり以下の3点。
- ユーザーの一覧を表示する
- WebSockets(SignalR)で受信したメッセージに従い、動的にユーザーの喋ってる状態を変化させる
- ユーザーの一覧ページはDiscord StreamKitのVoiceWidgetのようにする
ユーザー一覧は固定でもなんでも良かったのですが、せっかくなので管理画面も作りました。ASP.NET Core MVCのスキャフォールディング便利。
Discord風な一覧は具体的には以下のようなHTMLを返すページです。
<div id="app-mount">
<div style="font-family:Whitney, sans-serif;background-color:transparent;" class=" " data-reactid=".0">
<div class="voice-container" data-reactid=".0.0">
<ul class="voice-states" data-reactid=".0.0.0">
<li class="voice-state" data-reactid=".0.0.0.$3/=1$3">
<img class="avatar" src="https://pbs.twimg.com/profile_images/1489187859689279488/KOcT1zXj_400x400.jpg" data-name="buchizo (ゲスト) (Guest)" data-reactid=".0.0.0.$3/=1$3.$=10">
<div class="user" data-reactid=".0.0.0.$3/=1$3.$/=11">
<span class=" name" style="color:#ffffff;font-size:14px;background-color:rgba(30, 33, 36, 0.95);" data-reactid=".0.0.0.$3/=1$3.$/=11.0">buchizo (ゲスト) (Guest)</span>
</div>
</li>
</ul>
</div>
</div>
</div>
喋ってる状態になると、 img.avatar にspeakingが付きます。このままでもいいのですが、見た目がアレなのでSteamkitのCSSを参照するようにしてます。(OBS側でカスタムCSS適用するから要らないかもしれないけど)
余計な属性などはとってもいいと思いますが、よくある立ち絵カスタムCSSでID識別するのにdata-reactidをそのまま使ったりしてるのでそのままにしておきました。
あと個人毎にCSSを管理したりしたいかもしれないので、ユーザーID指定で指定ユーザーだけ表示されるページにしたりとか。
Chrome Extension側
Chrome Extension側は https://teams.microsoft.com/* 内の要素を監視して会議参加者の要素に変化があったら状態と名前をservice worker経由でWebSocketsのサーバーに投げるだけです。
構造がわりと複雑で泥臭い感じです。もうちょっときれいにしたいけどどなたか。。
あと表示名じゃなくもうちょっとIDぽい値が無いかなと思ったんですが、わからなかったので名前をキーにするしか、、みたいな感じです。いまのところ。
OBS側
OBS側はURLだけが違うぐらいで基本的にDiscordの時にやってるようなことをそのまますればOKです。
他にもCSS弄って好みのアニメーション付けたり、立ち絵を変えて口パクさせたりとかいろいろできると思います。上記の三日月望さんのCSSを適用すると冒頭の動画みたいな感じになります。簡単だね。
ソースなど
こちら: https://github.com/buchizo/twinkleteams
おまけ
ブラウザ版でTeamsミーティングに参加してると、喋ってる状態がちょっとワンテンポ遅れてる気がするんですよね。デスクトップ版Teamsでも同じような感じ?気のせい?謎。もしデスクトップ版のほうが遅延がないとかなら、参加者のアイコン周りのピクセルを監視して変化があったら喋ってる状態を通知する、とかでもありかなと思いました。(ただし参加者が増減したりすると位置が…)
根本的に参加者の人がビデオを提供してくれるなら、TeamsのNDI機能を使ってOBSに取り込んでもいいし、TeamsのカスタムTogetherモードシーンを作って絵作りをしてもいいわけです。というかMicrosoft Teams側でもうちょっと会議参加者の状態をとれるAPIなり充実してくれたらこんな苦労はいらないんですけどね。
まとめ
最初から
Discordで
ええんちゃうん?()