Traverba:一款以 Flutter 打造、同時執行 3 個 ASR 模型、本地 LLM 與相機 OCR 的翻譯 App

我打造了 Traverba——一款完全在手機本地端執行、不依賴任何雲端 API 的即時翻譯器。功能涵蓋語音辨識、108 種語言翻譯、92 種文字的相機 OCR、螢幕翻譯疊加層、音訊檔案轉錄,以及透過藍牙支援最多 7 人的離線群組聊天。

整個應用程式以 Flutter 搭配原生平台程式碼共同打造,由原生層負責繁重的 AI 運算。本文將介紹 Traverba 的功能、為何選擇 Flutter,以及在 iOS 和 Android 上線時遭遇的最大挑戰。

應用程式的功能

Traverba 共有五大核心功能,全部在離線狀態下運行:

即時語音翻譯 — 說一種語言,聽到並看到另一種語言的翻譯。提供三種模式:App 內翻譯、浮動系統音訊擷取(可翻譯 Zoom/Teams/Meet 的音訊),以及浮動麥克風模式。支援目標語言自動朗讀。

相機翻譯 — 將鏡頭對準菜單、招牌、表格或文件,即可即時翻譯。搭載兩種 OCR 引擎:Basic 模式(ML Kit)適合快速辨識,Professional 模式(PaddleOCR)適合處理中日韓、阿拉伯文、西里爾字母、梵文等複雜文字。支援 92 種語言,並直接在圖像上將外文替換為譯文。

螢幕翻譯 — 浮動疊加層,可翻譯任意 App 中的文字。看動漫、讀韓文新聞、玩日文遊戲,或收到微信訊息時,點擊疊加層按鈕,文字立即原地翻譯,無需切換 App。

檔案轉錄 — 匯入音訊或影片檔案(mp3、m4a、wav、mp4),即可取得帶時間戳記的雙語對照逐字稿。

離線群組聊天 — 最多 7 人透過藍牙網格連線,每人說自己的語言,所有訊息即時翻譯成每位參與者的語言。不需網路,不需伺服器,每支手機獨立完成語音辨識與翻譯。

以上功能全部在手機處理器本地端執行,無需 API 金鑰,不產生伺服器費用,資料不離開裝置。

為何選擇 Flutter

開發初期,我評估了 Flutter、React Native,以及完全原生(分別維護 Swift 和 Kotlin 程式碼庫)三個方案。

單一程式碼庫的跨平台能力是不可妥協的條件。 以一人之力維護兩套原生程式碼庫來打造這麼複雜的 App,根本不切實際。Dart UI 層——設定頁面、聊天氣泡、逐字稿視圖、引導教學、下載彈窗、語言選擇器——大約佔總程式碼的 60%。若要寫兩遍,開發時程直接翻倍。

Flutter 的平台通道讓原生整合變得可行。 AI 密集型的工作(ASR 推論、LLM 翻譯、OCR、藍牙網格、浮動疊加層)都透過平台通道和方法通道在原生 Swift/Kotlin 中執行。Flutter 不需要承擔 AI 執行環境的角色,它是連接各原生引擎的 UI 與編排層。

效能已足夠應付需求。 對於這類 App,Flutter 的效能顧慮在於額外開銷——對話中需要串接 ASR → 翻譯 → TTS,每毫秒都很關鍵。實際使用中,繁重運算由原生程式碼負責,Flutter 層帶來的延遲可忽略不計。Dart 層處理狀態管理、路由和 UI 更新,這些都是它擅長的工作。

Hot Reload 大幅加速了 UI 迭代。 App 共有五個功能介面(語音、相機、螢幕、檔案、群組聊天),每個介面都有多種狀態和模式,無需重新編譯即可迭代 UI,是顯著的生產力倍增器。

架構:Flutter 作為編排層

整個應用程式遵循清晰的職責分工:

Flutter/Dart 層負責:

  • 所有 UI(Material 3,手機與平板的自適應佈局)
  • 狀態管理與功能路由
  • 語言/地區選擇與使用者偏好
  • 可選模型的下載管理
  • 金幣經濟與訂閱權限控管
  • 引導教學流程

