TouchDesignerでのキュー操作

[TouchDesigner Advent Calender 2024](https://qiita.com/advent-calendar/2024/touchdesigner) 11日目記事

演劇やプロジェクションマッピングの映像送出にTouchDesignerを使用しています。
プロジェクションマッピングの制御ソフトとして出会ったのをきっかけにして、ノードベースのプログラミングによる多彩な制御が可能なことに魅力を感じ、以降ずっと送出ソフトとして使っています。

# 初期の画面
![初期の画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601755/acd5465d-6095-1c5c-c620-32cf97bea4ef.png)
使い始めた初期は，「ボタンを押すと映像が切り替わる」ことだけに集中して勉強をしましたので、ネットワーク画面にボタンを配置して、それを直接操作する形をとっていました。

この方式は、画面を見て操作をするということが可能な環境であれば特に大きな問題はなく、押したタイミングで画面が変わるため、わかりやすいということがいえます。

しかし、複雑なキューを組んでいったり、音と映像を同時に操作する私には、本番中の操作が煩雑になりヒューマンエラーを起こしやすいという欠点があります。

## 理想のシステム
+ 手元のコントローラで音も映像も操作する
+ 映像の送出は専用機（Windows）でやりたい
+ 音声の送出は使い慣れたMac上のQLabを使用する

まず、【TouchDesignerでどうやってキュー制御をするか】という問題にぶつかりました。

ここでいう「キュー制御」とは、演劇等の再生で求めている、「プログラムした順番通りに、想定通りの変化を起こす」ということです。

簡単なところで言うと、
1. あるセリフで映像1スタート
1. つぎのきっかけで映像1ストップ

というものですが、これだけの操作であれば、そもそもTouchDesignerである必要がありません。
私が望んでいることは、

1. きっかけの前までに、プロジェクターのシャッターを開ける
1. きっかけで、映像スタート
1. 映像が終わったらプロジェクターのシャッターを閉じる

とか、

1. きっかけの前までに、プロジェクターのシャッターを開ける
1. きっかけで、映像スタート
1. 映像をリアルタイムに変化させる
1. きっかけで、映像フェードアウト
1. 映像が黒になったらプロジェクターのシャッターを閉じる

のような複雑な制御が目標です。

可能ならば、その組んだキューを後から変更することも必要です。

そして、本番は可能な限り画面を見ずに、舞台を見ながら手元のコントローラで音と映像を制御すること。これは絶対条件でした。

# キュー操作ができるコンポーネントに出会った

[TauCeti Preset Engine](https://derivative.ca/community-post/asset/tau-ceti-preset-engine/61075)というものに出会いました

詳細は、省きますが、ネットワーク上のノードをドラックアンドドロップするだけで、必要なキューとして取り込み、状態をRecordできる上、変化する時間を決めてGoでキューを送ることができます。

使い方については、AlphaMoonbaseの[YouTube](https://www.youtube.com/watch?v=eYYBOyrZO0I)が公式にわかりやすく示してくれています。

## 遠隔で制御したい
Preset ManagerとCueliestというツールを手に入れ、キュー制御するのは容易になりましたが、これだと音と映像の複数台を同時に操作しなくてはなりません。

まずは、MIDI信号でやり取りを考え、MIDIコントローラを使っての制御を組みました。
しかし、私の環境の問題なのか、私の書いたpythonコードの問題なのか、機材の問題なのかはまだ検証していませんが、MIDIを送っていないときにもなにかしらの信号が送られてしまい、勝手にキューが走ってしまうという大問題が起こりました。

そこで、OSCを使用した遠隔制御で、音を制御しているMac上のQLabからOSCを送ることで制御することにしました。

![OSC制御のノード](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601755/2f8d1912-4567-4c34-5e01-8dfc803448ca.png)
幸いなことに、Preset Manager / Cuelistにはコマンドが想定してあり、`op('/cuelist/presetcuelist').Go()`でキューが走ります。

これを利用して、OSCで`/go`を受けたらキューを走らせるようにしています。


## 最近の画面構成
以上を元にした、最近の私の環境はこちらです。

1画面上に、送出するすべてのプレビュー画面とPJLinkで得られたプロジェクター情報を表示しており、プロジェクターが悪いのか、送出ができていないのかを一目で確認することができます。

また、各映像ソースがどのファイルで、どういう再生をしているのかも同時に表示させています。

![プロジェクター複数台制御](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601755/5863775e-00b1-4a11-3003-6f72e06ae202.png)

一番最近使ったプロジェクトでは、デジタル時計・アナログ時計を表示させ、またUI画面の全体の明るさを調節する「UI Opacityスライダー」を作ったことで、本番中の暗い客席でも見やすい画面を簡単に作ることができるようになりました。
![プロジェクター1台](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601755/3c554998-ba71-9fe7-268d-61a9558b765d.png)

参考までに、プロジェクトの全体像です。
![ネットワーク全体](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601755/f2fc3dd3-c510-6ce9-f265-0acab0581b5f.png)

送出映像の処理をしているコンテナ
![送出映像の処理](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601755/47ca3643-b6ac-b0ec-d3f5-d8be2c679184.png)

# （おまけ）COLORS base
REPLICATORなどを使う場合に、何種類もの色を設定して、変更したくなったときに全部変更するのがめんどくさいので、すべての色を管理するところを作っています。
![colors base](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601755/a23380d1-d57a-d9fb-0d2b-213688583375.png)

H,S,VのSとVの値から、`num_of_col`個の異なる色を作り出すようにしています。
作った色は`rgb`DATに格納してあり、どこからでも使いやすいようになっています。

また、`rgb`テーブルから、その色に合わせるのに最適な文字色（白か黒）を計算しています。WCAGを参考にしています。
このあたりのことはまたの機会に書くことにします。