# 水裡學・現場操作說明（給 13行／白輻射）

> 2026-09-07 發布版本，手機排隊與控制協定須與 relay 同步使用。網址與參數以本文為準；解鎖鑰匙另行私訊（不在此文件）。
> ⚠️ 瀏覽器自動播放政策：投影機的 Chrome 請用 `--autoplay-policy=no-user-gesture-required` 啟動（或開頁後點一下畫面），常態的互動聲響與整點表演的音樂才出得來。[私密展牆啟動工具](PRIVATE-WALL-SETUP.md) 已帶這個旗標。

## 網址

| 用途 | 網址 | 說明 |
|---|---|---|
| **曲面牆投影（13行）** | `https://cymatics.art.cheyuwu.com/?key=＜鑰匙＞&out=1&kiosk=1` | 4156×1200 滿版、無遮罩、無 UI；每半小時整自動表演（:00 與 :30，對網路時間；9/16 哲宇改）；自動連上牆管線。**帶 key 開過一次會記住，之後重整不用帶。** ✅ **2026-09-20 起，帶鑰匙開的牆會自己領到控制憑證**（開頁向同站 `/wall-token` 用同一把鑰匙換一次、記在這個分頁），**不用再手動帶 `&wallToken=`**——重開機、重開瀏覽器都一樣自動。驗法：開頁後 relay `/online` 那台終端 `synced:true`。手動帶 `&wallToken=`（找哲宇）仍可、且優先；[私密展牆啟動工具](PRIVATE-WALL-SETUP.md)也照舊。（9/17 實撞：沒帶 wallToken 的牆只顯示歷史的水、收不到觀眾送上來的水，手機那邊顯示牆離線——這條路現在只在鑰匙錯或 Pages 沒設 `WALL_TOKEN` 時才會發生。）表演音檔在這個網址**預設不播**（現場音樂由中央機播、網頁只對時；9/20 03:1x 哲宇拍板 A——正式網址已給出去、預設必須是對的那個）；本機要聽對位加 `&music=1`。 |
| 觀眾 QR（問卷） | `https://cymatics.art.cheyuwu.com/survey/` | 五題 → 顯影 → 上牆 → 分享／大家的水 |
| 一顆水的分享頁 | `https://cymatics.art.cheyuwu.com/w?m=…&seed=…` | 觀眾分享出去的連結（有預覽卡） |
| 母網域（作品本體） | `https://cymatics.art.cheyuwu.com/` | **9/18 起上鎖**：沒鑰匙會被送到問卷；有鑰匙＝上面投影網址 |
| **現場控制台** | `https://cymatics.art.cheyuwu.com/control/` | **用帳號登入**（Cloudflare Access 寄一次性密碼到信箱；哲宇／Ariel／support），不用鑰匙。手機就能按：▶ 表演／■ 中止／⏸ 暫停／🎲 隨機水／▦ 對位圖（格線・十字・色條・邊框）／HUD／重整／現場參數，右邊看作品資訊（哪台機器・fps・牆上現在哪顆水・誰在排隊・下次表演倒數）。說明 [CONTROL.md](CONTROL.md) |
| 聲音後台（技術） | `https://cymatics.art.cheyuwu.com/mixer/?key=＜鑰匙＞` | **同一把鑰匙上鎖**（沒鑰匙一樣送到問卷）。開著會在自己的 iframe 跑一面小牆（`live=0` 不搶觀眾的票、`ga=0` 不算一台終端），看七聲部、狀態機、表演時間軸（對時用：黃色播放頭＋四幕底色）、訊號鏈；調整只在那一頁，正式牆不受影響。說明 [AUDIO-MIXER.md](AUDIO-MIXER.md)。**現場投影機不要開這個**，用另一台電腦看 |

## 投影機參數（都在網址後面加）