原生層負責(透過平台通道):

  • ASR 推論(sherpa-onnx / whisper.cpp)
  • LLM 翻譯(Gemma 本地執行)
  • 傳統機器翻譯(ONNX NMT 模型)
  • 相機 OCR(ML Kit + PaddleOCR)
  • 文字轉語音
  • 群組聊天藍牙網格
  • 浮動疊加層(螢幕翻譯 + 系統音訊擷取)
  • 記憶體預算管理與模型載入/卸除

這兩層之間以一組具有明確契約的平台通道作為橋梁。Dart 端發送指令(「為粵語啟動 ASR」、「將此文字從日文翻譯成英文」、「擷取螢幕並執行 OCR」),原生端非同步回傳結果。

三個 ASR 模型,自動路由

沒有任何單一語音辨識模型能完整覆蓋所有語言。為了不讓部分語言的辨識品質低落,App 內建了三個各具專長的模型:

  • Parakeet 英語優化。隨 App 一同打包,英語 ASR 即開即用,無需下載。
  • Whisper.cpp 廣泛的多語言支援,涵蓋 30 多種語言。
  • Qwen3-ASR 中日韓優化,並專門支援粵語。

使用者選擇來源語言後,Dart 路由層自動挑選最適合的模型,並通知原生端啟動對應引擎。使用者完全不需要手動管理模型選擇。

棘手的地方在於記憶體。這些模型的 RAM 需求從 500MB 到 1.9GB 不等,若同時載入三個,大多數手機會直接崩潰。記憶體預算規劃器(以 Dart 編寫,向原生層查詢記憶體統計資料)追蹤已載入的模型,並在需要載入新模型時卸除最久未使用的模型。後端偏好儲存器會記住每台裝置上哪個計算後端(NPU、GPU、CPU)運作正常,讓後續執行能跳過失敗的後端。

雙層翻譯架構,涵蓋 108 種語言

翻譯透過兩條路徑執行:

第一層——傳統 NMT 模型(61 種語言): 速度快、記憶體佔用低,對資源豐富的語言對品質出色。ONNX 模型透過 sherpa-onnx 在兩個平台上執行。

第二層——裝置端 Gemma LLM(另外 47 種語言): 對於沒有專用 NMT 模型的語言(約魯巴語、阿姆哈拉語、寮語、緬甸語等),量化版 Gemma 2B 模型在本地端處理翻譯。速度比第一層慢,但將覆蓋範圍延伸至傳統模型表現欠佳的語言。

Dart 層根據語言對自動決定使用哪一層,使用者看到的是統一流暢的體驗。

相機 OCR:雙引擎,92 種語言

相機翻譯提供使用者可自行切換的兩種引擎:

Basic 模式 使用 Google ML Kit 的裝置端文字辨識,速度快,對拉丁字母、西里爾字母和中日韓文字處理良好,適合即時取景器使用。

Professional 模式 使用裝置端執行的 PaddleOCR,對複雜排版、混合文字、弧形文字和低對比度的辨識精度更高。由於計算量較大,每次擷取消耗 5 枚金幣。

有個教訓是吃過苦頭才學到的:iOS 預設只內建拉丁字母的 OCR 模型。中日韓、梵文和阿拉伯文需要在 Podfile 中明確加入對應的 pods。失敗完全無聲無息——ML Kit 對不支援的文字只會回傳空結果,不報任何錯誤。如果你要在 iOS 上用 ML Kit 開發多語言 OCR,務必檢查你的 Podfile。

浮動疊加層:原生實作,不走 Flutter

螢幕翻譯和系統音訊功能以原生疊加層的形式運行,脫離 Flutter 的渲染範圍。在 Android 上,這是一個以 Kotlin 編寫的系統疊加層服務;在 iOS 上,使用 Swift 的螢幕擷取 API。

這些疊加層透過平台通道回傳結果給 Flutter 翻譯引擎。架構上的挑戰在於生命週期管理——疊加層必須持續存活,即使主要的 Flutter Activity 已退至背景。

