vMix ハンズオン【第5回】「Triggerとオートメーションについて」

前回は → vMix ハンズオン【第4回】

vMix 公式サイトはこちら

1. 配信はもっと自動化(オートメーション)出来るはず

前回は、如何に vMix を誰でも本番のオペレーショがン出来る物にするか、についてお話ししました。
今回は、如何に vMix を効率よくオペレーションするか、についてお話ししたいと思います。

通常ですと、複雑な配信システムになればなる程、それをオペレーションするマンパワーが必要になります。 なぜなら「進行台本」という一種の「ソフトウェア」を逐次実行しているのが人間だからです。

筆者が常々思っているのは「その一部でも機械にやらせればもっと効率が良くなるのではないか?」という事です。 例えば、カウントダウンに合わせて「BGM フェードアウトして」「映像をスイッチングして」「マイクのフェーダーを上げて」「次の BGM 叩いて」みたいな同時多発的な操作を、 バシっとボタン1つ叩くだけで恙なく全部行われるのが理想ですね。しかもくそ高い機材を使わずに。

今回は、そういった同時多発的な操作を vMix に自動で行わせる事を考えていきます。

2. Trigger

まず、vMix のオートメーションとして良く使われる「Trigger」をご紹介します。

「Trigger」とは Input の各種イベントに応じて起動され、任意の Function を呼び出すことが出来る物です。 Function は前回説明した Shortcut と同じ物です。 もちろん Input 毎に複数の Trigger を作れます。

早速使用してみましょう。 Trigger は「⚙Input Settings」→「Trigger」で設定します。 Trigger を起動できるイベントは以下の通りです。

イベント発生タイミング
OnTransitionInTransition で OUTPUT へ表示される時に発生
OnTransitionOutTransition で OUTPUT から消される時に発生
OnOverlayInOverlay へ送られる時に発生
OnOverlayOutOverlay から消される時に発生
OnCompletionVideo, List, Photos, PowerPoint のみのイベント。再生ポジションが末尾に到達した際に発生。Loopしているときは発生しない
OnCountdownCompletedTitle のみのイベント。カウントダウンが 0 になった際に発生
OnAudioMeterDB6Audio メーターが -6dB を上回った時に発生
OnAudioMeterDB12Audio メーターが -12dB を上回った時に発生
OnAudioMeterDB18Audio メーターが -18dB を上回った時に発生

各 Trigger は以下の設定項目で定義されます。

項目機能
TriggerTrigger を仕込むイベント
FunctionTrigger で実行する Function
InputFunction の対象となる Input
DurationFunction の Duration パラメータ
DelayFunction が実行されるまでの時間(ミリ秒)
ValueFunction のパラメータ
MixFunction の対象となる Mix

この他、Function によっては追加の項目が存在します(詳細は割愛)。

これを踏まえたうえで、サンプルとして 3 つ程使用例を示したいと思います。

サンプル1: Trigger で Overlay を自動消去する

前回登場した「Overlay」ですが、その仕様上、一度 Overlay を出すと Input をスイッチングしても Output に残り続けます。 これは正常な動作ですが、便利な反面、世の中には如何なる Overlay も被せたくない Input と言うのが存在すると思います。 例えば CM 動画や、蓋絵、スライド等が挙げられるでしょう。 こう言った「VIPな」Input を出す時は Overlay をいちいち消さなければなりませんが、消し忘れて被せてしまうリスクが少なからず存在します。

そのリスクを完全に無くす為、絶対に Overlay を被せたくない Input に、Overlay を自動で消す Trigger を仕込みましょう。

「⚙Input Settings」→「Triggers」を開いて、以下の様に設定し、「Add」ボタンを押してください。

項目設定値
TriggerOnTransitionIn
Function「Overlay」→「OverlayInputAllOff」
Delay0

作成したらテストしてみましょう。Trigger を付けた物とは別の Input を Output に出して、Overlay を点けてください(*)。

そのまま、Trigger を設定した Input を Output に出しましょう。 仕込んだ通り、Trigger が発動して Overlay が自動的に消えたと思います。


(*) Overlay の点け方を覚えていますか?前回設定したショートカットを使ってもいいですし、Input の下に並んでいる 1 ~ 4 の数字ボタンを左クリックでもOKです。