| 參數 | 意思 |
|---|---|
| `out=1` | 畫布鎖 **4156×1200**（實際解析度；播放端拉成 5760×1200 由 13行 處理） |
| `kiosk=1` | 全黑底、無任何 UI／提示／標準字 |
| （表演排程） | **固定每半小時整（:00 與 :30）自動表演一分鐘，沒有參數可改**（9/16 哲宇：拿掉 `perf=`，舊網址帶著也會被忽略）。LED 定點時窗（週一至四 10:30–17:30、週五至日 10:30–19:30）**只在 `out=1` 或 `kiosk=1` 的展場機遵守**，主頁面測試任何時段都演 |
| `window=1` / `window=0` | 強制遵守／強制忽略 LED 時窗 |
| `mask=1` | 只給我們自己預覽平行四邊形遮罩；**正式投影不要加**（13行 現場裁切） |
| `room=xxx` | 上牆管線分房測試（手機端問卷也要同房才會互通；正式不用加） |
| `live=0` | 關掉上牆管線（不建議） |
| `sound=0` | 關掉常態的互動聲響（牆預設**有聲**，見下「常態」；表演一分鐘內自動靜音，不會跟表演音樂打架） |
| `vol=0.5` | 互動聲響音量 0–1（預設 0.7；現場對音響時調） |
| `music=1` / `music=0` | 表演音檔從這台出不出聲。`out=1`／`kiosk=1`／`wall=1` 的展場機**預設不播**（中央機播；9/20 哲宇拍板 A），本機測對位才加 `music=1`；主頁面預設播；時間軸與對時不受影響 |
| `perfOffset=2` | **9/20 對時旋鈕。** 排程整體平移幾秒（可負、可小數）：中央機的音樂在整點＋2 秒才起，就填 2；提早就填負。只影響每半小時的自動排程，Enter 手動觸發不受影響。⚠️ 兩台機器各自讀**系統時鐘**（程式沒有網路校時）——先把牆機與中央機都對 NTP，再用這個旋鈕修剩下的固定差 |
| `preRoll=5` / `fadeOut=5` | 整點前轉黑幾秒／收尾淡出幾秒（9/17 決議「先以 5 秒為主，現場再彈性調」）。網址改了就生效，不用改 `performance.json` 重部署；現場定案的值回來寫進 JSON |
| `musicOffset=0` | 牆自己那份表演音檔的起點（`clock.musicOffsetSec`）。牆機預設不播，這個只在 `music=1` 本機對位時有感——**跟中央機對時請用 `perfOffset`** |
| `remote=0` | 不問 relay 的「遠端參數」（見下一節）。預設會問：正式網址已經給出去、機器上很難換網址，上面這些旋鈕都可以從遠端設，**網址自己帶的永遠優先** |

## 遠端參數（2026-09-20，哲宇：「正式網址已經給出去、他們很難在機器上換網址；能從網頁端處理多少就處理多少，但不要影響原本的網址跟 param 功能」）

牆機的網址不用動。relay 存一份「這房的現場參數」，展場機（`out=1`／`kiosk=1`／`wall=1`）每次開頁先問它（2 秒內沒回就照舊開），
**網址沒帶的參數用它補**；網址自己帶的鍵永遠優先（所以原本的網址與 param 功能一個都不受影響）。改參數＝改 relay 一筆，牆收到廣播自己重整（跟遠端重整同一條路），不碰機器。

允許遠端設的鍵（白名單，其餘忽略）：`music`、`vol`、`perfOffset`、`preRoll`、`fadeOut`、`musicOffset`、`device`、`idle`、`dwell`。
`room`／`key`／`wallToken` **永遠不允許**（房要在連線前決定、鑰匙不進 relay）。

怎麼設（需要 `WALL_TOKEN`，找哲宇；studio.monolab.world 維運頁的「⚙️ 現場參數」表單走的是同一條）：

