WebToe
GitHub 開啟編輯器

WebToe 在瀏覽器裡跑的即時影像資料流引擎

運算子、連線、即時的 cook 迴圈,TouchDesigner 的工作方式,開一個瀏覽器分頁就能用。TOP 在 GPU 上算圖,CHOP 透過表達式驅動參數,SOP 與 MAT 餵給 3D 渲染器。把 .toe 拖進來,你的網路就打開了。

MIT · 零執行期相依套件 · WebGL2 + WebGPU · 260 KB JavaScript

這張圖就是範例 03 本身,直接從專案檔讀出來畫的:三條 ramp 鏈由 LFO 透過表達式(虛線)旋轉,疊加合成後再偏移色相。trans1.rotate = op('lfo1')['chan1']trans2.rotate = op('lfo2')['chan1']trans3.rotate = op('lfo3')['chan1']lfo1CHOP · lfolfo2CHOP · lfolfo3CHOP · lforamp1TOP · ramptrans1TOP · transformƒramp2TOP · ramptrans2TOP · transformƒramp3TOP · rampƒtrans3TOP · transformƒcomp1TOP · compositehsv1TOP · hsvadjustƒout1TOP · out
  • 連線 輸出接到輸入
  • 虛線 表達式讀取的 CHOP 通道
  • ƒ 由表達式驅動的參數
  • ● 顯示旗標
03 這張圖就是範例 03 本身,直接從專案檔讀出來畫的:三條 ramp 鏈由 LFO 透過表達式(虛線)旋轉,疊加合成後再偏移色相。 打開它 →
WebToe 編輯器正在執行範例 03 lfo garden:ramp、transform、composite、hsv adjust 運算子組成的網路,每個節點都有即時預覽,輸出顯示在檢視器。
/app/ 的編輯器,以 WebGL2 執行同一個 patch。TOP 節點即時預覽:每一格畫面由同一個 GPU 合成器畫出檢視器和所有可見的縮圖。

編輯器裡

  1. 範例 10 3d lines:geometry、camera、light、render、blur、composite 節點,背後是渲染出的線條緞帶與橘色球體。

    3D 管線

    範例 10:Geometry COMP 裡的 SOP 緞帶與 instanced 球體,加上攝影機、兩盞燈、Render TOP 與光暈處理。輸出畫在網路背後,和 TouchDesigner 一樣。

  2. 範例 09 showcase:TOP、CHOP、COMP、DAT 節點組成的密集網路,檢視器顯示合成後的輸出。

    所有家族一次用上

    範例 09:27 個節點、帶 in/out 通道的萬花筒 COMP,以及透過即時表達式驅動整個 patch 的 CHOP 控制系統。

  3. 範例 02 feedback trails:rectangle、transform、composite、blur、feedback、level 接成迴圈。

    回授

    feedback TOP 交回上一格畫面,再用逐漸變暗的 level,把滑鼠移動變成殘影。

  4. 範例 05 chop playground:LFO、noise、math、lag、merge 等 CHOP,選取 merge 後檢視器畫出通道。

    CHOP 示波

    選取一個 CHOP,檢視器就畫出它的通道:這裡是原始加總和延遲後的版本。

  5. 新增運算子對話框,在一個小 noise patch 上方,以可搜尋的格狀清單列出 TOP 運算子。

    新增運算子

    按 Tab 或雙擊開啟面板:每個家族一個分頁,搜尋跨所有家族。

  6. 範例 03 在 WebGPU 後端上執行。

    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。

terminal
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
TouchDesigner 匯入報告:213 個節點,71 個可執行,142 個保留為佔位節點,結構、連線與版面都保留;9 個表達式完成翻譯,14 個保持停用。
一個 213 節點正式專案在 v1.1 時的匯入報告:71 個可執行。同一個檔案在第一輪演進後達到 88 個。

還原的內容:節點類型與階層、跨 COMP 邊界與穿過 in/out 通道的連線、參數值與模式、DAT 文字與表格、網路版面,以及即時的 Python 表達式。能忠實翻譯的會翻成 WebToe 表達式(absTime.seconds*0.2 → time.seconds*0.2),其餘保持停用。匯入的 Python 永遠不會被執行。

匯入 TouchDesigner 專案 →

02 · 資料流

運算子、連線、表達式,一個 cook 迴圈。