サンプル2: カウントダウンを自動スタート、数字が 0 になったら Input スイッチ

vMix の Title Input にはカウントダウン機能があり、お手軽にカウントダウンを表示出来ます。 また、ご紹介した通り、Trigger にはカウントダウンが 0 になると発生するイベントが有ります。 これらを利用して、カウントダウンを行う蓋絵を用意し、数字が 0 になったら Input をスイッチするという Trigger を作りたいと思います。

まず、Title Designer でカウントダウン用の Title を作りましょう。今回はシンプルなテキストだけの Title にしました。 vMix に読み込んだ物が此方になります。

次に、Title Editor でカウントダウンの設定をします。 Title Input を右クリック→「Title Editor」→「Countdown」→「Settings」を押してください。

カウントダウンの設定項目は以下の通りです。

項目機能
Durationカウントダウンする時間(時:分:秒)
Stop Timeカウントダウンが停止する時間(時:分:秒)ここで例えば 00:00:30 と設定すると、30秒だけカウントダウンして止まる。
Display Formatカウントダウンの時間表記。HH が時、mm が分、ssが秒
Reverseカウントアップする場合チェック
Display xx when Stoppedカウントダウンが停止した場合に、初期状態に戻すか否か
Current Time現在のカウントダウン時間。カウントダウンを開始すると自動更新される

これらを以下の様に設定します。

項目設定値
Duration00:01:00
Stop Time00:00:00
Display Formatmm:ss
Reverseチェック無し
Display xx when Stoppedチェック無し
Current Time変更なし

これで 1 分間のカウントダウンを行う「カウントダウン Input」が出来ました。 また、適当な「蓋絵 Input」を作って、Multi View にカウントダウン Input をセットしましょう。 以下の様な真っ白い蓋絵にしました。

次に Trigger を仕込んでいきます。 まず、蓋絵 Input に以下の Trigger を追加します。 「なぜ、カウントダウン Input に追加しないのか」は後ほど説明します。

項目設定値
TriggerOnTransitionIn
Function「Title」→「StartCountdown」
Inputカウントダウン Input
TitleText1 (*1)
Delay0

(*1) Title Input には複数のテキストフィールドを持てるので、どのテキストフィールドでカウントダウンをスタートするか指定する追加項目が有ります。

更に、カウントダウン Input に以下の Trigger を追加します。

項目設定値
TriggerOnCountdownCompleted
Function「Transition」→「Fade」
InputPreview (*2)
Duration500 (*3)
Delay0
Mix1

(*2) Preview にある Input が Output に出されます

(*3) ここでは Fade の時間を設定します

Multi View にセットされた Input ではイベントが発生しない

おそらく Trigger の重複を防ぐための仕様だと思いますが、Multi View にセットされた Input に対しては、 OnTransitionIn, OnTransitionOut, OnOverlayIn, OnOverlayOut, OnCompletion のイベントが発生しません。 従って、本サンプルでは OnTransitionIn の Trigger は、カウントダウン Input ではなく、蓋絵 Input に仕込んでいます。

OnCountdownCompleted は、カウントダウンしている Title Input その物でしか発生しない

(カウントダウン Input を Multi View にセットした)蓋絵 Input に OnCountdownCompleted の Trigger を追加しても動作しません。 OnCountdownCompleted の Trigger は必ずカウントダウン Input に設定します。

最後に、何でも構わないので Video または静止画や Color Bar と言った、「テスト用 Input」を作成してください。

以上で、Trigger を仕込み終わりました。早速、テストしてみましょう。

まず、Output に「テスト用 Input」を出します。次に、「蓋絵 Input」を出しましょう。

カウントダウンが自動で開始しましたね?Preview に戻った「テスト用 Input」はそのままにしておいてください。

1 分間カウントダウンが続いて 00:00 になった次の瞬間、自動的に「テスト用 Input」が Preview から Output へと送られました。

この様に Trigger を使用すれば、通常なら 2 手・3 手必要な進行を、最初の 1 手だけで自動進行する事が出来ます。 注意としては、Trigger がきちんと想定どおりの動作するか入念にテストを行ってください。 いくら vMix に慣れていても、本番中に Trigger を仕込むのはリスクが高い行為なので行ってはいけません。

