WebToe 在瀏覽器裡跑的即時影像資料流引擎
運算子、連線、即時的 cook 迴圈,TouchDesigner 的工作方式,開一個瀏覽器分頁就能用。TOP 在 GPU 上算圖,CHOP 透過表達式驅動參數,SOP 與 MAT 餵給 3D 渲染器。把 .toe 拖進來,你的網路就打開了。
MIT · 零執行期相依套件 · WebGL2 + WebGPU · 260 KB JavaScript
- 連線 輸出接到輸入
- 虛線 表達式讀取的 CHOP 通道
- ƒ 由表達式驅動的參數
- ● 顯示旗標
編輯器裡
-
3D 管線
範例 10:Geometry COMP 裡的 SOP 緞帶與 instanced 球體,加上攝影機、兩盞燈、Render TOP 與光暈處理。輸出畫在網路背後,和 TouchDesigner 一樣。
-
所有家族一次用上
範例 09:27 個節點、帶 in/out 通道的萬花筒 COMP,以及透過即時表達式驅動整個 patch 的 CHOP 控制系統。
-
回授
feedback TOP 交回上一格畫面,再用逐漸變暗的 level,把滑鼠移動變成殘影。
-
CHOP 示波
選取一個 CHOP,檢視器就畫出它的通道:這裡是原始加總和延遲後的版本。
-
新增運算子
按 Tab 或雙擊開啟面板:每個家族一個分頁,搜尋跨所有家族。
-
WebGPU
同一個專案在
?backend=webgpu上執行。每個 2D TOP 都有手寫的 GLSL 與 WGSL。
01 · 匯入
拖進 .toe,就打開了。
把 TouchDesigner 專案拖進編輯器,它就變成一張即時運作的 WebToe 網路。支援的運算子會直接跑;其他的保留成佔位節點(stub),名稱、連線、參數、程式碼都留著,匯入報告會清楚列出各有多少。
在瀏覽器裡解碼
WebToe 直接讀取二進位的 .toe / .tox 容器:不需要安裝 TouchDesigner,不需要橋接程式,檔案也不會離開你的電腦。
- 在瀏覽器裡解碼一個 20 MB 演出檔(33,923 個檔案)
- 0.35 s
- 與 TouchDesigner 官方
toeexpand輸出逐位元組一致的正式專案檔 - 125 / 125
原生 .toe 解碼僅供研究用途。
備援:橋接程式
本機橋接程式在 127.0.0.1 上執行你自己安裝的 TouchDesigner 所附的 toeexpand,再把展開結果交給頁面。一行指令;或用 TouchDesigner 內附的 Python 執行 bridge.py。
npx webtoe # → http://127.0.0.1:9881/app/預設只綁定 127.0.0.1,不附帶任何 Derivative 的東西,處理完就刪除上傳的檔案。
在真實演出檔上實測
一個 20 MB 的正式演出專案,直接拖進頁面、在瀏覽器裡原生解碼。2026-10-04 在 MacBook Pro(M4 Max)的 Chrome 實測。八月時走橋接程式,同等大小的檔案要 8.0 秒。
- 匯入的節點
- 14,656
- 可執行(10,343 個節點)
- 71%
- 翻譯完成的 Python 表達式
- 2,246
- 從容器解出的檔案
- 33,923
- 從拖放到網路開始運作
- 0.54 s