一個關鍵教訓:在 iOS 上,原生橋接實例必須被強持有(static 或由單例持有)。如果橋接是一個沒有任何持有者的實例變數,ARC 會將其回收,所有回呼閉包就會靜默變成空操作。我曾有好幾天被一個卡在 0% 的下載進度指示器搞得焦頭爛額,原因正是橋接被回收了——沒有崩潰,沒有錯誤,只是靜默失敗。

藍牙群組聊天

離線群組聊天使用藍牙網格協定。每支手機同時扮演接收端和中繼端,訊息廣播至所有連線裝置。每台裝置獨立執行 ASR 和翻譯,沒有「主機」或「伺服器」手機。

Flutter 負責聊天 UI、訊息狀態和參與者管理。藍牙協定棧完全原生實作(iOS 使用 CoreBluetooth,Android 使用藍牙 API),並透過平台通道橋接。

完整流程的延遲(語音 → ASR → 翻譯 → 廣播 → 顯示)約為 1 秒。Dart UI 採用樂觀顯示策略(發送時立即顯示「翻譯中…」),讓對話體驗更加流暢。

數字

  • 支援語言: 共 108 種(61 種 ML + 47 種 AI)
  • ASR 語言: 30 種裝置端語音辨識
  • OCR 語言: 92 種相機文字辨識
  • App 基礎大小: 約 150MB + 可下載模型
  • 平台: 以單一 Flutter 程式碼庫支援 iOS + Android
  • Dart/Flutter 程式碼: 約佔總程式碼庫 60%(UI、狀態、路由、業務邏輯)
  • 原生程式碼: 約佔 40%(ASR、LLM、OCR、藍牙、疊加層、記憶體管理)
  • 團隊規模: 1 人

Flutter 在這個專案中做對的事

單一程式碼庫應對複雜 UI。 五個功能介面、每個介面多種模式、下載彈窗、引導教學、自適應佈局——對一個獨立開發者來說,只需寫一遍而非兩遍,是能否順利上線的關鍵差異。

平台通道設計良好。 Dart 與原生程式碼之間的橋梁清晰、文件完善、運作可靠。對於一款繁重運算在原生端、使用者體驗在 Flutter 端的 App,這正是最合適的架構。

Hot Reload 加速迭代。 調整佈局、測試狀態、優化 UX 流程——Hot Reload 將每次迭代時間從數分鐘縮短至數秒,橫跨數百次 UI 修改。

生態系統已相當成熟。 狀態管理(Riverpod)、導航、本地化(117 種語系)、自適應設計——Flutter 生態系統對這些需求都有生產就緒的解決方案。

遇到的困難

記憶體壓力是 Flutter 的盲點。 Flutter 沒有提供細粒度的記憶體控制介面。當你要同時在 Flutter 引擎旁載入多個原生 ML 模型時,你需要在原生層管理記憶體,再將狀態暴露回 Dart。Flutter 沒有內建 API 能告訴你「App 目前使用了多少 RAM」或「系統記憶體壓力狀況如何」。

原生疊加層的生命週期。 在 Flutter 渲染範圍之外運行的浮動疊加層,在架構上相當複雜。疊加層啟用時,Flutter Activity 可能已退至背景。保持橋接存活、管理狀態同步、處理各平台特有的生命週期事件,需要大量 Flutter 無法抽象化的原生程式碼。

iOS 建置複雜度。 CocoaPods 搭配 ML Kit 文字腳本 pods、權限設定(同時載入 ASR + LLM 所需的 increased-memory-limit)、App 追蹤透明度的觸發時機、程式碼簽署——iOS 建置流程有許多 Flutter 工具鏈無法完全管理的細節環節。

立即體驗

Traverba 在兩個平台均免費提供。語音、相機、螢幕翻譯和文字翻譯全部免費且無限制使用。Premium 方案($1.99/月)可解鎖群組聊天、檔案轉錄和會議摘要功能。

現已上架 Google PlayApp Store。更多資訊請參閱 traverba.com

歡迎就架構設計、Flutter 與原生整合模式,或裝置端 AI 相關問題交流討論。