スマホからも参加できる！DiscordとOBSを連携してバ美肉トーク動画を作ろう！

# 2022/12/24 Discord StreamKit Overlayの仕様変更について
Discord StreamKit Overlayが仕様変更されたようです。
取り急ぎ対応しました。
名前が表示されなくなったのでOBSのテキストなどで対応していただけますと…

```css
body,
#root,
#root * {
  overflow-y: hidden !important;
  --url-kuchitoji-meake: url("【1_口を閉じていて、目が開いている画像のURL】");
  --url-kuchitoji-metoji: url("【2_口を閉じていて、目が閉じている画像のURL】");
  --url-kuchiake-meake: url("【3_口を開いていて、目が開いている画像のURL】");
  --url-kuchiake-metoji: url("【4_口を開いていて、目が閉じている画像のURL】");
}

/* 選択したユーザ以外の画像を非表示にする */
img:not([src*="avatars/【DiscordのユーザID】"]) {
  display: none;
}

[class*="Voice_voiceStates__"] {
  display: flex;
}

[class*="Voice_voiceState__"] {
  height: auto;
}

[class*="Voice_avatar__"] {
  height: auto !important;
  width: 100% !important;
  border-radius: 0 !important;
  padding: 20px 0 0;
  animation: yurashi 2000ms ease-in-out infinite alternate,
    mabataki-kuchitoji 2500ms infinite;
  transform-origin: 50% 125%;
}

[class*="Voice_avatarSpeaking__"] {
  position: relative;

  border-color: transparent;
  animation: yurashi 2000ms ease-in-out infinite alternate,
    mabataki-kuchiake 2500ms infinite;
}

[class*="Voice_name__"] {
  display: none;
}

img[src*="avatars/【DiscordのユーザID】"] {
  content: var(--url-kuchitoji-meake);
  border-radius: 0;
  border: none;
}

/* 口閉じまばたき */
@keyframes mabataki-kuchitoji {
  0% {
    content: var(--url-kuchitoji-meake);
  }

  1% {
    content: var(--url-kuchitoji-metoji);
  }

  16% {
    content: var(--url-kuchitoji-meake);
  }

  100% {
    content: var(--url-kuchitoji-meake);
  }
}

/* 口開けまばたき */
@keyframes mabataki-kuchiake {
  0% {
    content: var(--url-kuchiake-meake);
  }

  19% {
    content: var(--url-kuchiake-meake);
  }

  20% {
    content: var(--url-kuchiake-metoji);
  }

  35% {
    content: var(--url-kuchiake-meake);
  }

  100% {
    content: var(--url-kuchiake-meake);
  }
}

/* 体ゆらし */
@keyframes yurashi {
  0% {
    transform: rotate(-1deg);
  }

  100% {
    transform: rotate(1deg);
  }
}
```