還原的內容:節點類型與階層、跨 COMP 邊界與穿過 in/out 通道的連線、參數值與模式、DAT 文字與表格、網路版面,以及即時的 Python 表達式。能忠實翻譯的會翻成 WebToe 表達式(absTime.seconds*0.2 → time.seconds*0.2),其餘保持停用。匯入的 Python 永遠不會被執行。
02 · 資料流
運算子、連線、表達式,一個 cook 迴圈。
網路就是一群接在一起的運算子。每一格畫面,引擎從輸出往回拉,相依的節點只算一次,結果在這一格內快取。回授(feedback)是唯一刻意保留的循環:它讀的是上一格。
-
TOP28
GPU 影像運算子:產生器、濾鏡、合成、回授、lookup、render、媒體輸入與 NDI 收發。
-
CHOP14
通道:LFO、noise、math、lag、speed、mouse in、SOP to。驅動參數的數值都從這裡來。
-
SOP21
型別陣列幾何:基本形體、copy、skin、noise、twist,以及 COMP 網路用的 in/out。
-
MAT7
場景渲染器的材質:constant、lit(phong 與 pbr)、line、point sprite、wireframe。
-
COMP5
帶 in/out 通道的容器,以及 3D 物件:geometry(含 instancing)、camera、燈光。
-
DAT6
運算子可讀取的文字與表格:ramp 可以從表格讀色彩鍵值。
共 81 種運算子,建置時直接從引擎的註冊表計算。 所有運算子 →
每個參數都可以是表達式
表達式是 JavaScript,在固定的作用域裡求值:time、me、op()、parent()、ext(),加上數學函式庫(sin、clamp、fract、lerp、rand…)。可以即時讀取通道和其他參數,並有循環保護。
op('lfo1')['chan1'] // a CHOP channel, by name
parent().par.speed * 0.5 // a parameter up the hierarchy
time.seconds * 0.2 // engine time
ext('energy', 0.5) // a value the host page sends in03 · 對齊度
用真實的 TouchDesigner 作品來量。
「完整」由資料定義,不靠功能清單:60 個來自每日生成藝術創作的真實 TouchDesigner 專案(28,698 個節點,2022–2026),用官方 toeexpand 展開,依運算子類型計數。公開的只有彙總數字。
每一步都在同樣的 28,698 個節點上重新量測(docs/ROADMAP.md)。其餘節點匯入為佔位節點:結構、連線、版面與程式碼都保留。
- 一個 213 節點參考專案在同樣三步的可執行節點數
- 56 → 71 → 88
- TouchDesigner 官方運算子總數,分屬 7 個家族
- ~675
- WebToe 目前提供的運算子種類
- 81
- 一個 2025 年大量使用 POP 的專案,在 POP 對應到 SOP 實作後的可執行比例
- 43% → 73%
接下來,依序是
- 多樣本 CHOP 與時間切片:音訊、trail、resample、wave 的前提。
- GLSL TOP:把 TouchDesigner 注入的著色器約定轉接到 WebGL2。
- 在 WebGPU compute 上實作 POP:這正是第二個後端存在的理由。
Python 是永久的邊界。匯入的 Python 會保留、會顯示,但不會執行;規劃中的替代方案是需要手動啟用的 JavaScript 回呼 DAT。
04 · 引擎
小、明確、沒有相依套件。
為網頁從零寫成的原創引擎,不是移植。它在瀏覽器的 GPU 上實作同一套工作方式:運算子家族、接線網路、表達式驅動的參數、即時 cook 迴圈。
- 零執行期相依套件
- 整個 app 只有引擎、編輯器和著色器:260 KB JavaScript,gzip 後 76 KB。
- 兩個 GPU 後端
- 預設 WebGL2,加上
?backend=webgpu就切到 WebGPU,兩者共用一份與後端無關的 pass 約定。2D 已對齊;3D 場景 pass 目前只有 WebGL2。 - 一條相依規則
- import 只往下走,
core不 import 任何東西。運算子透過公開的registerOpAPI 註冊。 - 可嵌入
mountEditor(el, options)把不依賴框架的編輯器放進任何頁面。宿主頁面可以透過postMessage載入專案、驅動表達式。- 有版本的檔案格式
.webtoe.json帶有版本號與遷移鏈;不認得的運算子類型會降級成同家族的佔位節點,而不是讀取失敗。- 值得才用 WASM
- NDI 的像素轉換跑在 1 KB 的 WebAssembly 核心上,並有 JavaScript 備援。只有實測確實更快才採用 WASM。
apps/web ──▶ @webtoe/editor ──▶ @webtoe/ops ──┐
│ │ ├──▶ @webtoe/core
├──▶ @webtoe/gpu ───────┤
└──▶ @webtoe/io ────────┘
05 · 引擎 ↔ 演出
WebToe 是引擎,open-audiovisual 是演出。
open-audiovisual 是姊妹專案:一套網頁原生的影音演出框架,有 MIDI、和弦與姿態輸入、訊號到參數的對應層、含場景與 cue 的時間軸,以及後台監看。
它的 @openav/world-webtoe 轉接器把這個編輯器嵌進 iframe,每一格讀取演出解算後的參數,把有變動的送進 patch。在網路裡它們就是普通數字:任何表達式寫 ext('energy') 就能讀。
// the host page drives the patch; expressions read ext('energy')
frame.contentWindow.postMessage(
{ type: 'webtoe:ext', values: { energy: 0.8 } }, '*');
// swap the project
frame.contentWindow.postMessage(
{ type: 'webtoe:load', url: 'https://example.com/patch.webtoe.json' }, '*');06 · 開始
三種開始方式。
-
在瀏覽器裡
什麼都不用裝。打開編輯器,從工具列載入十個範例之一,或把專案檔拖到頁面上。
-
在你的電腦上
在 127.0.0.1 上啟動編輯器與匯入橋接程式,並自動開啟。需要 Node 20 以上。
npx webtoe # → http://127.0.0.1:9881/app/ -
從原始碼
整個 monorepo:引擎、運算子、兩個 GPU 後端、編輯器、匯入器、橋接程式。
npm run check會跑型別檢查與測試。git clone https://github.com/frank890417/WebToe.git cd WebToe && npm install npm run dev # → http://localhost:8643/app/
文件
- 開始使用在瀏覽器打開編輯器、用 npx webtoe 在本機執行,或建立 monorepo 開發環境。
- 範例編輯器內建的十個專案,各自示範什麼,以及直接打開它們的連結。
- 匯入 TouchDesigner 專案把 .toe 或 .tox 拖進編輯器。哪些內容會帶過來、哪些變成佔位節點、表達式如何翻譯,以及橋接程式與 toeexpand 兩條路。
- .toe 格式WebToe 如何在瀏覽器裡讀取 TouchDesigner 的二進位專案容器。
- 運算子WebToe 提供的每一個運算子,依家族列出、直接從引擎註冊表產生;以及 cook、佔位節點與自訂運算子的運作方式。
- 表達式用一行 JavaScript 表達式驅動任何參數,讀取時間、通道、其他參數,以及宿主頁面送進來的數值。
- 嵌入與外部控制把編輯器放進 iframe 或直接掛載到你的頁面,用網址載入專案,並以 postMessage 與 ext() 從外部驅動 patch。
- NDI 橋接程式透過一個小型本機橋接程式,從瀏覽器接收與送出 NDI 影像;像素轉換跑在 1 KB 的 WebAssembly 核心上。
- 架構套件與唯一的相依規則、兩個後端共用的 GPU pass 約定、cook 模型、檔案格式,以及背後的取捨。
- TouchDesigner 對齊度對瀏覽器引擎來說「往 TouchDesigner 對齊」是什麼意思、如何用 60 個真實專案量測、WebToe 現在在哪裡,以及接下來做什麼。