サンプル3: Input のスイッチングと共に、Audio Input の Fade In/Out を行う

Audio Input は Input の Multi View にセットしておけば、自動的に ON になりますが、Fade In/Out は Transition の Duration 設定に依存します。 (そして、それは大抵の場合短すぎる) Shortcut を使って Fade In/Fade Out を行う例を、第3.5回で紹介しました。そこから更に発展させて、Input のスイッチングに連動して自動で行う事は出来ないでしょうか?

Yes、可能です。そう Trigger ならね。

今回用意するのは、次の Input 4 つです。

  1. 適当な「Audio Input」(マイク Input)。マイクをつないだ Audio デバイスなどを追加してください。
  2. 適当な「Audio」(BGM Input)。お好きな BGM を追加してください。
  3. 適当な「Camera」(Camera Input)。カメラを繋いだキャプチャーデバイスや Webcam を追加してください。
  4. 適当な「Image」(蓋絵 Input)。蓋絵用の静止画を追加してください。

Input を読み込んだプリセットはこちらになります。

Trigger の仕込みを始める前に、「マイク Input」と「BGM Input」の設定を変更します。

  • 「⚙Input Settings」→「General」→「Automatically mix audio」「Automatically Play with Transition」 「Automatically Pause after Transition」からチェック外す。つまり標準の自動制御を全部 OFF にする。

次に「 Input」に Trigger を仕込みましょう。 今回は、

  • 「蓋絵 Input」が表示された時「BGM Input」が ON になり、消されたときは OFF になる
  • 「Camera Input」が表示されたとき「マイク Input」が ON になり、消されたときは OFF になる

という感じの動作にしたいと思います。

まず「蓋絵 Input」に Trigger を追加します。

蓋絵 Input: 表示されたときの Trigger

項目設定値
TriggerOnTransitionIn
Function「Audio」→「Audio On」
Input「BGM Input」
Delay0
項目設定値
TriggerOnTransitionIn
Function「Input」→「Play」
Input「BGM Input」
Delay0
項目設定値
TriggerOnTransitionIn
Function「Audio」→「SetVolumeFade」
Input「BGM Input」
Delay0
Value100,3000 (*1)

(*1) 3秒かけて 100% までフェード

蓋絵 Input: 消されたときの Trigger

項目設定値
TriggerOnTransitionOut
Function「Audio」→「SetVolumeFade」
Input「BGM Input」
Delay0
Value0,3000 (*2)
項目設定値
TriggerOnTransitionOut
Function「Audio」→「AudioOff」
Input「BGM Input」
Delay3000 (*3)
項目設定値
TriggerOnTransitionOut
Function「Input」→「Pause」
Input「BGM Input」
Delay0

(*2) 3秒で 0% まで Fade Out

(*3) 直前の Trigger から 3 秒後に実行

また、正しい実行順にする為、作成した一連のトリガーを 「▲」「▼」ボタンを使って下図の様に並べ替えてください。

次に「Camera Input」に Fade In の Trigger を追加します。

Camera Input: 表示されたときの Trigger

項目設定値
TriggerOnTransitionIn
Function「Audio」→「Audio On」
Input「マイク Input」
Delay0
項目設定値
TriggerOnTransitionIn
Function「Audio」→「SetVolumeFade」
Input「マイク Input」
Delay0
Value100,3000

Camera Input: 消されたときの Trigger

項目設定値
TriggerOnTransitionOut
Function「Audio」→「SetVolumeFade」
Input「マイク Input」
Delay0
Value0,3000
項目設定値
TriggerOnTransitionOut
Function「Audio」→「AudioOff」
Input「マイク Input」
Delay3000

先程と同様に、作成した一連のトリガーを 「▲」「▼」ボタンを使って下図の様に並べ替えてください。

複数 Trigger を並べた時の動作は?

今回のサンプルで注目頂きたいのが、複数の Trigger を並べた時の動作についてです。 複数の Trigger が同じイベントに設定されている場合は、リストの上にあるものから順に実行されます。 その場合、「Trigger の完了を待たずに」次々と実行されていきますが、 「Delay」が設定されている場合は、その時間待ってから実行されます。 また、それ以降の Trigger は、直前の物が実行されてから実行となりますから、結果的に下記の様な実行タイミングとなります。