```sh
RELAY=https://cymatics-relay.cheyuwu.workers.dev
# 看現在生效的
curl -s "$RELAY/config"
# 設（merge：只動列出的鍵；值 null＝刪掉那把鍵）
curl -s -X POST "$RELAY/admin/config" -H "Authorization: Bearer <WALL_TOKEN>" -H 'Content-Type: application/json' \
  -d '{"params":{"perfOffset":2,"vol":0.5}}'
# 全部清掉（整份取代成空）
curl -s -X POST "$RELAY/admin/config" -H "Authorization: Bearer <WALL_TOKEN>" -H 'Content-Type: application/json' -d '{"params":{},"replace":true}'
```

- 設完 relay 回 `wallsNotified: N`＝打到幾面開著的牆；每面牆比對後**只有真的有差才重整**（同值不動、網址自己帶的鍵不動）。重整後網址會多 `rc=…` 標記（記住哪幾把是遠端補的，下次開機才拿得掉）與 `rl=`（破快取），都是正常的。
- 牆重整那一下畫面會黑 1–2 秒，跟遠端重整一樣；表演中收到也照重整（需要改參數的時候通常是要修東西）。
- 分房測試：`?room=x` 的牆問的是 `/config?room=x`；正式牆是 `main`。
- `/online` 多一格 `config.keys`＝現在有哪些遠端參數在生效；`?remote=0` 開的牆不問也不聽。

## 鍵盤（主頁面／投影頁；大小寫都可）

| 鍵 | 動作 |
|---|---|
| **Enter** | 立刻觸發一場表演（含音樂）；表演中再按＝中止回常態 |
| **空白鍵** | 暫停／繼續全部（水、表演時間軸、音樂、魚、雨、排程全凍住；再按繼續） |
| **P** | 開／關屬性面板（debug UI、時間軸、訊號） |
| **O** | 換一顆完全不同的隨機水（參數 5–8 秒滑過去；持有 60 秒不被輪播蓋掉） |
| **I** | 隨機灑一堆水滴 |
| 畫面雙擊 | 同 P |

> 主頁面預設**沒有任何 UI／標準字**；`?debug=1` 一開就顯示面板。
> 滿版水（牆／輸出／主頁面）**邊緣一律不反射**（波到邊被吸掉，不會在上下邊之間彈成橫條）；`?reflect=1` 才會回到硬牆。個人水頁（`?m=`）不受影響。

## 表演一分鐘怎麼跑

整點前 5 秒轉黑 → 音樂起點＝整點 → 四幕（收集 0–15s／輸送 15–31s／混濁 31–46s／淨化 46–66.5s）→ 66.5s 起收黑 5 秒（71.5s 全黑，對齊音樂 65–67s 的自淡；9/17 哲宇改，原 61.5）→ 回常態。第四幕整幕比之前再拉近 50%（看水波細節）。**音樂由中央機播放**，牆端只對時（網路時間）；`musicOffsetSec` 可微調牆與音樂的對位（現場校）。

## 常態（沒有表演時）

**牆在常態下有聲音**（9/17 起）：七聲部合成器跟著水面走——波源幾顆、驅動多強、光斑多亮各對一個聲部，雨滴落下是水滴音；換一顆水，聲音也跟著滑過去。**開頁就自己出聲，不用點任何東西**（Chrome 要放行自動播放，用啟動工具或加上面那個旗標；沒放行就等第一次點畫面或按鍵）。表演一分鐘內自動靜音，結束後回來。聲音從播放端那台電腦的音訊輸出出來——**要接到現場音響才聽得到**，這一段要跟白輻射／13行 對。`sound=0` 關、`vol=` 調音量。

有觀眾送水 → 用 6 秒把眼前水面漸變成那位觀眾的水，再停 45／30／20 秒（派送時依待呈現人數 1–2／3–7／8 人以上決定；已開始者不縮短）；沒人 → 輪播過往訪客的水（75 秒換一顆、7 秒漸變）；歷史庫空 → 安靜的水。常態切換會保留原本波紋，波源位置、光色與力度一起移動。

2026-09-07 常態精修版：O 連按會從眼前狀態接續；表演中 O 不搶畫面。正式輸出維持 `out=1`，**不要額外加 `wall=1`**：後者是較低水面格點的長牆預覽，雖然輸出像素相同，細節密度不同。本機驗收方法見 [動態穩定性驗收](EXHIBITION-STABILITY.md)。

