返回學思錄
2026-04-09

Kaze 產品日誌 (三):跨越邊界 —— 瀏覽器擴充功能與 App 的資訊傳遞機制與 Rule Engine 實踐

Kaze 產品日誌 (三):跨越邊界 —— 瀏覽器擴充功能與 App 的資訊傳遞機制與 Rule Engine 實踐

在討論完 HLS/DASH 的底層挑戰後,我們必須面對一個更現實的問題:如果連下載連結都抓不到,再強大的下載引擎也無用武之地。

從 Native App 的設計角度來看,要在封閉的作業系統中感知並攔截網頁內容,其實有兩條截然不同的路徑。

方案一:內建 WebView(App 內的專屬瀏覽器)

這是許多傳統下載工具採用的方式。在 App 內嵌入一個瀏覽器組件,讓用戶在 App 內部進行操作。雖然這能擁有最大的流量控制權,但它其實沒那麼好用:

  • 維護成本: 你必須為用戶開發出一整套瀏覽器功能(標籤頁、密碼管理、自動填充等)。
  • 體驗與 Session 斷層: 這是最致命的一點。用戶在自己習慣的瀏覽器(如 Safari 或 Chrome)中已經登入了網站、儲存了紀錄時,如果要求他在 App 內建的 WebView 重新登入、重新搜尋影片,這會造成極大的使用摩擦。

方案二:Browser Extension(當用戶瀏覽器的「哨兵」)

這是 Kaze 最終選擇的路。我們不嘗試自己做一個瀏覽器,而是派駐一個「哨兵」進入用戶最熟悉的瀏覽器環境。

這種方式讓下載引擎不需要「模擬」用戶的狀態(如 Session, Headers, LocalStorage 等),因為 Extension 直接就在那個狀態之中。 當用戶在網頁上按下播放時,Extension 能以第一人稱視視角攔截到完整的請求上下文。

這種架構讓 Kaze 維持了工具的純粹 —— 用戶繼續在習慣的地方觀看,Kaze 則在背後安靜地處理繁瑣的抓取工作。

資訊傳遞:從 Native Messaging 到 WebSocket 的架構演進

獲取到連結後,下一個難題是如何將這些高度時效性的媒體流資訊,安全且精準地從瀏覽器沙盒「傳遞」給 Kaze 的應用主體。

在 Kaze 的早期版本中,我們依循官方標準採用了 Native Messaging。這套機制透過標準輸入輸出(Stdio)與 App 溝通,但它在實際工程中遇到了不少的麻煩:

  • 連接的不穩定性: Native Messaging 往往需要一個宿主進程作為橋樑,當瀏覽器分頁切換或 Extension 更新時,連接極易發生「隱性斷開」,導致攔截失效。對用戶而言,這常表現為一種莫名其妙的「斷線」狀態。
  • 雙向通訊的侷限: 它的設計初衷是 Request-Response 模型,難以達成低延遲、高頻率的非同步主動推送(Server-side Push)。

在重構版中,我們決定改採 WebSocket 建立持久化的通訊橋樑。這帶來了幾個核心的工程優勢:

  1. 非同步主動推送(Async Push): Extension 一旦攔截到 HLS/DASH 索引,會透過 WebSocket 管道將清單與封裝好的 Headers 推送至 App。這種「即時感知」免去了任何輪詢(Polling)的開銷。
  2. 狀態持久化與 Session 共享: WebSocket 連接與特定分頁無關,這讓我們能在 App 端維護一個完整的用戶上下文。App 可以主動向 Extension 發起 Query,獲取當前 Host 資訊或執行特定的 Rule 動作,這對我們後來實現的「Album Mode」自動化邏輯至關重要。
  3. 跨瀏覽器的一致性: 透過 Local Loopback 的通訊方式,我們避開了各家瀏覽器對 Native Messaging 註冊方式的繁瑣依賴,讓跨瀏覽器的攔截邏輯保持高度一致。

Rule Engine 的攻防戰:識破偽裝的 HLS 索引

在網路封包的世界裡,攔截到的請求五花門。我們不可能把每一個 .ts.m4s 片段都丟給下載器。我們需要一套精準的 Rule Engine(規則引擎) 來判斷「什麼該抓」。

1. 識破混淆的內容

在早期用戶的反饋中,有些影音平台會玩一些「躲貓貓」的技術,例如,明明內容是一個 HLS 的 .m3u8 清單,但其副檔名卻被故意改成 .jpg.png。對播放器來說這無所謂,只要 Content-Type 正確即可,但這會讓傳統的過濾器直接忽略它。Kaze 的 Rule Engine 必須具備特徵識別能力(Fingerprinting),即便它是個圖片路徑,只要符合 HLS 的語法結構,我們就能識破它。

2. 動態規則發布(Remote Rules)

這是 Kaze 最引以為傲的維護體系。影音平台的技術更新速度極快,如果規則死寫在 App 裡,用戶必須不斷更新版本才能跟上。我們將 Rule Engine 抽離成獨立的 JSON 設定檔。當某個網站的攔截邏輯改變時,我們能在後台即時發布新規則,用戶端的 Kaze 會在數秒內自動載入新規則。在開發的高峰期,我們甚至曾經達成過「一天兩次」規則更新的頻率,以應對網站的動態攻防。

通用介面(General Interface)的抽象化

為了讓 Rule Engine 運作得更順暢,我們在 Kaze 的 Rust 底層設計了一套 General Interface。這套介面將「攔截、解析、處理、下載」定義為一套標準化的流程:

  • Interceptor:負責根據網站規則(Regex 或 Path)捕獲請求。
  • Passer:負責解析捕獲到的內容,並處理 Header 模擬。
  • Processor:負責處理特定網站的解壓縮、加密或解密(Plugin 概念)。

這種模組化的設計,讓我們在支援新網站時,往往只需要在 rules.json 裡增加幾行規則,而不必改動任何一行核心程式碼。

匿名監測與診斷:快速反饋的閉環

作為一個 Side Project 團隊,我們沒有大量的 QA 人員來遍歷所有網站。Kaze 的 Rule Engine 整合了一套匿名統計回報系統。當某個 Rule 在多個用戶端頻繁出現 Parsing Error 時,我們的後台會自動報警。

這讓我們能先於用戶請求前,就主動發現某個影音網站更換了加密方式,並及時透過動態發布機制修復規則。

不過 Kaze 2開始,我們讓Rule本身的編輯與存儲的主控權回到用戶手上,我們就不太需要有上報機制,剛好也可以趁此調整隱私權政策,我們基本上只剩上報跟隱私無關的程式問題了。

結語

瀏覽器擴充功能與應用端的緊密結合,加上靈活的 Rule Engine,構成了 Kaze 的「眼睛」。沒有這雙眼睛,再強大的下載引擎也只是在黑暗中摸索。

下一篇,我們將聊聊這一切重生的推手 —— 那場「2 小時 AI 重構」,以及我們如何運用 AI 將舊時代的遺產轉換為現代的效能野獸。


探索 Kaze 2: 如果你對我們正在開發的下載技術感興趣,歡迎前往 Kaze 產品頁面 了解更多細節並支持我們的 Side Project。

#Kaze#Browser Extension#WebSocket#Rule Engine#Architecture