TriggerDelayTimeline
Trigger 10ms0ms
Trigger 23000ms3000ms
Trigger 30ms3000ms

つまり途中に Delay が設定されている Trigger がある場合、それ以降の Trigger も Delay 分実行が遅れるという事です。 ありがちなミスとしては、3秒後に 2 つの Trigger を実行したい、という仕込みを以下の様にしてしまうと、想定に反して最後の Trigger 3 が 6 秒後に実行されます。

TriggerDelayTimeline
Trigger 10ms0ms
Trigger 23000ms3000ms
Trigger 33000ms6000ms

お好みで、第3.5回でご紹介した、Fade In/Out の Shortcut を仕込んでも良いでしょう。

Trigger の仕込みが終わりましたら、早速テストを実施しましょう。 まずは「BGM Input」を OFF(「Audio」ボタンが反転してない状態)かつ 一時停止状態(「▶再生」ボタンが表示されている状態)に、 「マイク Input」を OFF にそれぞれ設定し、初期状態としてください。

そして、「蓋絵 Input」を Output に表示させてください(Transition はなんでもいいです)。 すると「BGM Input」が ON かつ再生され、3秒かけて Fade In します。

更に、「Camera Input」を Output に表示させてください。 すると「BGM Input」が 3 秒かけて Fade Out した後、OFF かつ 一時停止されます。 また、同時に「マイク Input」が ON になり、3秒かけて Fade In します。

上記を何度繰り返しても、正しく動作するかを確認してください。

さて、ここで注意があります。 今回作った Trigger は Fade In/Out に 3 秒掛かる事になりますが、 Fade しきる前(即ち 3 秒以内)に再びスイッチングを行ったらどうなるでしょうか?

答えは、Fade In 中の Audio が途中で OFF になります。なぜなら、直前で実行された Trigger が動作し続けているからです (3 秒後に OFF にするという Trigger が実行されることで強制的に OFF にされてしまう) 従って、今回の Trigger を使用する際は、Trigger の動作が重複する 3 秒未満の間隔でスイッチングしてはいけません。

Trigger の実行が重複すると、予期しない不都合が発生することから、 vMix では長い実行時間を持つ Trigger を非推奨としています。 そもそも内部的な制限が最大 30 秒とされており、それ以上の時間を掛けて Trigger を実行する事は出来ません。 長い時間が掛かる用途には、後述の Scripts を使用する事が推奨されています。

改良案

そもそも 0% まで Fade Out して消音されるのだから、いちいち Audio を OFF にしたり、 (裏で再生されっぱなしになりますが)一時停止したりする必要がないという考え方も出来ます。 従って、OnTransitionOut の Trigger から、SetVolumeFade 以外を削除してしまえば良いです (OnTransitionIn の Trigger は残しておいてください)

幸運にして SetVolumeFade は重複がなく、以前の処理を上書きしてくれるので、連打しても問題ありません。

3. Scripts

vMix では、VB.NET によるスクリプティングが可能です。 スクリプト内では、 vMix で用意されている全ての Function を使用する事が出来ます。 また、.NET framework が使用できるとドキュメントに書かれているので、 WebClient を使ってネットにアクセスしたりも出来るそうです。夢が広がりますね。

注意としては、書いたスクリプトは 1 個の関数にラップされ、クラス定義は使用できないという事です。 恐らく Imports も出来ないので、外部オブジェクトの使用は不可でしょう。 無理やり外部オブジェクトを呼び出す方法はなんか有るかもしれませんが、今は追及しません。

・・・え?「Visual Basic なんてヤダー」? 俺だってヤだよ。

「Settings」→「Scripting」で Script を登録します。 登録したスクリプトは、そのまま「Start」を押して起動もできますし、 ショートカットや Trigger で起動することも出来ます(その為の ScriptStart という Function が用意されています)

幾つかサンプルコードをご紹介します。ここからはプログラミング言語「VB.NET」の知識が必要です。

サンプル1: Hello World

Title Input に「Hello World!」と設定して Overlay 表示するスクリプトです。

' Text という名前の Input を変数 i にセット
dim i = Input.Find("Text")

' Input の Text1 というフィールドに文字列をセット
i.Text("Text1") = "Hello World!"

