# 留言統計與自動剪輯改進
Userscript 轉接格式見 [/chat 入口與參數文件](CHAT_API.md);平台與接收管道的分類見 [來源說明](USERSCRIPT_SOURCES.md)。未知來源仍參與熱度,明確標記 `isTest: true` 的測試資料只顯示及記錄,不參與熱度。
## 資料與 keyword 頁面
- 每則留言只統計一次,翻譯不另加次數;ID 去重依平台區分。
- 統計保留內容、次數、首次/最後已知時間、平台及每種留言最近 5 筆紀錄。
- 最近紀錄有使用者、訊息 ID、平台時間、接收時間與時間來源。
- TikTok/YouTube 使用可取得的原始時間;Twitch 的目前聊天 SDK 事件未提供
發送時間,使用處理回呼入口的接收時間,避免把查詢頭像的耗時算入事件時間。
- 舊檔案可直接載入,保留次數;未保存的歷史時間與留言明細無法還原。
- keyword 顯示 Top 10、可搜尋/排序/分頁的全部留言,以及最多 200 筆最近紀錄。
這是完整留言統計,沒有把句子拆成詞。
- 主程序與子程序沿用同一累計快照;啟動子程序前保存基準,合併快照不重複相加。
## 剪輯判斷
- 所有平台聊天均可觸發,Twitch 僅是剪輯畫面入口。各平台用自己的聊天/觀眾基準計算分數,取通過最低留言量與發言人數的平台最高分。安靜平台不稀釋热度;不把不同平台的觀眾當作同一人去重。
- 建議設定:30 秒窗口、每 5 秒評估、持續約 10 秒;每平台最少 6 筆、3 位不同發言人;分散在多平台且各自未達此門檻時不觸發。
- 一般每人每窗口最多計入 3 筆;單人模式為 5 筆。多人相同留言可以計入,不再全域按文字去重。
- 基準排除當前窗口;先暖機 3 分鐘,資料過期或 Socket 斷線會重新暖機。
- 除加權分數外,聊天速率至少需要達基準下限的 1.5 倍;觀眾倍率最多採計 2 倍。
- 平台卡片上的「不足」是三個**各自獨立**的門檻(都看 30 秒窗口),卡片直接顯示「目前值/門檻」:
- **留言 N/minMessages**:窗口內有效留言數要 ≥ `minMessages`(預設 6)。有效留言已套用「一般每人 3 筆、單人模式 5 筆」。
- **人數 N/minUsers**:窗口內不同發言人數要 ≥ `minUsers`(預設 3)。
- **聊天倍率 N/1.5**:`聊天倍率 = 目前速率 ÷ max(基準速率, floorMsgPerMin)`,要 ≥ `minMessageRatio`(預設 1.5)。
目前速率 = 窗口留言數 ÷ 0.5 分鐘(`rateWindowMin`);基準速率 = 近 30 分鐘樣本(**排除當前窗口**)的中位數(`baselineWindowMin`)。
三者都過、且加權分數 ≥ `scoreThreshold`(預設 1.8)才會觸發。
- **自適應絕對門檻(預設開啟)**:`minMessages` 會依近期每分鐘訊息中位數下調(最低 4,上限為設定的 6);`minUsers` 會依近期單一 30 秒窗口的最大不同發言人數下調(最低 2,上限為設定的 3)。聊天倍率與分數門檻不變,仍要求相對爆量。`AUTO_CLIP_ADAPTIVE_THRESHOLDS=0` 可回到固定 6/3;`AUTO_CLIP_MIN_MESSAGES`、`AUTO_CLIP_MIN_USERS`、`AUTO_CLIP_MIN_MESSAGE_RATIO` 可調整上限。
- **單人活躍發言者模式(預設 `auto`)**:追蹤近 15 分鐘各平台的不同發言者;剛好 1 位時改用單人門檻:至少 5 則不同訊息、1 位發言人、聊天倍率 3.0、分數 2.5,每人最多 5 則;同一人重複相同文字不累計。第二位發言者出現就回到一般門檻。`auto` 另外限制全平台觀眾 ≤ `AUTO_CLIP_SOLO_MAX_VIEWERS`(預設 20);`AUTO_CLIP_SOLO=on` 可忽略觀眾上限,`off` 停用。`AUTO_CLIP_SOLO_*` 可調整視窗、訊息數、倍率、分數與每人上限。
- 觸發判定只看「達標平台」自己的有效門檻;跨平台總留言/總人數不會稀釋或替代單一平台的門檻。
- 暫存 ID 最多 10,000 筆/30 分鐘;舊聊天不納入,ID 及發言人限制依平台區分。
- `AUTO_CLIP_MODE=shadow` 是預設值:只記錄,不向 Twitch 發送剪輯請求。
Config 可改成 `live`,儲存後重新啟動子程序生效。`AUTO_CLIP_ENABLED=1` 仍為必要條件。
- 影子觸發、正式觸發、建立中、成功及失敗分開統計。成功需查到可用剪輯。
請求逾時或未確認可用時不立即重送,保留冷卻以免重複建立。
- 自動剪輯不再要求延後建立;手動剪輯維持原設定。
## 即時與歷史分開
- **即時**:子程序透過 `AUTOCLIP_STATS` 每 5 秒推送最近快照;`/autoclip/data` 只服務即時頁。記憶體保留 2000 筆(約 2.8 小時)是刻意的 rolling window,不代表完整歷史。
- **歷史**:Server 將每個場次寫入 `data/autoclip.sqlite`(`sessions`/`samples`,以 `session + t` 去重),不再只在子程序結束時覆寫 JSON。`/autoclip/sessions` 列出場次,`/autoclip/history?session=…` 查詢並在過長時降採樣。
- 頁面的「即時/歷史」分頁:即時維持 5 秒更新與 runtime/stale banner;歷史可選場次並查看完整 session,不受即時 rolling window 限制。
- 平台卡片在最後一列是 reset(`platforms: []`)時,退回最近有效平台快照並標示時間;選取歷史事件時仍使用該事件保存的平台明細。
- 模式徽章會顯示「影子模式(只記錄,不剪輯)」或「正式剪輯模式」,避免誤以為影子模式應該產生 clip。子程序停止超過 30 秒未更新時顯示 stale banner。
- 設定頁的 `AUTO_CLIP_MODE` 只寫入 `.env`/`process.env`;子程序在啟動時讀取。若目前設定與上次執行不同,徽章顯示「(待套用)」,banner 會寫出目前執行模式與設定模式;停止後再啟動直播子程序才會生效。
- 舊 `autoclip_stats.json` 首次啟動會匯入為 legacy session;歷史預設保留 30 天,過期資料由啟動時的 prune 清除。
## 圖表與時間核對
分數圖將連續完全相同的分數合併為水平區段,保留起訖端點、分數變化與每個觸發事件。
滑過線段會顯示該分數的起訖時間、持續長度及原始評估筆數,不再逐筆顯示重複圓點。
總分、平台分數與門檻使用同樣的繪圖壓縮;原始歷史與留言證據不刪除。
時間軸依實際時間比例繪製;單筆或孤立樣本保留可見點,無觸發事件也照常畫線。
缺值會斷線;至少有 3 個有效時間間隔時,以間隔中位數估計取樣頻率,
間隔超過「20 秒與正常間隔四倍的較大值」才視為疑似中斷,避免將舊版較疏的樣本切碎。
樣本不足時不單憑時間間隔判定中斷;連線表示已知樣本趨勢,不保證期間沒有漏收。
頁面預設顯示即時平台卡片,取每次評估的 `platforms`,不必等到觸發剪輯。
六個平台位置固定;卡片顯示分數、門檻、有效留言/人數、管道、平台資格與採計分數。
歷史場次未選取觸發點時改顯示本場最高(最高分樣本、達標窗口數、管道 union),不再只取最後一個樣本;切換時間範圍時改顯示所選範圍最高。
點卡片可突出對應平台曲線,未知來源使用相同方式顯示。缺少樣本顯示破折號,不補成零。
選取觸發點或歷史事件時,平台卡片切換成該次快照;舊紀錄未保存平台資料時明確提示,
不會用即時資料補齊。即時分頁按「返回即時」恢復更新;歷史分頁用場次選單切換。
即時總覽只在即時分頁顯示;子程序停止或超過 30 秒未更新時顯示 stale banner。
評估每 5 秒執行一次;狀態列(子程序的 `[AutoClip] …` 與伺服器端的 `📈 [AutoClip] 統計更新`)改為事件驅動,
只在狀態改變、觸發或每 60 秒心跳時輸出,避免每次評估都洗版。統計資料仍每 5 秒推播,供頁面即時更新。
觸發分數、觀眾及留言趨勢以分頁切換。大螢幕將事件詳情放在圖表右側,手機改為下方;
計算說明和歷史結果預設收合。選取有窗口資料的事件時,分數圖標示該統計窗口。
圖表預設顯示最後樣本往前 30 分鐘,可切換 10 分鐘、1 小時或全部;三種趨勢共用時間範圍。
歷史事件選單保留該場次紀錄,選取範圍外事件會自動定位至事件附近;「返回即時」回到即時分頁。
時間範圍只影響圖表;歷史分頁的「全部」是所選 SQLite 場次,不是即時 2000 筆窗口。
觸發點旁顯示計入的留言數、發言人數及一則短文;平常只標範圍內最新事件,選取後改標選中事件。
畫面上接近的事件以「N 次觸發」合併標記,點擊後可逐筆查看並放大群組範圍,放大後重新計算分組。
選中事件所在群組會展開標記,保持所選點與摘要可辨識。原始觸發事件不合併或刪除。
標籤先嘗試點的右側,再嘗試左側;碰撞時小幅上下錯開,以短線連回觸發點。
無法避開其他標籤或觸發點時省略摘要,仍可用點擊/下拉選單查看完整事件。
舊紀錄在圖上簡寫「舊紀錄 · 無明細」,數量未知的完整說明保留在提示與詳情。
展開區顯示該點的統計窗口、分數、門檻與計入留言。觸發時固定保存快照,
每個事件最多保存 200 則、每則文字最多 1,000 字元;截斷會標示在筆數說明。
這份清單是「被計入熱度的留言」,不是全部收到的原始聊天。
舊圖表紀錄未保存訊息,會顯示無法補回。
另保存熱度開始、觀測峰值、觸發、請求與完成時間。如果 Twitch 提供剪輯的
VOD 位移,且能確認 VOD 屬於同一直播,才計算片段是否涵蓋觀測峰值;
沒有足夠資料就標示尚未核對,不能據此保證已剪到遊戲/畫面的精彩瞬間。
觀眾反應與直播畫面仍有延遲,需要先用影子模式對照實際直播校準。
## 本次本機設定
將原本的 5 分鐘窗口/1.5 分鐘持續確認,調成 0.5/0.167 分鐘;
觀眾與聊天權重調成 0.2/0.8,訊息基準下限調為每分鐘 2 筆,模式設為 shadow。
尚未啟動正式剪輯,沒有發送 Twitch 測試請求。
## 驗證
```sh
node --test Test/message_stats.test.mjs Test/autoclip_v2.test.mjs Test/tiktok_chat_guard.test.mjs Test/socket_transport.test.mjs
node --check TikTok.js
node --check Server.js
```
`node Test/keyword_preview.mjs` 提供本機 18765 埠的合成資料 UI,供檢查
keyword、autoclip 與 config;不讀取真實留言、不啟動直播、不保存設定。
## 跨平台時間校準
可在 .env 設定 AUTO_CLIP_PLATFORM_DELAY_MS={"TikTok":5000,"Youtube":10000},單位毫秒,正值代表該平台反應相對 Twitch 畫面落後,從事件時間扣除。預設全部為 0,不猜測延遲;需要用實際直播核對。校準後超出窗口的留言不納入即時熱度。圖表明細保存校準前時間及各平台分數/採計貢獻。
觀眾人數只使用可取得且未過期的平台資料;例如沒有 Kick 人數時,Kick 聊天仍可獨立觸發。Twitch 剪輯入口離線或資料過期時維持暫停、重新暖機。