🎙️ Lecture 20: 【實戰演練七】進階語音過濾與正則運算 (brlReader)

NOTE作者資訊 (Author Info)

🎧 錄音室開場:點字與語音的火車調度員!


🎯 專案解密:brlReader 的開發血淚史

當我們閱讀 brlReader_history.md,會發現開發這個外掛時遇到了三大魔王:

1. 語音合成器罷工(WorldVoice 不講話)

一開始,開發者把點字字典硬塞進 NVDA 核心。結果遇到特定語音引擎(如 WorldVoice 或 eSpeak)時,因為點字被轉成中文,語音引擎的「語言偵測」大亂,導致整行靜音! * 解決方案:不再依賴核心字典。改用 L18 學過的 speech.filter_speechSequence。並且加上 moveToEnd(..., last=False),要求 NVDA 把我們的攔截器排在「所有過濾器的最前面」,在語音引擎處理前就先把它翻譯成中文!

2. 空白與字串被拆散的悲劇

NVDA 底層會把一段文字如 o0' 拆成兩個元素:字母 o 與數字 0'。這導致查字典時永遠比對失敗。另外,瀏覽器複製貼上時,常常會偷偷在字元中間塞入空白 o 0 '。 * 解決方案:在過濾器內,把語音序列(sequence)裡所有的文字先強制黏在一起 (join),然後使用「正則表達式 (Regex)」把多餘的空白過濾掉,最後才拿去查字典。

3. 數字被字典「誤殺」

點字裡的數字是用 # 開頭,例如 #cc 代表 33。但如果翻譯後變成 33,NVDA 可能又會拿 33 去查字典,結果把 33 唸成了點字裡的「我我」! * 解決方案(防誤殺保護):使用強大的 re.split(r'(#[a-j0-9.,/%:-]+)', text)。這句魔法把文字精準切成「數字區塊」與「普通區塊」。數字區塊翻譯完後,直接貼上「免死金牌(跳過字典)」,徹底解決了二次查表的問題!


📝 大導演的 Vibe Coding 派工單 (Prompt)

如果你想要 AI 重現這個神級外掛,請使用以下的高階 Prompt:

「你現在是精通 NVDA 語音過濾器與 Python 正則運算的頂尖工程師。請幫我寫一個全域外掛 brlReader.py

核心開發規範(請嚴格遵守避坑指南): 1. 請在 __init__ 中註冊 speech.filter_speechSequence,並務必使用 moveToEnd(last=False) 搶佔最優先執行權。 2. 【字串重組與空白過濾】:在過濾器中,請先將語音序列裡所有字串元素拼接合併,並使用 Regex 將英數之間無意義的空格刪除,以解決 NVDA 核心字串拆分的問題。 3. 【數字邊界與防誤殺】:請使用 re.split(r'(#[a-j0-9.,/%:-]+)', text) 來精準分割點字數字區塊。 4. 對於分割出的奇數(數字)區塊,去除 # 並將 a-j 轉譯為 1-0 後,直接保護,絕對不可送入點字字典翻譯。 5. 偶數(非數字)區塊,則正常送入 brl.dic 進行查表替換。 6. 請提供一個繼承自 gui.settingsDialogs.SettingsPanel 的原生設定面板,讓使用者可以勾選開啟/關閉偵錯日誌。

請直接輸出完整且考慮到多重保護機制的 Python 原始碼。」


🎓 學習總結

brlReader 是一個將 Vibe Coding 技巧發揮到極致的案例。身為大導演,當你發現 AI 寫的程式「在某些時候會唸錯」時,不要只跟 AI 說「壞掉了」。你要學會看 Log 紀錄,發現原來是「空白」或「數字」被誤判。然後在下一版的 Prompt 中,加入「正則過濾」與「數字防護」的具體指令,這才是 Vibe Coding 大師的真正實力!

👉 下一堂課:Lecture 21 【終極大師專案】Windows 底層鍵盤攔截與執行緒安全 (zhuyin_say)
👉 回課程大綱:學習地圖

🔥 專家級深度思考與實戰挑戰 (Expert Challenge)

以下題目專為尋求真正硬核觀念與專家級實戰能力的學員設計。題目無法從講義表面抄寫解答,請嘗試獨立思考後再點擊展開解析。

❓ 挑戰 1:點字觸摸顯示器 (Braille Display) 的 8 點點字碼 (8-dot Braille) 轉換機制 👉 點擊展開專家解析答案

【實戰情境問題】:NVDA 如何將螢幕上的文字(如 Python 程式碼)轉換為點字顯示器上的點陣訊號?點字翻譯表 (Braille Translation Table) 在此過程中扮演什麼角色?

【鑑別點說明】:測試學員對視障點字顯示器(Braille Output Layer)與 Liblouis 點字翻譯引擎的理解。

【專家級解答與深度剖析】: NVDA 內建了開源的 Liblouis 點字翻譯引擎。當文字傳入時,Liblouis 根據使用者設定的點字表(如 Unicode 8點點字表或台灣注音點字表),將文字字元映射為 8 個位元 (Bit) 的位元組掩碼(如 Bit 1~8 對應點字顯示器上的 8 個物理觸針升降)。NVDA 隨後透過 USB/藍芽 Serial 協定將此點陣位元組傳送給點字顯示器硬體,驅動壓電陶瓷片升起對應點位。

❓ 挑戰 2:點字游標 (Braille Cursor) 與螢幕焦點 (System Focus) 的同步追蹤 👉 點擊展開專家解析答案

【實戰情境問題】:當視障使用者用手觸摸點字顯示器上的按鈕(觸控點字鍵/Routing Key)時,NVDA 如何將點字單元格的實體位置精確映射回網頁 DOM 樹中的特定節點?

【鑑別點說明】:深剖點字路由鍵 (Routing Keys) 與雙向無障礙幾何映射 (Bidirectional Mapping)。

【專家級解答與深度剖析】: NVDA 在渲染點字時,維護了一份「文字字元 ➔ 點字單元格 ➔ NVDAObject 屬性」的雙向映射陣列(Text-to-Braille Map)。當使用者按下點字顯示器某個單元格上方的 Routing Key 時,硬體會拋出包含單元格索引的觸控訊號。NVDA 的點字處理器查表找出該單元格對應的文字位置與 `NVDAObject` 節點,並立即呼叫 `obj.setFocus()`,實現了「手指摸到哪裡,螢幕焦點就瞬間跳到哪裡」的雙向同步。