' Input を Overlay 1 番に表示
i.Function("OverlayInput1In")

※実行する前に、プリセットへ「Text」という名前で「Text1」というテキストフィールドを含む Title Input を追加してください。

サンプル2: 定期的にメッセージを Overlay 表示

3 分おきに 30 秒間のメッセージ表示を自動で行うスクリプトです。 この為に Overlay 4 番を占有するものとします。 停止されるまで無限に動作し続けます。

While True
    ' 150秒停止
    System.Threading.Thread.Sleep(150000)

    ' 30秒表示
    Input.Find("Message").Function("OverlayInput4In")
    System.Threading.Thread.Sleep(30000)

    ' メッセージ消去
    Input.Find("Message").Function("OverlayInput4Out")
End While

※実行する前に、プリセットへ「Message」という名前で Title Input を追加してください。

サンプル3: 配信 Output で抜かれている人に Discord で通知する

ネットにアクセスするサンプルです。

リモート配信しているときに、出演者の画面を Output に表示(フレーム・イン)したら、本人に Discord でメンションして通知します。 表示されなくなった(フレーム・アウト)時も通知したいので、出演者 1 人につき、2 つのスクリプトを使用します。

前準備として、Discord 上でテキストチャンネルの Webhook URL を生成しておいてください。

また、出演者の Discord ID(長い数字)を確認して控えておいてください。

FrameInNotify

フレーム・インした時に実行。

' Webhook URL をセット
Dim uri As Uri = new Uri("https://discord.com/api/webhooks/1234/xyzw")

Using client As WebClient = New WebClient()
    client.Encoding = System.Text.Encoding.UTF8
    client.Headers.Add("Content-Type", "application/json")

    ' 12345678 を 出演者の Discord ID に置換
    client.UploadStringAsync(uri, "{""content"": ""<@12345678> さんフレーム・インしました!""}")
End Using

FrameOutNotify

フレーム・アウトした時に実行

' Webhook URL をセット
Dim uri As Uri = new Uri("https://discord.com/api/webhooks/1234/xyzw)

Using client As WebClient = New WebClient()
    client.Encoding = System.Text.Encoding.UTF8
    client.Headers.Add("Content-Type", "application/json")

    ' 12345678 を 出演者の Discord ID に置換
    client.UploadStringAsync(uri, "{""content"": ""<@12345678> さんフレーム・アウトです。""}")
End Using

Input への Trigger 仕込み

出演者画面 Input へ、スクリプトを起動する Trigger を仕込みましょう。

項目設定値
TriggerOnTransitionIn
Function「Scripting」→「ScriptStart」
Delay0
ValueFrameInNotify
項目設定値
TriggerOnTransitionOut
Function「Scripting」→「ScriptStart」
Delay0
ValueFrameOutNotify

出演者画面 Input を出し入れしてみた結果が下記のとおりです。

メッセージの内容と、Discord 側の通知設定を工夫すれば、もっと便利に出来るかもしれませんね。

こちらのサンプルでは、WebClient で POST するだけでしたが、Web からデータを取ってくることも可能です(*)。


(*) とは言え、データを取って来るだけならスクリプトではなく、後々解説する予定の「Data Source」を使った方が簡単です。

vMix の状態を取りたい

多分聞かれるんで書いときますが、スクリプトの中で vMix の状態(アクティブな Input とか、配信の状態とか)を取りたい場合、 XML() という API 関数を使ってください。XML 形式で vMix の状態が返されるので、頑張ってパースして目的の値を引っ張り出しましょう。

詳しくはドキュメントを参照してください。

4. 今回はここまで

今回はかなり深い内容で、ソフトウェア開発方面に明るくない方は意味が良く分からなかったかもしれません。 しかし、高度なスクリプティングまで行かなくとも、Trigger だけでも理解して上手く使えれば、配信オペレーターの負担を相当軽減できるはずです (*)。 是非チャレンジしてみてください。

次回は、Input Settings や Overlay、Transition(可能なら Stinger Transition も)について更に掘り下げて行きたいと思います。 アップまでしばらくお時間いただければと思います。

次回は → vMix ハンズオン【第6回】


(*) 逆に、仕込みの作業量は増えますが!