TouchDesigner + Claude
Updated: 2026-05*
Claude生成記事であり、一部まだ未検証。
1. はじめに
ここではTouchDesigner(以下TD)からClaude(Anthropic社の大規模言語モデル)を呼び出して連携する手法を、Windows / macOS両環境で習得する。Claudeは自然言語による指示を受けて、文章生成・画像理解・構造化データ生成などを行うAIである。TDからClaude APIを利用することで、ノードベースでは記述しづらい「意味的な判断」「言語的な応答」「文脈に応じたパラメータ生成」を作品に組み込めるようになる。
本教材ではAPIキーの準備から、テキスト生成・Vision(画像入力)・Tool use(関数呼び出し)といった代表的な利用パターンまでを段階的に扱う。前提として、Pythonの基本構文と、TDのText DAT・Web Client DATの基本操作を一通り把握していることが望ましい。
1.1 本教材で扱う内容
- Anthropic APIキーの取得と環境変数による安全な管理
- anthropic Python SDKのTDプロジェクトへの導入
- Web Client DATによるSDK不要のAPI呼び出し
- JSON形式の構造化応答によるパラメータ自動生成
- Vision機能によるTOP画像のClaude投入
- ストリーミング応答とTool useの応用
1.2 参考サイト
本稿の内容は以下のサイトおよび公式ドキュメントを参考にしている。
参考)
- Anthropic公式ドキュメント
- Anthropic Python SDK(GitHub)
- Models概要
- Vision(画像入力)
- Tool use
- Streaming Messages
- Python in TouchDesigner(Derivative公式)
2. 開発環境
ClaudeをTDから利用するには、Anthropic APIへの接続準備と、TDからAPIを呼ぶ手段の選定が必要となる。前者は両OS共通、後者はSDK方式とWeb Client DAT方式の二択となる。
2.1 Anthropic APIキーの取得
ClaudeのAPI利用にはAnthropicアカウントとAPIキーが必要である。手順は以下の通り。
- console.anthropic.com にアクセスしアカウントを作成する
- 「Billing」から最小額のクレジット(USD 5程度で本教材の事例には十分)をチャージする
- 「API Keys」から新規キーを発行する
- 発行されたキー(
sk-ant-で始まる文字列)を控える
※ APIキーは発行直後の画面でしか全体表示されないため、必ずその場でコピーしておく ※ APIキーをTDプロジェクトファイル内、Text DATの本文、git管理下のテキストに直接書き込んではならない。漏洩した場合、無関係な第三者によって課金される
2.2 APIキーを環境変数で渡す
APIキーはOSの環境変数として設定し、TD内からはos.environ.get('ANTHROPIC_API_KEY')で読み出す形が安全である。
Windowsでの設定手順
- スタートメニューから「環境変数」を検索→「環境変数を編集」を開く
- ユーザー環境変数として新規追加する
- 変数名:ANTHROPIC_API_KEY
- 変数値:(取得したsk-ant-…の値)
- TDを再起動して反映させる
macOSでの設定手順
- ターミナルで
~/.zshrcを開き、末尾に以下を追記するexport ANTHROPIC_API_KEY="sk-ant-..."
source ~/.zshrcで反映する- 同じターミナルから
open -a TouchDesignerでTDを起動する
※ Macの場合、Finderからアイコンをダブルクリックして起動すると環境変数を引き継がないケースがある。確実に渡したい場合はターミナルからopen -aで起動する
設定が正しく入ったかは、TDのTextport(Alt+T、Macは⌥+T)で以下を実行して確認する。
import os
key = os.environ.get('ANTHROPIC_API_KEY')
print(key[:15] + '...' if key else 'not set')sk-ant-api03-...のように先頭が表示されれば成功である。not setが返る場合は変数がTDに渡っていないため、TDを再起動するか起動方法を変える必要がある。
2.3 anthropic SDKの導入
TDからClaude APIを呼ぶには二通りの方法がある。
- 方法A:公式のanthropic Python SDKを利用する。記述がシンプルで機能が豊富。ただし追加インストールが必要
- 方法B:TD標準のWeb Client DATで直接APIを叩く。追加インストール一切不要
本教材では3章前半でAを、3章末尾でBを示す。SDKを使う場合は以下の手順でインストールする。SDK不要で進める場合(特に環境構築を最小化したい場合)はこの節を飛ばしてよい(任意)。
Windowsでの導入
- コマンドプロンプトを開き、以下を実行する
cd C:\TD_Projects\my_project
"C:\Program Files\Derivative\TouchDesigner\bin\python.exe" -m pip install --target=python_libs anthropicmacOSでの導入
- ターミナルで以下を実行する(HomebrewでTD同バージョンのPythonが入っている前提)
cd ~/TD_Projects/my_project
/opt/homebrew/bin/python3.11 -m pip install --target=python_libs anthropic※ Mac環境構築の前提(Homebrewによる並行Pythonのインストール)については、別教材「TouchDesigner + Python」の2章を参照
※ インストール先がプロジェクトフォルダ内のpython_libsであることが重要である。グローバルに入れた場合TDは参照しない
導入確認はTextportで以下を実行する。
import sys
sys.path.append(project.folder + '/python_libs')
import anthropic
print(anthropic.__version__)バージョン番号が表示されれば成功である。
3. 簡単な連携の事例
ここでは最小構成で動作する4つの事例を順に行う。3.1〜3.3は方法A(SDK利用)、3.4は方法B(Web Client DAT)で記述する。
3.1 一行の応答を取得する
Claudeに一言返してもらうだけの最小例から始める。
- Text DAT「td_claude_hello」
- Edit Contents…から以下を貼り付ける
import sys, os
sys.path.append(project.folder + '/python_libs')
import anthropic
client = anthropic.Anthropic(api_key=os.environ.get('ANTHROPIC_API_KEY'))
msg = client.messages.create(
model='claude-haiku-4-5-20251001',
max_tokens=100,
messages=[
{'role': 'user', 'content': 'TouchDesignerを一行で説明せよ'}
]
)
print(msg.content[0].text)Text DATを右クリック→Run Scriptで実行する。1〜3秒後にTextportに応答テキストが表示されれば成功である。
※ モデルはclaude-haiku-4-5-20251001を指定している。Haikuは高速かつ低コストの軽量モデルで、本教材の事例はこれで十分まかなえる。より高品質な応答が必要な場合はclaude-sonnet-4-6、最高品質を求める場合はclaude-opus-4-7に切り替える
3.2 詩を生成してText TOPに表示する
応答テキストをTOP経由で画面に表示する事例。
ノード構成は以下のように接続する。
- Text DAT「td_claude_poem」(応答の格納先)
- Text DAT「td_claude_runner」(実行用スクリプト)
- Text TOP「text_display」
Text TOP「text_display」の設定
- Text:op(’td_claude_poem’).text(式モードで参照)
- Font Size:48
- Resolution:1280 × 720
Text DAT「td_claude_runner」のスクリプト
import sys, os
sys.path.append(project.folder + '/python_libs')
import anthropic
client = anthropic.Anthropic(api_key=os.environ.get('ANTHROPIC_API_KEY'))
msg = client.messages.create(
model='claude-haiku-4-5-20251001',
max_tokens=200,
messages=[
{'role': 'user', 'content': '光と影をテーマに三行詩を作れ。本文のみ返し、前置きや解説はしないこと'}
]
)
op('td_claude_poem').text = msg.content[0].texttd_claude_runnerをRun Scriptするたびに、新しい三行詩がText TOP上に表示される。
※ API呼び出しには1〜3秒のレイテンシがあるため、毎フレーム呼び出す用途には向かない。ボタン押下・音量しきい値・タイマー等のイベント駆動で発火させるのが現実的である
3.3 JSON形式でパラメータを受け取る
Claudeの強みは、自由テキストの応答だけでなく、指示に従った構造化データを返せる点にある。シーンの雰囲気を表すテキストから、複数のパラメータ値を一度に生成させる事例を扱う。
- Text DAT「td_claude_mood」
import sys, os, json
sys.path.append(project.folder + '/python_libs')
import anthropic
client = anthropic.Anthropic(api_key=os.environ.get('ANTHROPIC_API_KEY'))
prompt = '''
シーンの雰囲気を表すパラメータをJSONで返せ。前置き、説明、コードブロック記号は禁止する。
返答は以下のスキーマに厳密に従うこと:
{
"r": float 0.0-1.0,
"g": float 0.0-1.0,
"b": float 0.0-1.0,
"speed": float 0.0-2.0,
"noise_amount": float 0.0-1.0
}
r/g/bはシーンを代表する色のRGB値(0.0-1.0)として返すこと。
今回のテーマは「真夜中の海底洞窟」
'''
msg = client.messages.create(
model='claude-haiku-4-5-20251001',
max_tokens=300,
messages=[{'role': 'user', 'content': prompt}]
)
params = json.loads(msg.content[0].text)
op('constant1').par.colorr = params['r']
op('constant1').par.colorg = params['g']
op('constant1').par.colorb = params['b']
op('lfo1').par.rate = params['speed']
op('noise1').par.amp = params['noise_amount']ノード構成は以下の通り。
- Text DAT「td_claude_mood」
- Constant TOP「constant1」
- LFO CHOP「lfo1」
- Noise TOP「noise1」
テーマ部分(「真夜中の海底洞窟」)を「夏の昼下がりの公園」「廃工場の最深部」「桜が散る石庭」などに差し替えると、それぞれの雰囲気に応じたパラメータが返ってくる。
※ 稀にClaudeが指示を破って前置き文を付けて返すことがある。その場合json.loadsで例外が出るため、try/exceptでラップするか、より大きいモデル(sonnet以上)を使うと安定する
※ HSV色空間で返させて手元でRGB変換する方法もあるが、教材としてはRGB直指定が最も結果が予測しやすい
※ 構造化応答をより厳密に制御したい場合は、4.3で扱うTool useの仕組みを使うとスキーマ違反を強制的に防げる
3.4 SDK不要でWeb Client DATから呼ぶ
anthropic SDKを入れたくない場合、TD標準のWeb Client DATで直接APIを叩ける。配布先の環境構築を最小化したい場合や、Mac環境でHomebrewのセットアップを避けたい場合に有用である。
ノード構成は以下のように接続する。
- Table DAT「headers」(リクエストヘッダ用)
- Web Client DAT「webclient1」
- Text DAT「response」(応答の取り出し用)
Table DAT「headers」の中身(2列のテーブル、左列がヘッダ名、右列が値)
- 1行目:x-api-key | (APIキーの値)
- 2行目:anthropic-version | 2023-06-01
- 3行目:content-type | application/json
Web Client DAT「webclient1」の設定
- Request URL:https://api.anthropic.com/v1/messages
- Request Method:POST
- Request Headers DAT:headers
- TDのバージョンによりパラメータ名が「Headers DAT」「Header Table」等と表記揺れする。Web Client DATのパラメータページでヘッダ参照用のDATパラメータを探して指定する
- Request Body:以下のJSON文字列
{
"model": "claude-haiku-4-5-20251001",
"max_tokens": 200,
"messages": [
{"role": "user", "content": "TouchDesignerについて一文で述べよ"}
]
}Web Client DATのRequest pulseボタンを押すと送信され、応答がwebclient1のresponseテーブルに格納される。
※ Table DATにAPIキーをそのまま書き込むと、プロジェクトファイル保存時にキーが残ってしまう。実運用ではTable DATの値をスクリプトで起動時に動的に挿入するか、別途環境変数読み出しのText DATから注入する形にする ※ Web Client DAT方式の弱点はストリーミング応答が扱いづらい点と、Visionや複雑なTool useでBodyのJSONを手書きする必要がある点である。本格利用ではSDK方式を推奨する
4. 実践につながる簡単な実験
ここではClaudeをTDの中でより主体的に使う3つの実験を行う。
4.1 Vision:カメラ画像をClaudeに見せて反応してもらう
Claudeは画像入力に対応している。Webカメラのフレーム、あるいはTD内で生成中の映像そのものをClaudeに送り、内容の説明や状態判定を文章で返してもらえる。
ノード構成は以下のように接続する。
- Video Device In TOP「videoin1」
- Resolution TOP「resolution1」
- Text DAT「td_claude_vision」(解析スクリプト)
- Text DAT「caption」(応答の格納先)
- Text TOP「caption_display」
Resolution TOP「resolution1」の設定
- Input TOP:videoin1
- Output Resolution:512 × 512
- Resolution:Custom Resolution
Text TOP「caption_display」の設定
- Text:op(‘caption’).text(式モード)
Text DAT「td_claude_vision」のスクリプト
import sys, os, base64
sys.path.append(project.folder + '/python_libs')
import anthropic
# 対象TOPを一時PNGに保存してbase64化する
top = op('resolution1')
tmp_path = project.folder + '/tmp_frame.png'
top.save(tmp_path)
with open(tmp_path, 'rb') as f:
img_b64 = base64.b64encode(f.read()).decode('utf-8')
os.remove(tmp_path) # 一時ファイルは読み終えたら削除
client = anthropic.Anthropic(api_key=os.environ.get('ANTHROPIC_API_KEY'))
msg = client.messages.create(
model='claude-haiku-4-5-20251001',
max_tokens=200,
messages=[{
'role': 'user',
'content': [
{'type': 'image', 'source': {
'type': 'base64',
'media_type': 'image/png',
'data': img_b64
}},
{'type': 'text', 'text': '映っているものを20字以内の俳句調で表現せよ。本文のみ返せ'}
]
}]
)
op('caption').text = msg.content[0].textRun Scriptするたびに、その瞬間のカメラ映像をClaudeが俳句調で詠み、Text TOPに表示される。
※ TOP.save()は同期処理である。毎フレーム呼ぶとフレームレートが落ちるため、Timer CHOPで数秒〜数十秒に1回程度の発火に留める ※ 解像度は512 × 512程度で十分で、それ以上はAPIコストが上がるだけで応答品質はほぼ変わらない
4.2 ストリーミング応答で文字を逐次描画する
Claudeの応答は通常完了まで待つが、ストリーミングモードでは生成途中のトークンを順次受け取れる。長文を生成しつつ、生成と同時に画面に流す演出が可能となる。
- Text DAT「story」(応答テキストの蓄積先)
- Text DAT「td_claude_streamer」(実行スクリプト)
- Text TOP「story_display」
Text TOP「story_display」の設定
- Text:op(‘story’).text(式モード)
Text DAT「td_claude_streamer」のスクリプト
import sys, os
sys.path.append(project.folder + '/python_libs')
import anthropic
client = anthropic.Anthropic(api_key=os.environ.get('ANTHROPIC_API_KEY'))
op('story').text = '' # 描画前にクリア
with client.messages.stream(
model='claude-haiku-4-5-20251001',
max_tokens=500,
messages=[
{'role': 'user', 'content': '無人駅で起こる短編怪談を200字程度で。本文のみ返せ'}
]
) as stream:
for chunk in stream.text_stream:
op('story').text = op('story').text + chunk実行すると、storyに格納されるテキストがClaudeの生成速度に合わせて少しずつ伸びていく。Text TOPでstoryを参照しているため、画面上の文字が次第に増えていく演出となる。
※ TDのメインスレッドをブロックするため、ストリーム中はTD全体のフレームレートが落ちる。本格利用では公式ドキュメントPython Threadingを参照し、別スレッドで実行する構成に変更する
4.3 Tool useでClaudeにTDオペレータを操作させる
Tool useは、Claudeに「あなたが呼べる関数の一覧」を渡し、その関数を呼び出してもらう機能である。これによりClaudeに自然言語で指示するだけで、TD内のオペレータを直接操作させる経路が作れる。
- Text DAT「td_claude_tooluse」
import sys, os
sys.path.append(project.folder + '/python_libs')
import anthropic
client = anthropic.Anthropic(api_key=os.environ.get('ANTHROPIC_API_KEY'))
tools = [{
'name': 'set_constant_color',
'description': 'シーン中央のConstant TOPの色(RGB)を変更する',
'input_schema': {
'type': 'object',
'properties': {
'r': {'type': 'number', 'description': '赤成分、0.0から1.0'},
'g': {'type': 'number', 'description': '緑成分、0.0から1.0'},
'b': {'type': 'number', 'description': '青成分、0.0から1.0'}
},
'required': ['r', 'g', 'b']
}
}, {
'name': 'set_noise_amount',
'description': 'シーン全体のノイズ量を変更する',
'input_schema': {
'type': 'object',
'properties': {
'amount': {'type': 'number', 'description': '0.0(平穏)から1.0(最大荒れ)'}
},
'required': ['amount']
}
}]
user_prompt = '夕焼けの色にして、空気は少しざらついた感じで頼む'
msg = client.messages.create(
model='claude-sonnet-4-6',
max_tokens=500,
tools=tools,
messages=[{'role': 'user', 'content': user_prompt}]
)
for block in msg.content:
if block.type == 'tool_use':
args = block.input
if block.name == 'set_constant_color':
op('constant1').par.colorr = args['r']
op('constant1').par.colorg = args['g']
op('constant1').par.colorb = args['b']
elif block.name == 'set_noise_amount':
op('noise1').par.amp = args['amount']「夕焼けの色にして、空気は少しざらついた感じで頼む」という曖昧な指示を渡すだけで、Claudeがset_constant_color(r=0.95, g=0.45, b=0.15)とset_noise_amount(amount=0.25)のような呼び出しを返し、それに応じて実際のパラメータが変更される。
tools配列にset_lfo_rate、set_camera_zoom、play_audio_clipなど任意の関数を追加していけば、Claudeを「自然言語で操作できる演出オペレータ」として扱える。
※ Tool useはモデルの推論能力に依存する。haikuでも基本動作はするが、複数のtoolを状況に応じて選び分けるような判断はsonnet以上が安定する ※ 3.3のJSONプロンプトと比較して、Tool useはAnthropic側がスキーマ違反を防ぐため、構造化応答の確実性が高い
5. おもしろネタ3つ
5.1 ネタ①:AI観客 - 作品を見続けて評するClaude
Vision機能を使い、TDの出力画面そのもの(Render TOPやWindow CompのキャプチャTOP)を一定間隔でClaudeに送る。プロンプトを「あなたは現代美術評論家である。今あなたが見ている映像作品の印象を2文で述べよ」とすると、自作のTD作品をClaudeが評論し続けるインスタレーションが成立する。
- Render TOP「render1」(または出力中の最終TOP)
- Timer CHOP「timer1」(30秒周期)
- CHOP Execute DAT「dat_exec1」(timer1のCycleコールバック)
- Text DAT「critic_log」(評論文の蓄積)
- Text TOP「critic_display」(画面下部に重畳)
CHOP Execute DATのonValueChangeまたはonOffToOnでrender1の現在フレームをClaudeに送り、応答をcritic_logに追記する。プロンプト本体は4.1のスクリプトを流用し、テキスト部分を以下に置き換える。
'あなたは現代美術評論家である。今あなたが見ている映像作品の印象を、専門用語を交えつつ2文で述べよ'応答をリングバッファ的にcritic_logに溜めると、会期中Claudeのコメントが少しずつ蓄積されていく様子そのものが鑑賞対象になる。展示後にCSVとして書き出せば「Claudeから見た本作品の批評集」が記録として残る(おまけ)。
5.2 ネタ②:自己進化するシーン - Claudeが次の30秒を設計する
3.3のJSONパラメータ生成を発展させ、Claudeに「直前のシーンのパラメータ」と「観客の現在の滞在時間」を渡し、次の30秒間どう演出すべきかを答えさせる。
- Timer CHOP「scene_timer」(30秒周期で発火)
- Text DAT「td_claude_director」(演出依頼スクリプト)
- Animation COMP「anim1」(応答パラメータの補間先)
td_claude_directorのプロンプト部分(以下は枠組みのスケッチ。previous_params は前30秒間のパラメータ辞書、dwell_time はTimer CHOPやSensorから取得した観客の滞在秒数、schema は3.3のJSONスキーマ文字列を流用する前提)
prompt = f'''
あなたは映像インスタレーションの演出家である。
直前30秒間のシーンのパラメータは以下の通りであった:
{json.dumps(previous_params, ensure_ascii=False)}
観客は現在この作品の前に{dwell_time}秒間立ち続けている。
次の30秒、観客を退屈させずかつ刺激しすぎないために、以下のスキーマに沿って次のシーンのパラメータをJSONで返せ。説明は不要:
{schema}
'''応答パラメータをAnimation COMPの補間先として流し込めば、Claudeが連続的に演出を設計し続けるシーンとなる。観客が長居するほど刺激を強めにする、短時間で離脱した場合は次の客のために穏やかに戻す、といった文脈依存の演出ロジックを自然言語で書ける(おまけ)。
※ 30秒に1回のAPI呼び出し(claude-haiku-4-5、入出力合わせて概ね数百〜千トークン程度)の場合、1時間あたりのコストは概算で数十セント程度のオーダーになる(トークン数とモデル単価により上下する)
5.3 ネタ③:制作中のネットワークについて壁打ち相手になってもらう
最後に、作品鑑賞ではなく制作支援としての使い方。現在開いているTDネットワークの構成(オペレータ名、種別、接続関係、主要パラメータ)をPythonで自動収集し、Claudeに「このネットワークをもっと面白くするには?」と相談する。
- Text DAT「td_claude_advisor」
import sys, os, json
sys.path.append(project.folder + '/python_libs')
import anthropic
# このスクリプトを置いたText DATの親COMP直下のオペレータ情報を収集する
# /project1 全体を対象にしたい場合は parent() を op('/project1') に置き換える
ops_info = []
for c in parent().findChildren(depth=1):
ops_info.append({
'name': c.name,
'type': c.OPType,
'inputs': [i.name for i in c.inputs if i is not None]
})
client = anthropic.Anthropic(api_key=os.environ.get('ANTHROPIC_API_KEY'))
msg = client.messages.create(
model='claude-sonnet-4-6',
max_tokens=1000,
messages=[{
'role': 'user',
'content': f'''現在制作中のTouchDesignerネットワークは以下の通りである:
{json.dumps(ops_info, ensure_ascii=False, indent=2)}
このネットワークをより面白くする変更案を3つ提案せよ。各案について
- 追加または変更すべきオペレータ
- なぜその変更で表現が面白くなるか
を簡潔に述べよ。'''
}]
)
print(msg.content[0].text)実行するとTextportに3つの改善案が表示される。Slack送信用のWebhookに繋げば、制作中に常駐させる相棒として機能する。「使い慣れたオペレータの組み合わせばかりで似た画面しか作れない」という袋小路を抜け出す助けになる。
※ ネットワーク情報の収集を再帰的にすればCOMP内部まで読めるが、トークン消費が増える。最初はdepth=1で十分
6. まとめ
ClaudeをTDから扱うときの要点を整理する。
用途別の推奨モデルは以下の通り。
- 短い応答・JSONパラメータ生成・俳句や短文生成:claude-haiku-4-5-20251001
- Tool use・構造的判断・Vision応答:claude-sonnet-4-6
- 重要な演出切替や長文生成:claude-opus-4-7
Claudeは(少なくとも現時点では)ノードやCHOPと違って「毎フレーム呼べる」ものではなく、レイテンシ・コストともに数秒〜数十秒に1回のイベント駆動が前提となる。そのため作品設計の段階で「いつClaudeに聞くか」「何を聞くか」をシーン設計に組み込む発想が要となる。
学習の順序としては、
- 3.1〜3.2で「呼び出して応答を受ける」体験をする
- 3.3でJSON応答によるパラメータ生成に慣れる
- 4.1のVisionで画像入力を体験する
- 4.3のTool useでClaudeを能動的なオペレータとして扱う
の流れが取り組みやすい。Claudeを「もう一人の演出担当」「最初の観客」「制作中の壁打ち相手」として組み込むと、TDのノード構成だけでは到達しづらい、意味的・言語的な表現の幅が広がる。