## 出狀況先看這裡

| 症狀 | 處置 |
|---|---|
| 畫面黑／凍住 | 重整（網址帶版本，一定拿最新） |
| 到點沒表演 | 看是不是 LED 時窗外（排程固定每半小時，網址不需任何參數） |
| 觀眾送水牆沒反應 | **先看 `/online`**（不用 token）：`terminals` 空＝牆沒開；有一筆但 `synced:false`＝牆開著卻沒領到控制憑證（2026-09-20 起帶鑰匙的牆會自己領——還是 false 就重整一次；再不行＝鑰匙不對或 Pages 沒設 `WALL_TOKEN`，找哲宇；手動帶 `&wallToken=` 開一次也行）。再確認手機與牆同房、relay 的 WALL_TOKEN 相同；手機顯示離線時不代表已上牆。重連後會恢復當前票。 |
| 想看時間軸／訊號 | 按 P |
| 牆沒聲音 | ①點一下畫面或按任一鍵（自動播放被 Chrome 擋下）②確認 Chrome 是用啟動工具或帶 `--autoplay-policy=no-user-gesture-required` 開的 ③播放端電腦的音訊輸出有接到音響 ④網址沒帶 `sound=0`；表演一分鐘內本來就靜音 |
| 現場沒人、牆要重整 | 遠端下指令即可，不必到場（見下）|
| 觀眾說送不出去（手機顯示稍後再試／429）| 同 IP 短時間送太多顆會被節流一分鐘，等一下就好；整群人一直被擋＝會場 wifi 被誤封，找哲宇用 `/admin/unban` 解（relay/README） |

聯絡：吳哲宇（墨雨）。

### 遠端重整牆面（不必到現場）

牆卡住或要換新版本時，從任何地方對 relay 下一個指令，牆會自己重新載入。**預設是立刻強制重整，
不等牆手上的事做完。** 需要 `WALL_TOKEN`（找哲宇）。

```sh
curl -s -X POST https://cymatics-relay.cheyuwu.workers.dev/admin/reload \
  -H "Authorization: Bearer <WALL_TOKEN>" \
  -H 'Content-Type: application/json' -d '{"reason":"現場卡住"}'
```

