Skip to content

feat(eew): announce predicted intensity before warning sound - #546

Open
archie0732 wants to merge 4 commits into
ExpTechTW:mainfrom
archie0732:codex/eew-spoken-intensity
Open

feat(eew): announce predicted intensity before warning sound#546
archie0732 wants to merge 4 commits into
ExpTechTW:mainfrom
archie0732:codex/eew-spoken-intensity

Conversation

@archie0732

@archie0732 archie0732 commented Aug 20, 2026

Copy link
Copy Markdown

這個 PR 做了什麼

在強震監視器顯示於前景時,以系統 TTS 朗讀最新 EEW 預估震度,朗讀完成後才播放原有警示音;新報會中斷舊播報並改讀最新結果。

相關 issue

怎麼驗

手動測試(Android Emulator,x86_64)

執行:

tool\run.ps1 -d emulator-5554 --dart-define=DPIP_DEMO_MONITOR=true --dart-define=DPIP_DEMO_MONITOR_SEVERE=true --dart-define=DPIP_DEMO_MONITOR_SOUND=true

進入「雷達」,切換為「強震監視器」,確認四項:

  • 聽得到朗讀預估震度
  • 朗讀完成後才播放警示音,兩者不重疊
  • 離開強震監視器後立即停止播報
  • 快速切換分頁十次不閃退(驗 MethodChannel.Result 只回一次)

iOS 尚未驗證:開發環境為 Windows,沒有實機或模擬器。SpeechPlugin.swift 只經過 CI 編譯。

自動測試

  • tool/check/commits.sh upstream/main..HEAD:4 commits 通過
  • tool/dev/analyze.shflutter analyze 無問題
  • tool/check/l10n.shlayering.shstorage.shnotification_sounds.shtooling.sh
  • 本次新增的 10 個測試全部通過:
    • 前景 EEW 播報與警示音排序、逾時 fallback
    • 最新報取代舊報、忽略重複及較舊報次、資料過期停止播報
    • 中文五弱/五強/六弱/六強朗讀文字及震度範圍保護