網路就是一群接在一起的運算子。每一格畫面,引擎從輸出往回拉,相依的節點只算一次,結果在這一格內快取。回授(feedback)是唯一刻意保留的循環:它讀的是上一格。

共 81 種運算子,建置時直接從引擎的註冊表計算。 所有運算子 →

每個參數都可以是表達式

表達式是 JavaScript,在固定的作用域裡求值:time、me、op()、parent()、ext(),加上數學函式庫(sin、clamp、fract、lerp、rand…)。可以即時讀取通道和其他參數,並有循環保護。

表達式 →

expressions
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 in

03 · 對齊度

用真實的 TouchDesigner 作品來量。

「完整」由資料定義,不靠功能清單:60 個來自每日生成藝術創作的真實 TouchDesigner 專案(28,698 個節點,2022–2026),用官方 toeexpand 展開,依運算子類型計數。公開的只有彙總數字。

語料庫中能以 WebToe 運算子執行的節點比例
  1. v1 第一個版本32.3%
  2. 第一輪 表達式 v2、路由類 TOP、DAT 表格47.1%
  3. R3 3D 管線:SOP、MAT、geometry、camera、render62.3%

每一步都在同樣的 28,698 個節點上重新量測(docs/ROADMAP.md)。其餘節點匯入為佔位節點:結構、連線、版面與程式碼都保留。

一個 213 節點參考專案在同樣三步的可執行節點數
56 → 71 → 88
TouchDesigner 官方運算子總數,分屬 7 個家族
~675
WebToe 目前提供的運算子種類
81
一個 2025 年大量使用 POP 的專案,在 POP 對應到 SOP 實作後的可執行比例
43% → 73%

接下來,依序是

  1. 多樣本 CHOP 與時間切片:音訊、trail、resample、wave 的前提。
  2. GLSL TOP:把 TouchDesigner 注入的著色器約定轉接到 WebGL2。
  3. 在 WebGPU compute 上實作 POP:這正是第二個後端存在的理由。

Python 是永久的邊界。匯入的 Python 會保留、會顯示,但不會執行;規劃中的替代方案是需要手動啟用的 JavaScript 回呼 DAT。

TouchDesigner 對齊藍圖 →

04 · 引擎

小、明確、沒有相依套件。

為網頁從零寫成的原創引擎,不是移植。它在瀏覽器的 GPU 上實作同一套工作方式:運算子家族、接線網路、表達式驅動的參數、即時 cook 迴圈。

零執行期相依套件
整個 app 只有引擎、編輯器和著色器:260 KB JavaScript,gzip 後 76 KB。
兩個 GPU 後端
預設 WebGL2,加上 ?backend=webgpu 就切到 WebGPU,兩者共用一份與後端無關的 pass 約定。2D 已對齊;3D 場景 pass 目前只有 WebGL2。
一條相依規則
import 只往下走,core 不 import 任何東西。運算子透過公開的 registerOp API 註冊。
可嵌入
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 ────────┘
npm workspaces,import 只往一個方向流。 架構 →

05 · 引擎 ↔ 演出

WebToe 是引擎,open-audiovisual 是演出。

open-audiovisual 是姊妹專案:一套網頁原生的影音演出框架,有 MIDI、和弦與姿態輸入、訊號到參數的對應層、含場景與 cue 的時間軸,以及後台監看。

它的 @openav/world-webtoe 轉接器把這個編輯器嵌進 iframe,每一格讀取演出解算後的參數,把有變動的送進 patch。在網路裡它們就是普通數字:任何表達式寫 ext('energy') 就能讀。

host page
// 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 · 開始

三種開始方式。

  1. 在瀏覽器裡

    什麼都不用裝。打開編輯器,從工具列載入十個範例之一,或把專案檔拖到頁面上。

    開啟編輯器

  2. 在你的電腦上

    在 127.0.0.1 上啟動編輯器與匯入橋接程式,並自動開啟。需要 Node 20 以上。

    terminal
    npx webtoe        # → http://127.0.0.1:9881/app/
  3. 從原始碼

    整個 monorepo:引擎、運算子、兩個 GPU 後端、編輯器、匯入器、橋接程式。npm run check 會跑型別檢查與測試。

    terminal
    git clone https://github.com/frank890417/WebToe.git
    cd WebToe && npm install
    npm run dev       # → http://localhost:8643/app/

文件