線上課程背景播放 JavaScript:套用、還原與計時驗證
讓教材正常播放後,在課程主頁的 Console 執行下方完整 JavaScript,即可暫時停用頁面隱藏時的計時處理與定期回應確認。這段程式保留實際的物件及函式名稱,供之後直接複製使用;僅適用具備相同 CourseReader 實作的一般網頁教材,不是所有學習平台通用的腳本。
這份筆記整理一次 2026-10-19 的瀏覽器觀察與暫時修改。公司、網域、課程、帳號及紀錄識別碼已移除;套用與還原程式保留原名稱,其餘 API 動作及 JSON 則使用概念範例。
直接複製使用
執行前先確認教材正在正常播放,而且沒有等待回應的確認視窗。Console 的執行環境要選課程主頁 Home.html 的最上層 frame,不能選內嵌影片或閱讀器 iframe。
程式會檢查 readerStatus === 3 與 _ContentType === "0" 。不符合時會停止;若平台改版後找不到物件或函式,也要重新確認實作,不能只刪掉檢查繼續執行。
看到「已套用暫時修改;未改寫累積時數。」表示腳本已執行到最後。重複執行會顯示「已套用,無須重複執行。」,避免覆蓋用來還原的原始函式。
這段程式停用確認機制,沒有自動按確認,也沒有修改累積秒數或直接提交課程完成狀態。頁面不被主動暫停,仍不代表瀏覽器一定允許長時間背景執行,或伺服器一定認列全部時間。
還原與下次使用
在同一個主頁 Console 執行:
還原會恢復原本的可見性處理函式與回應確認設定,再依當前頁面狀態同步計時。若原本啟用回應確認,先前已清除的倒數會重新開始,並非恢復舊倒數的剩餘秒數。
重新整理也會清除暫時修改,但可能中斷正在進行的閱讀,應先透過原介面正常回存。準備換教材時,先還原、正常離開,再於下一份符合條件的教材播放後重新套用;同頁換課時,舊的 patch 標記不一定會自動清除。
判斷是否成功記錄時數,仍要比對閱讀計時、回存請求及離開教材後重新查詢的紀錄。畫面上的時間持續增加,或 API 回傳 HTTP 200,都不足以證明課程已通過。
先分清楚三種時間與進度
資訊 | 代表意義 | 不能直接推論的結果 |
|---|---|---|
影片播放位置 | 播放器目前播到第幾秒 | 平台認列的閱讀秒數 |
閱讀視窗計時 | 前端依閱讀狀態計算的時間 | 已成功回存的時間 |
重新查詢的閱讀紀錄 | 伺服器回傳的累積結果 | 所有活動均已通過 |
課程完成狀態 | 時數、測驗、問卷等條件的綜合結果 | 單次回存請求的成功與否 |
觀察案例中,教材被歸類為一般網頁,內容嵌入外部影片。回存的播放位置欄位為空,沒有看到依外部播放器進度回報的資料。因此,不能將播放位置與平台計時視為同一件事;這也不表示所有影音教材都使用相同實作。
從 Network 建立證據
先被動觀察正常閱讀流程,再考慮變更。Chrome DevTools 的 Network 可保留跨頁請求,並檢視 Payload、Response 與 Initiator;Initiator 能協助追到發出請求的程式位置。 Chrome DevTools Network reference
記錄課程列表的既有時數、閱讀視窗計時與當前時間。
保留正常播放狀態,捕捉至少一次週期回存。
比對請求方法、端點、欄位名稱、狀態碼與業務結果。
在載入的 JavaScript 中追查計時啟停、週期回存及離開結算。
把「實際請求」、「程式碼分支」與「推論」分開記錄。
Resource Timing 可以補充頁面先前載入哪些 URL、何時開始請求,但不能取代 Request Body 與 Response Body。若開始觀察前就已開啟教材,起始回應可能不在新啟用的 Network 記錄裡,不應為了補抓而直接重整正在閱讀的頁面。
公開筆記只保留必要欄位與去識別化範例。HAR、Copy as cURL 或完整表單內容可能包含登入憑證、員工資訊與組織資料,不能把原始輸出直接放進文章。
API 的角色與回存內容
同一個系統通常有數種不同用途的請求。以下名稱僅用來表達此次觀察到的角色:
示意動作 | 用途 | 本次觀察程度 |
|---|---|---|
| 記錄最近閱讀的教材 | 程式碼與資源時序 |
| 建立或取得閱讀紀錄,載入既有時間 | 程式碼與資源時序;未取得起始回應 |
| 週期回存、暫停/恢復、離開結算 | 實際 POST 與回應,以及程式碼 |
| 維持登入或線上狀態 | 程式碼與資源時序 |
登入保活不等於閱讀時數回存。更新動作名稱即使帶有 finish,也可能只是在結算一段閱讀工作階段,並非把整堂課標記完成。
實際週期請求可抽象為下列資料;欄位名稱與結構已改寫,原請求使用表單編碼:
值得注意的是,觀察到的回存沒有直接包含前端累積秒數。這支持「伺服器可能結合工作階段、請求時間與暫停狀態計算時數」的推論,但後端原始碼不可見,無法確認精確算法、時間上限或防重播規則。
正常回存收到 HTTP 200;還原系統自訂的回應編碼後,業務結果表示成功且未進入閒置狀態。該回應沒有累積時數或課程通過旗標,所以仍須另外查詢紀錄。
前端計時與週期回存
案例中的顯示計時器每 100 毫秒執行一次,以啟動時的累積值加上當下時間差,更新閱讀視窗。回存則由同一個迴圈累計 3,000 次 callback 觸發,在前景且未受節流時約為 5 分鐘。
這裡有兩個不同的計算基礎:
顯示時間使用日期時間差。
回存頻率使用 callback 次數。
背景執行若受到計時器節流,兩者可能出現差異:畫面下一次更新時補上經過時間,但回存要等 callback 次數達標。瀏覽器確實可能限制背景計時器,具體行為也受版本、音訊播放與其他條件影響,不能把 5 分鐘視為嚴格保證。 MDN Page Visibility API
暫停、恢復及正常離開各有狀態處理;正常離開會使用結算旗標。程式也有離開頁面時使用 fetch 搭配 keepalive 的分支,但這只能說明它嘗試在離開時送出,不能取代實際送達與寫入驗證。
頁面可見性不是視線偵測
document.visibilityState 與 visibilitychange 描述頁面是否可見,不能判斷使用者眼睛看向哪裡。切換分頁、最小化與切換應用程式也不能一概視為相同事件,應讀取實際狀態; blur/ focus 與可見性是不同訊號。 MDN Page Visibility API
此次一般網頁教材啟用了可見性檢查。程式分支在 hidden 時停止閱讀及回應確認計時,並回存;回到 visible 後再啟動。這些是應用程式的行為,不是 Page Visibility API 自動替平台執行的功能。
以下診斷片段只讀取狀態,不修改偵測或課程資料:
回應確認是什麼
另一套機制是定期要求使用者回應。案例當時的設定為每 20 分鐘出現一次確認視窗,限 30 秒回應;這些數值是當次執行參數,不是所有平台的固定規則。
階段 | 程式處理 |
|---|---|
到達確認時間 | 停止閱讀計時、回存並顯示確認視窗 |
使用者按確認 | 恢復計時,重新啟動下一輪確認計時 |
超過回應期限 | 顯示停止記錄提示,關閉閱讀視窗 |
已檢視的確認按鈕回呼主要是關閉視窗與恢復計時,沒有看到獨立的「本人已確認」API。不過,狀態恢復仍可能經由共用回存函式送出資料,因此不能解讀成「按確認完全不會影響後端」。
暫時修改與自動確認的差異
本次曾在教材正常閱讀、沒有等待確認的狀態下,進行可還原的前端暫時修改。流程是保存原函式與設定,先停止既有回應計時器,再停用後續確認,並以空函式取代頁面可見性處理。最後驗證函式已替換、確認計時器已停止,以及閱讀計時仍在增加。
先停止計時器的順序很重要:若停止函式本身會檢查啟用旗標,先關閉旗標可能使它提早返回,留下仍在執行的舊計時器。
做法 | 對流程的影響 | 能否證明伺服器認列 |
|---|---|---|
停用前端確認 | 不再依原週期彈出視窗 | 不能;僅確認本機狀態已修改 |
自動按下確認 | 理論上會經過原視窗及恢復回呼 | 不能;本次未實作或驗證 |
正常手動確認後重新查詢 | 保留原流程,再檢查持久化結果 | 可驗證該段紀錄,仍需另看整堂課條件 |
自動按確認比較接近原本前端流程,不等於比較容易被後端接受。尚未觀察到後端對兩種方式的差別,也沒有證據支持「有按確認就一定認列」。
此次修改沒有改寫累積秒數,也沒有直接提交課程完成狀態。只驗證到前端閱讀狀態維持、短時間內顯示計時繼續增加;沒有完成長時間背景播放或後端認列驗證。
還原時應恢復原處理函式與旗標,再依當前可見狀態同步計時。重新整理也會重新載入原程式,但可能中斷當前閱讀;先完成正常回存再重整。這類頁面物件修改不是跨重整、跨教材或跨登入的持久設定,不能假設換課後仍有相同行為。
如何驗證伺服器實際記錄
先以正常手動流程建立基準,並將以下步驟用於有權測試的環境。需要比較背景行為時,每次只改變一個條件,避免同時切換可見性、播放器狀態與回應機制。
記錄重新查詢得到的起始閱讀時間與課程狀態。
記錄實際經過時間,以及暫停、確認、恢復與回存的時間點。
檢查週期回存是否收到預期的業務成功結果。
透過原介面正常回傳並離開教材。
重新查詢課程列表,計算伺服器時間增量。
分別檢查教材門檻、其他教材、測驗與問卷,避免只看總進度。
可用下列公式整理觀察結果:
若增量與前端顯示不一致,先排除列表未更新、回存失敗、暫停期間、時間取整及後端結算延遲,再判斷是否有額外規則。無論停用偵測或自動確認,都不能僅憑畫面計時斷言有效。
證據範圍與未完成事項
項目 | 本次結果 |
|---|---|
正常週期回存 | 捕捉到實際請求與業務成功回應 |
前端計時與偵測邏輯 | 已讀取當次載入的程式及設定 |
暫時修改 | 已套用,短時間前端狀態與計時驗證通過 |
自動確認 | 僅討論可行性,未實作、未執行 |
修改後的伺服器時數 | 尚未透過離開後重新查詢核對 |
直接呼叫 API 完成課程 | 未測試,不能宣稱可行 |
後端計時與防重播規則 | 無法由前端觀察完整確認 |