完整 tool/dev/test.sh 在 Windows 上有 56 個失敗,其中 55 個集中在 test/tool/*(Git Bash 把 Windows 路徑轉成 D:GitHub...),另一個是 test/shared/semantics_overlay_portal_test.dart,該檔案本次未修改且在 CI 上為綠。

安全關鍵的部分

播報只在前景、可見的監視器上發生;背景與終止狀態的推播完全不經過這個閘門。TTS 引擎不存在或卡住時有兩層逾時(控制器 8 秒、通知閘門 10 秒),任何情況下都不會讓警示通知被無限期壓住 —— 最壞情況是警報比平常響,不會晚。feed 進入 stale/offline 時直接停止播報。

其他兩則 commit

ci(android)Build Android 先前為紅,原因與本功能無關:這個 PR 從 fork 開,pull_request 事件拿不到 repository secrets,Decode keystore 於是寫出空的 keystore 與四個值全空的 key.properties,Gradle 在 packageRelease 讀不到 keystore 而失敗。同顆 commit 的 iOS job 是綠的,因為它以 --no-codesign 建置。修法是把簽章從這個 job 拿掉:可上傳的簽章成品本來就由 release.yml 在 push 到 main 時產生,而 android/app/build.gradle.ktskey.properties 不存在時會退回 debug signing。

refactor(eew)flutter_tts 不支援 Swift Package Manager,而這個專案的 iOS 端不使用 CocoaPods(README → 參與開發)。Flutter 每次建置都會警告並說明「will become an error in a future version」,在那之前它會透過相依關係悄悄把 Podfile 帶回來。因此改為 app 自有的 com.exptech.dpip/speech channel,兩邊各三十行;SpeechService 原本就是介面,上層的控制器、閘門與測試一行未改。pubspec.yamlpubspec.lock 現在與 main 完全相同,這個 PR 不再引入任何相依套件。

檢查清單

  • tool/check/commits.sh origin/main..HEAD 通過
  • 一個 commit 一件事
  • flutter analyze 通過;新增測試全數通過
  • 新的使用者可見字串都走 AppLocalizations,沒有寫死(含新增的粵語 app_yue.arb
  • 無 UI 視覺變更

@lowrt

lowrt commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

記得要 rebase before merging

New(zh-Hant): 強震監視器會先朗讀地震預估震度,再播放警示音
New(en-US): the seismic monitor announces predicted intensity before the warning sound
@archie0732
archie0732 force-pushed the codex/eew-spoken-intensity branch from ad76de1 to 1f489c4 Compare September 5, 2026 07:30
@lowrt

lowrt commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

@archie0732

The following plugins do not support Swift Package Manager for ios:

  • flutter_tts
    This will become an error in a future version of Flutter. Please contact the plugin maintainers to request Swift Package Manager adoption.

`flutter_tts` ships no Swift Package Manager support, and the iOS build
has none of the CocoaPods setup it therefore needs (README → 參與開發:
"iOS 已改用 Swift Package Manager,不需要 CocoaPods"). Flutter says so
during every build and adds that it "will become an error in a future
version" — until then it quietly reintroduces a Podfile through a
transitive dependency, which is the half of that warning nobody reads.

So the two calls it was providing are owned here, as the eleventh iOS
plugin and the thirteenth Android channel: `AVSpeechSynthesizer` on one
side, `android.speech.tts.TextToSpeech` on the other, thirty lines each.
`SpeechService` was already an interface with the package behind a single
implementation, so the announcement controller, the notification gate and
their tests are untouched.

Both sides answer a `speak` exactly once and answer it normally when a
later phrase supersedes it: latest-report-wins is this caller's contract,
so a cut-off phrase is the expected path rather than an error. The Android
half replies on the main thread — `UtteranceProgressListener` runs on a
binder thread, and a `MethodChannel.Result` answered from there is a crash
rather than a warning — and holds the first call until the engine finishes
binding, because the announcement that matters most is the first one.
@lowrt

lowrt commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

@archie0732
https://github.com/dlutton/flutter_tts/pulls
看起來裡面有不少人抄作業Network graph (而且有三個PR😂

另外剛創 https://github.com/ExpTechTW/flutter_tts 可以開PR

@archie0732

Copy link
Copy Markdown
Author

@archie0732 https://github.com/dlutton/flutter_tts/pulls 看起來裡面有不少人抄作業Network graph (而且有三個PR😂

另外剛創 https://github.com/ExpTechTW/flutter_tts 可以開PR

maplibre_gl 那條路我沒想到,fork 確實是這個 repo 既有的做法。上游那三個 PR 從 5 月放到現在都沒合,等作者應該是等不到了。

不過在你留言之前我已經先改成 app 自有的 channel 了(c537a540),所以想先把兩個方案的現況擺出來,你決定要哪一個我照做。

現在這版(自有 channel)

com.exptech.dpip/speech,SpeechPlugin.swift + SpeechChannel.kt,兩邊各約 30 行,跟現有的 CompassPlugin / ScreenWakeChannel 同一個模子
SpeechService 原本就是介面、flutter_tts 只在一個實作裡,所以上層的控制器、閘門和那 10 個測試一行未改
pubspec.yaml 和 pubspec.lock 現在跟 main 完全相同,這個 PR 不再引入任何相依
Android 實機驗過四項:聽得到朗讀、講完才響、離開就停、快速切換分頁十次不閃退(這項是在驗 MethodChannel.Result 只回一次)
代價:只實作 speak / stop,沒有語音選擇、語速、音高、佇列
fork + SPM

保留完整功能,之後要調語速那類的不用再寫原生
代價是 ExpTechTW 要長期維護那個 fork、追上游
流程上多一輪:移植 SPM 改動 → 在 fork 開 PR → 合併 → 回來改 DPIP 的相依
以這個功能目前只需要「講一句話、講完通知我」來說,我覺得自有 channel 的成本比較低;但如果之後預期會用到 flutter_tts 的其他能力,那 fork 比較划算,這個你比我清楚。

另外不論走哪條路,我沒有 Mac,iOS 端的執行期行為(語音真的出得來、audio session 不會蓋掉別的 app)都要麻煩有裝置的人幫忙看一下。

你說走 fork 我就把 c537a54 拿掉改成 git 相依,覺得自有 channel 可以就維持現狀。

@archie0732
archie0732 marked this pull request as ready for review September 5, 2026 13:15
@archie0732
archie0732 requested a review from a team as a code owner September 5, 2026 13:15
@lowrt

lowrt commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

@whes1015 起床再看方案說法

經過測試iOS模擬器有說話 預估所在地震度
然後這個沒有設定可以開關?

@BigDuck430

BigDuck430 commented Sep 5, 2026

Copy link
Copy Markdown
Member

五弱 五強 六弱 六強的部份,有需要加「等級」嗎?因為地牛是直接五弱 這樣感覺贅字也比較少
給個小建議 謝謝

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

唸出地震預測震度

3 participants