参考:
* [OBSのDiscord通話相手立ち絵表示ジェネレーター](https://obs-discord-picture.alfebelow.com/)
* [Discord Streamkit Overlay Tester](https://codepen.io/BOCHIsPG/pen/zYLGEaZ)

# 概要
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Discord StreamKit OverlayとOBSのカスタムCSSを連携させてお手軽バ美肉してみました！<br>Discord上で話している間だけアバターの口が自動で開きます。<br>Discordで話すだけなので参加者はスマホからでもアバターを動かせます。青髪の中の人は実際にスマホから話してもらってます。<br>実装は後日まとめます〜 <a href="https://t.co/a5SGnLAGQA">pic.twitter.com/a5SGnLAGQA</a></p>&mdash; レオナ (@reona396) <a href="https://twitter.com/reona396/status/1398651946123157505?ref_src=twsrc%5Etfw">May 29, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">Discord StreamKit OverlayとOBSのカスタムCSSを連携させてお手軽バ美肉するやつ、3人でも試してみました。<br>Discordで発言してる人のアバターの口が開く&amp;自動でまばたきと体のゆれが付きます。<br>アバターの操作不要でボイチャするだけでバ美肉トーク動画が作れるの楽しい！！<br>実装まとめは鋭意執筆中📝 <a href="https://t.co/FvEdUgQfpu">pic.twitter.com/FvEdUgQfpu</a></p>&mdash; レオナ (@reona396) <a href="https://twitter.com/reona396/status/1399477724754825219?ref_src=twsrc%5Etfw">May 31, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

* バ美肉トーク動画が簡単に撮れる！
* OBSを立ち上げる用のPCがあれば、他の参加者はスマホからでもバ美肉トークに参加できる！
* アバターの操作不要！Discordのボイスチャンネルで話しているだけで自動的にアバターが動く！
    * ボイチャで発言すると自分のアバターの口が開く！
    * 自動でまばたきしたり体が揺れたりする！
* Discordで設定しているニックネームがアバターに自動で紐づいてネームタグが表示される！
* 複数人でのトークも対応できる！
    * アバターのアニメーションやネームタグのおかげで、動画上でどの声が誰か識別しやすくなる！

# 設定と実装

## 必要なソフトのインストール
PCでOBSとDiscordをインストールします。
[ダウンロード \| OBS](https://obsproject.com/ja/download)
[Discord](https://discord.com/)

## アバターの作成とアップロード
まずはアバターを準備していきましょう。
アバターは、

1. 口を閉じていて、目が開いている画像
2. 口を閉じていて、目が閉じている画像
3. 口を開いていて、目が開いている画像
4. 口を開いていて、目が閉じている画像

の4種類の画像で構成されています。
これら4種類の画像を用意しましょう。

私の場合、アバターはこちらのジェネレーターを利用して生成しました。
(概要に貼った動画では、一部の画像を左右反転して利用しています。また、ジェネレーターごとに利用規約が異なるのでよく確認しておきましょう)
[五百式立ち絵メーカー｜Picrew](https://picrew.me/image_maker/625876)

![qiita01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67311/6720195d-5798-ae15-d2e5-e4cd52643bdc.png)

準備ができたら、4枚の画像をDiscordのテキストチャンネルにアップロードしておきます。

## Discord StreamKit Overlayの設定
[Discord StreamKit Overlay](https://streamkit.discord.com/overlay)
上記から`Install for OBS`ボタンをクリック > `VOICE WIDGET`タブをクリック > `Server`からしゃべる予定のDiscordサーバを選択します。
その後、その下の`Voice Channel`でしゃべる予定のボイスチャンネルを選択します。
設定したら、この画面右下の`browser source`として書かれているURLを控えておきます。
`https://streamkit.discord.com/overlay/voice/~~~~~` みたいなURLです。

![スクリーンショット 2021-06-01 21.05.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67311/9cb088df-e8a5-fbfd-86aa-8642c64e93bc.png)

## Discordの設定
Discordの`ユーザ設定` > `アプリの設定`内の`詳細設定` > `開発者モード`をオンにしておきます。

## OBSの設定
OBSの`ソース` > `ブラウザ`を選択します。
![スクリーンショット 2021-05-30 17.51.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67311/144b3d3a-9961-8f8d-f967-b4668fa1c4bd.png)

設定ウィンドウの`URL`欄に先ほどDiscord StreamKit Overlayを設定した際に控えたURLを貼りつけます。
また、同じウィンドウ内の`カスタムCSS`欄に以下のコードを貼りつけます。

```css
/* 画像のURL */
:root {
  --url-kuchitoji-meake: url("【1_口を閉じていて、目が開いている画像のURL】");
  --url-kuchitoji-metoji: url("【2_口を閉じていて、目が閉じている画像のURL】");
  --url-kuchiake-meake: url("【3_口を開いていて、目が開いている画像のURL】");
  --url-kuchiake-metoji: url("【4_口を開いていて、目が閉じている画像のURL】");
}

/* 選択したユーザ以外の画像を非表示にする */
li.voice-state:not([data-reactid*="【DiscordのユーザID】"]) {
  display: none;
}

/* 通常時の設定 */
.avatar {
  content: var(--url-kuchitoji-meake);
  height: auto !important;
  width: 100% !important;
  border-radius: 0 !important;

  animation: yurashi 2000ms ease-in-out infinite alternate, mabataki-kuchitoji 2500ms infinite;
  transform-origin: 50% 125%;
}

/* 話している時 */
.speaking {
  border-color: rgba(0, 0, 0, 0) !important;
  position: relative;
  animation: yurashi 2000ms ease-in-out infinite alternate, mabataki-kuchiake 2500ms infinite;
}

/* 口閉じまばたき */
@keyframes mabataki-kuchitoji {
  0% {
    content: var(--url-kuchitoji-meake);
  }

  1% {
    content: var(--url-kuchitoji-metoji);
  }

  16% {
    content: var(--url-kuchitoji-meake);
  }

  100% {
    content: var(--url-kuchitoji-meake);
  }
}

/* 口開けまばたき */
@keyframes mabataki-kuchiake {
  0% {
    content: var(--url-kuchiake-meake);
  }

  1% {
    content: var(--url-kuchiake-metoji);
  }

  16% {
    content: var(--url-kuchiake-meake);
  }

  100% {
    content: var(--url-kuchiake-meake);
  }
}

/* 体ゆらし */
@keyframes yurashi {
  0% {
    transform: rotate(-1deg);
  }

  100% {
    transform: rotate(1deg);
  }
}

/* ネームタグ表示位置調整 */
li.voice-state {
  position: static;
  text-align: center;
}

div.user {
  position: absolute;
  right: 0;
  left: 0;
  bottom: 35px;
  margin: auto;
}

body {
  background-color: rgba(0, 0, 0, 0);
  overflow: hidden;
}

.voice-container .voice-states .voice-state .user .name {
	font-size:20pt !important;
}
```

次に、先ほどDiscordのテキストチャンネルにアップロードした4枚の画像をそれぞれ右クリックして`リンクをコピー`を選択して画像URLをコピーします。
上記カスタムCSSの`root`内の対応するところに画像URLをペーストしましょう。

最後に、アバターと紐付けたいDiscord上のアカウントを右クリックして`IDをコピー`を選択し、
上記カスタムCSSの`【DiscordのユーザID】`にペーストしましょう。
終わったら`OK`ボタンを押します。

## テストしてみる
設定したDiscordのボイスチャンネルに入って、アバターが表示されるか確認しましょう。
アバターの位置やサイズを調整したら完成です！
ついでに背景画像も設定するといい感じになります。

![スクリーンショット 2021-06-01 20.39.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67311/cc923e66-e98f-4322-30fc-93dd78895304.png)

Discordのボイチャ上で適当にしゃべってみて、アバターの口が開くか確認してください。

## 複数人のアカウントのアバターを立てたい時は
ソースにブラウザを同じ手順で必要な人数分追加してください。
その際、アバター画像URLやIDの書き換えを忘れずに行ってください。

OBSの仮想カメラをオンにしてDiscordのカメラ設定を`OBS Virtual Camera`にすると、
DiscordのビデオチャットにOBSの映像を流せます。
他の参加者にも自分のアバターの動きを確認してもらいましょう。
`録画開始`ボタンを押して動画を保存すれば完成です！

なお、Discordのサーバ上でアカウント名を右クリック > `ニックネームの変更`で設定した名前がネームタグに反映されます。
アカウント名を名乗るもよし、アバターの名前をつけるもよし、色々楽しんでみてください！！

# 発想元
複数人でバ美肉してトークするコンテンツを制作したいと考えていた時、当初は [だれでもVtuber](https://booth.pm/ja/items/2362820) もしくは下記のような自作ツールを参加者それぞれのPCで立ち上げてもらって音声と映像をとりまとめる方向で考えていたのですが、
参加者への負担が大きいということでこの方法になりました。
アバターのアニメーションはだれVリスペクトです。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">p5.jsで画像を読み込んで、一定フレームごとに短時間画像を差し替え(まばたき)しながら、低い位置を起点に振り子のように揺らしてみた。<br>実装してみるまで「揺らす」ってこんなに重要って気がつかなかったよ…たしかにキャラクター感が出るなぁ <a href="https://t.co/qhPxBrvWzY">pic.twitter.com/qhPxBrvWzY</a></p>&mdash; レオナ (@reona396) <a href="https://twitter.com/reona396/status/1397917681563492353?ref_src=twsrc%5Etfw">May 27, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

色々調べてるうちに、Discord上で誰が発言しているか紐付けているAmong usプレイ動画を見つけて「これだ！」と思った次第です。

# 今後の課題
* ~~ネームタグ表示の文字もっと見やすくしたい~~  
→ 2021/12/23 ネームタグの文字サイズや位置を調整しコードを更新
* アバターのアニメーションもっと細かくしたい
    * 体の上下方向の揺れ
    * 発言時間が長い時、口をパクパクさせる
* DiscordのIDもroot内にまとめたい
    * 変数としてまとめてみたら一人のアカウントから3体のアバターに紐づいた…正しい書き方を探したい
* インタラクティブに表情を変えられるようにしたい
    * カスタムCSSだけでできるだろうか…
* たまにアバター画像がチラつくのをできれば抑制したい

# 参考文献
* [Discordで喋ってる人を分かり易くするカスタムCSS \| 萬巓堂本店](https://manten-do.net/archives/273)
* [DiscordStreamKit 立ち絵変換 \| 萬巓堂本店](https://manten-do.net/contents/dsk01)
* [DiscordとOBSを連携させてゲーム配信に喋ると動くイラストをつけよう【配信者必見！】 \| NatoriGameblog](https://gamer-natori.com/broadcast-001-discord-obs/)
* [OBS StudioにDiscordで通話中のメンバーを横並びに表示して、ぴょこぴょこ動かす方法｜T\.T｜note](https://note.com/protein_daizi/n/n0abb4237680d)
* [Discord StreamKit Overlay Sample](https://gungeespla.github.io/obs_discord_sample/)
* [Discord StreamKit OverlayでディスコードID、立ち絵をCSS変数で設定してみた｜こまる｜note](https://note.com/nagi777/n/naab40980918c)
* [【データ配布あり】Discord Streamkit Overlayのcssカスタム用テストデータを作った \| ALBA LUNA](https://albalunaweb.net/note/10296.html)