先看現在連著哪幾面牆、各跑哪一版：把上面的 `-X POST … -d …` 換成 `/admin/walls`（GET）。
完整選項（指定某一面牆、等訪客看完再換、限制）→ [relay/README.md](../relay/README.md#遠端重整牆面adminreload2026-09-16)。


## online 偵測與 GA（2026-09-19，哲宇：「一連到系統就知道有終端網頁正在開著」）

不用登入、不用 token，任何地方打一個網址就知道現場活著沒（studio.monolab.world 維運分頁與 Muse 看門狗讀的就是這一條）：

```sh
curl -s https://cymatics-relay.cheyuwu.workers.dev/online            # 正式房
curl -s 'https://cymatics-relay.cheyuwu.workers.dev/online?room=x'  # 分房測試
```

回 `terminals`（現在開著的牆：`label`＝哪台機器、`build`、`platform`／`screen`、`sinceReloadSec`＝上次重整多久前、`uptimeSec`、`fps`、`fresh`、`synced`＝有沒有 wallToken、`leader`）、
`visitors`（`survey`／`result`／`gallery`／`share`／`total`＝現在有多少人在問卷哪一頁）、`health.status`（🟢 `ok`＝牆連著且 30 s 內有心跳；🟡 `degraded`＝連著但沒心跳／沒 wallToken／不是 leader；🔴 `down`＝沒有牆）。

- **牆要告訴它自己是哪台機器**：網址加一次 `&device=<機器名>`（例：`&device=13hang-wall-1`），之後這個瀏覽器 profile 會記住、不用再帶；[啟動工具](PRIVATE-WALL-SETUP.md)預設帶這台電腦的 hostname（`--device` 可改）；也可以從遠端參數設 `device`（上一節）。沒帶的機器會自己報 **GPU 型號 · 螢幕**（例 `RTX 5090 · 12096x960@1`）當名字（`labelSource:"auto"`；瀏覽器拿不到電腦名稱，這已經是網頁能認到的極限），`/online` 另有 `gpu`／`platformVersion`／`arch`／`cores`／`memoryGB`／`screens`（多螢幕）幾欄可對。
- 牆每 15 s 送一次心跳（含最近 5 秒平均 fps）；問卷／分享頁每 30 s 報一次自己在哪一頁、關頁時報一次離開（75 s 沒消息就當離開）。不記 IP、不記名字、不記答案。
- 常見讀法：`terminals` 空＝牆沒開或整台機器沒網路；有一筆但 `synced:false`＝開著卻沒帶 wallToken（觀眾的水到不了牆）；`sinceReloadSec` 很大＝一直沒重整（正常）、突然歸零＝剛重整過（遠端 reload 或自癒）。
- 監看端要即時推播：`wss://cymatics-relay.cheyuwu.workers.dev/ws?role=monitor`，連上先收一筆同 `/online` 的 JSON、之後有變動或每 15 s 再收一筆；不算人、不入列。
- **定時縮圖**（2026-09-20，契約 v1.1）：展場機（`out=1`／`kiosk=1`／`wall=1`）開頁 20 s 後傳第一張、之後**每 5 分鐘**一張 960×277 的 JPEG（≤ 96 KB）到 relay，**只留最新一張、覆蓋、不存歷史**；牆斷線 15 分鐘後圖跟著清。
  看圖：`/online` 每台終端多 `snapshotAt`（幾點傳的）與 `snapshotUrl`，或直接開 `https://cymatics-relay.cheyuwu.workers.dev/snapshot?room=main&device=<deviceId>`（deviceId 從 `/online` 抄；studio.monolab.world 維運分頁的終端表每列會顯示這張）。
  網址參數：`&snapshot=0` 關、`&snapshot=1` 強制（本機 127.0.0.1／localhost 預設不送，加 1 才送）；主頁面／手機內嵌（`q=low`）本來就不送。
  效能：capture＋縮圖在主執行緒約 1–2 ms、JPEG 編碼在背景執行緒，實測 rAF 60 fps 不掉；全部走 `setTimeout`，不在畫面迴圈裡。console 只在第一張成功時印一行耗時。

**GA4**：property `properties/555080825`、資料串流 `G-KB4CY5JTK0`（兩個作品共用 property，各自的串流 id）。牆／問卷／分享頁都會送；牆的 session 在報表用使用者屬性 `kind = terminal` 濾掉（觀眾＝`visitor`），每個事件都帶 `role`（`wall`／`survey`／`share`／`water`）與 `device_label`。`?ga=0` 關；本機（127.0.0.1／localhost）預設不送、`?ga=1` 才送。事件（snake_case）：

- 問卷：`page_view`（每換一頁一筆，`page_location` 帶 `#p-q3` 這種）、`survey_start`、`survey_name`（只記長度）、`survey_step`{step, choice}、`survey_reveal`{seed}、`queue_join`{position, eta}、`wall_presenting`、`wall_touch`（每顆水第一次＋之後每 10 次一筆）、`share_image`、`share_video`{audio}、`share_link`、`mail_self`、`gallery_open`、`gallery_detail`{seed}、`sound_toggle`{on}、`mandala_sound_play`
- 分享頁 `/w`：`w_view`{seed}、`w_listen`、`share_link`／`share_video`／`share_image`／`mail_self`
- 牆：`wall_boot`{build, room, remote＝遠端補了哪些鍵}、`relay_connected`{leader}、`perform_start`{trigger: schedule／manual／relay}、`perform_end`{seconds}、`visitor_arrive`{seed, source: relay／local}、`fps_sample`{fps}（每 5 分鐘）、`page_error`{message}、`remote_reload`{when, hard}、`remote_config`{keys}（遠端參數有差、即將重整）

## 問卷首頁鏡射牆＋人人可推（2026-09-20，哲宇：「觀眾進到問卷的第一頁，能看到跟牆上一樣的水，還有能點擊影響牆上的水」）

- **首頁的水＝牆上現在的水**：牆每秒把「現在放哪顆」（五題答案＋seed）回報給 relay，relay 有變才記、公開 `GET /now`；問卷首頁在首頁那一頁時每 3 s 問一次，有變就用跟牆一樣的 6 秒 transition 滑過去（第一次 2.5 秒）。牆放安靜的水（歷史空）時首頁回預設那顆（多核・共振，就是原本首頁的水）。**表演一分鐘內首頁不跟**（牆在演四幕，手機演不了），停在最後一顆。
- **點首頁的水，牆上也有漣漪**：不用填問卷、不用票——首頁的每一下 tap／drag 走 `POST /nudge` 到牆（手機端 150 ms 一顆、relay 同 IP 3000／分＋全場 720／分、牆端 80 ms 一顆；超限只丟掉，不封）。牆在表演、暫停、沒 leader 時不收。**自己的水正在牆上的那位照舊走本人的路**（`/interact`，順位與時間不變）；本人在放時別人點首頁也會有漣漪（哲宇：人人可推）。
- 首頁狀態列（標題下第三行）：「這就是現在牆上的水，點一下，牆上也會有漣漪」／「展牆正在表演中，結束後再一起玩」／「展牆暫時離線，先在手機上玩水」（離線＝relay 沒有 leader 牆；離線時點水不送）。
- 看牆上現在是哪顆：`curl -s https://cymatics-relay.cheyuwu.workers.dev/now`（`now.m`／`now.seed`／`now.kind`＝visitor 真觀眾的票／hold O 鍵／idle 閒置輪播／quiet 安靜的水；`wallOnline`；`performing`）。
- 沒有新的網址參數；牆網址不用動。舊版牆（不回報 now）接新 relay＝`/now` 停在最後一顆，首頁不會跟。

## 手機排隊與連動（新協定，需整套更新）

手機隨時能玩自己的水；等到本人在展牆顯影完成，才開放手機手勢影響牆面。手機會顯示即時順位與狀態。表演、播放端暫停或斷線期間關閉連牆，保留未用完的時間。每房最多12位等待加1位正在呈現；滿額時作品仍保存，手機提供再次申請，沒有排入就不顯示等待承諾。

建議使用[私密展牆啟動工具](PRIVATE-WALL-SETUP.md)，從現場電腦的私密環境檔注入控制憑證，避免放入網址。

播放端新增私有控制設定 `wallToken`，與既有開頁鑰匙 `key` 用途不同。由管理者將同一值設為 relay 的 `WALL_TOKEN` 與播放端的 `wallToken`；不要加到觀眾 QR、分享連結或本文。播放端讀取後會移除網址中的該參數，保存在此分頁的 sessionStorage。分頁關閉、換瀏覽器或清除儲存後須重新設定。沒有設定就只能呈現本機水，不能消費觀眾隊伍。

更新順序：先於本機完成整合驗收；安排停止收件的維護時間，設定後端憑證並更新 relay，再更新牆與問卷，開啟播放端並確認單一主牆。用兩支手機測試不同順位，確認等候者只玩本機、本人確實影響牆；再測表演暫停與恢復。這些完成後才重新開放 QR。正式部署後仍須在展機完成首次憑證設定與現場排演。

兩個瀏覽器同房時只有一個主牆，另一個作備援，不自行消費隊伍。這不等於多投影逐幀同步；既有中央輸出與投影分配仍照現場配置。

詳細契約與驗收：[手機互動與排隊](INTERACTION-EXPERIENCE.md)。任何回退都要同步回退牆、問卷與 relay；新票資料位於獨立名稱空間，勿刪除票或既有歷史。
