制工具:利用Vision框架實(shí)現(xiàn)屏幕取詞)
開發(fā) macOS 應(yīng)用時(shí)把屏幕上的文字“抓”下來(lái)復(fù)制到剪貼板是一個(gè)很常見(jiàn)的自動(dòng)化需求。之前我一直用第三方 OCR 服務(wù)或者 Tesseract但配置麻煩、識(shí)別中文效果也不理想。后來(lái)發(fā)現(xiàn) macOS 系統(tǒng)本身自帶了 OCR 能力通過(guò) Vision 框架就能調(diào)用不需要聯(lián)網(wǎng)也不依賴任何第三方 SDK??吹接腥朔窒砹艘粋€(gè)叫 “Monkey see, monkey do” 的小項(xiàng)目思路就是“眼睛看到什么就能復(fù)制什么”本質(zhì)上就是屏幕截取 原生 OCR。這篇文章我就把這條鏈路完整拆解一遍帶你從零實(shí)現(xiàn)一個(gè) macOS 原生 OCR 文字復(fù)制工具代碼可以直接跑。本文適合 macOS 開發(fā)者、自動(dòng)化腳本愛(ài)好者也適合想了解 Vision 框架文本識(shí)別的大前端和 AI 方向讀者。學(xué)完你可以掌握如何調(diào)用 macOS 原生 OCR 識(shí)別圖片如何截取屏幕區(qū)域如何把識(shí)別結(jié)果寫入剪貼板并了解權(quán)限配置、性能優(yōu)化和常見(jiàn)坑點(diǎn)。1. 背景macOS 上實(shí)現(xiàn) OCR 有哪些方案1.1 什么是 OCROCROptical Character Recognition光學(xué)字符識(shí)別的目的是從圖像中提取文字。比如一張截圖、一張掃描件、甚至攝像頭拍到的畫面只要里面有文字OCR 就能把它們變成可編輯、可復(fù)制的文本。在 macOS 上做文字識(shí)別常見(jiàn)方案有方案類型優(yōu)缺點(diǎn)Tesseract開源本地引擎免費(fèi)但需要安裝語(yǔ)言包中文識(shí)別精度一般百度 OCR / 騰訊 OCR云端 API精度高但要聯(lián)網(wǎng)、有調(diào)用配額涉及隱私macOS Vision系統(tǒng)原生框架免費(fèi)、離線、集成度高支持中文無(wú)需額外依賴從工程角度看如果你的工具只在 macOS 上跑且不想把用戶截圖上傳到云端Vision 框架是最合適的選擇。它內(nèi)置在系統(tǒng)里性能和識(shí)別率都經(jīng)過(guò)蘋果優(yōu)化尤其是 macOS 12 之后對(duì)中文、日文、韓文的支持已經(jīng)比較完善。1.2 “Monkey see, monkey do” 想表達(dá)什么“Monkey see, monkey do” 是一個(gè)英文俗語(yǔ)意思是“看到什么就模仿什么”。放到 OCR 工具里就是一個(gè)很形象的產(chǎn)品邏輯屏幕上出現(xiàn)什么文字工具就把它識(shí)別并復(fù)現(xiàn)出來(lái)。你可以想象這樣的使用場(chǎng)景看視頻時(shí)發(fā)現(xiàn)字幕里有想要保存的句子直接一框選就復(fù)制閱讀加密 PDF 或圖片型 PDF 時(shí)無(wú)法選中文字用 OCR 工具提取軟件界面上的報(bào)錯(cuò)信息無(wú)法復(fù)制直接截屏識(shí)別開會(huì)時(shí)想把幻燈片里的文字快速做成筆記。這些需求都可以用 macOS 原生能力實(shí)現(xiàn)不需要購(gòu)買專業(yè)軟件。1.3 為什么推薦使用系統(tǒng)原生 OCR使用 Vision 框架的好處很明顯離線可用不依賴網(wǎng)絡(luò)不把數(shù)據(jù)上傳到第三方服務(wù)器免費(fèi)無(wú)限量本地計(jì)算沒(méi)有 API 配額和費(fèi)用隱私安全截圖留在本機(jī)適合處理敏感文檔中文支持好系統(tǒng)語(yǔ)言包已經(jīng)內(nèi)置開箱即用與 macOS 系統(tǒng)深度集成可以配合快捷鍵、Automator、Shortcuts 使用。如果你的應(yīng)用只面向 macOS優(yōu)先用系統(tǒng)能力往往是性價(jià)比最高的方案。2. 環(huán)境準(zhǔn)備與版本說(shuō)明在開始寫代碼之前先確認(rèn)你的開發(fā)環(huán)境和運(yùn)行環(huán)境。2.1 操作系統(tǒng)版本Vision 框架從 macOS 10.15 開始引入文本識(shí)別能力但早期的VNRecognizeTextRequest僅支持英文。如果你需要識(shí)別中文建議使用 macOS 12 Monterey 及之后版本此時(shí) Live Text 已內(nèi)置識(shí)別質(zhì)量和語(yǔ)言豐富度提升明顯。本文示例基于 macOS 13/14 實(shí)測(cè)理論兼容 macOS 12。如果你的系統(tǒng)是 macOS 10.15 或 11代碼大部分可用但中文識(shí)別可能受限。2.2 開發(fā)工具Xcode可以使用 Xcode 14 或更高版本命令行工具也可以單獨(dú)安裝Swift示例代碼基于 Swift 5Command Line Tools如果你不想建完整 Xcode 工程直接用swift命令編譯運(yùn)行也可以。檢查 Command Line Tools 是否安裝xcode-select --install查看 Swift 版本swift --version2.3 運(yùn)行權(quán)限如果你的 OCR 工具只識(shí)別圖片文件不需要額外權(quán)限。但如果你要實(shí)現(xiàn)屏幕實(shí)時(shí)取詞需要給終端或 App 授權(quán)“屏幕錄制”權(quán)限系統(tǒng)設(shè)置 → 隱私與安全性 → 屏幕錄制把你運(yùn)行工具所在的終端 App比如 Terminal、iTerm勾選上。如果你要把工具打包成獨(dú)立 App還需在 App 的Info.plist中聲明keyNSScreenCaptureUsageDescription/key string需要截取屏幕內(nèi)容以進(jìn)行 OCR 文字識(shí)別/string如果是命令行工具沒(méi)有 Info.plist但系統(tǒng)仍會(huì)在第一次調(diào)用截屏 API 時(shí)彈出授權(quán)提示。2.4 示例項(xiàng)目結(jié)構(gòu)為了讓示例盡量簡(jiǎn)單我們不建 Xcode 工程直接用 Swift 腳本。項(xiàng)目結(jié)構(gòu)如下monkey-see/ ├── main.swift ├── Package.swift # 可選如果使用 SwiftPM └── images/ └── sample.png你可以把main.swift當(dāng)成獨(dú)立命令行工具運(yùn)行。3. 核心原理Vision 框架如何做文字識(shí)別Vision 是蘋果提供的計(jì)算機(jī)視覺(jué)框架。它并不直接對(duì)外暴露 UI而是通過(guò) request-handler 模式工作。3.1 核心概念VNRecognizeTextRequest文本識(shí)別請(qǐng)求對(duì)象負(fù)責(zé)配置識(shí)別參數(shù)VNImageRequestHandler圖像請(qǐng)求處理器負(fù)責(zé)把圖片數(shù)據(jù)交給 Vision 分析VNRecognizedTextObservation識(shí)別結(jié)果包含文字內(nèi)容和坐標(biāo)位置。一個(gè)完整的識(shí)別流程是把圖片轉(zhuǎn)換為CGImage創(chuàng)建VNRecognizeTextRequest創(chuàng)建VNImageRequestHandler并執(zhí)行請(qǐng)求遍歷VNRecognizedTextObservation提取文本。3.2 識(shí)別精度設(shè)置recognitionLevel有兩個(gè)選項(xiàng).fast速度快適合實(shí)時(shí)截屏.accurate精度高適合從圖片中提取文字。對(duì)于截圖場(chǎng)景建議先用.accurate提高準(zhǔn)確率如果性能不夠再改為.fast。3.3 語(yǔ)言支持通過(guò)recognitionLanguages可以指定識(shí)別語(yǔ)言。常用語(yǔ)言代碼zh-Hans簡(jiǎn)體中文en-US英文ja-JP日文ko-KR韓文。如果希望同時(shí)識(shí)別中英文可以傳入多個(gè)語(yǔ)言request.recognitionLanguages [zh-Hans, en-US]注意并非所有語(yǔ)言在所有系統(tǒng)版本上都可用建議做一次可用語(yǔ)言查詢。3.4 坐標(biāo)系統(tǒng)Vision 的坐標(biāo)系統(tǒng)與 UIKit/AppKit 不同。Vision 使用歸一化坐標(biāo)原點(diǎn)在圖片左下角y 軸向上。如果你需要把文字框畫在截圖原圖上需要做坐標(biāo)轉(zhuǎn)換。3.5 核心代碼示例下面是一個(gè)最小可用的 Swift 函數(shù)用來(lái)識(shí)別一張 PNG 圖片中的所有文字import Vision import AppKit func recognizeText(from image: NSImage) - String { guard let cgImage image.cgImage(forProposedRect: nil, context: nil, hints: nil) else { return } var resultText let request VNRecognizeTextRequest { request, error in guard let observations request.results as? [VNRecognizedTextObservation] else { return } for observation in observations { if let candidate observation.topCandidates(1).first { resultText candidate.string \n } } } request.recognitionLevel .accurate request.recognitionLanguages [zh-Hans, en-US] request.usesLanguageCorrection true let handler VNImageRequestHandler(cgImage: cgImage, options: [:]) try? handler.perform([request]) return resultText }這段代碼中topCandidates(1)返回置信度最高的一個(gè)候選文本usesLanguageCorrection會(huì)利用語(yǔ)言模型修正識(shí)別結(jié)果默認(rèn)開啟try? handler.perform忽略錯(cuò)誤實(shí)際項(xiàng)目中建議用do-catch處理。4. 完整實(shí)戰(zhàn)從屏幕截取到復(fù)制文字接下來(lái)我們實(shí)現(xiàn)一個(gè)完整的命令行工具用戶啟動(dòng)程序后截取當(dāng)前屏幕自動(dòng)識(shí)別屏幕上的所有文字并復(fù)制到剪貼板。4.1 創(chuàng)建 Swift 腳本先創(chuàng)建一個(gè)文件夾mkdir monkey-see cd monkey-see touch main.swift用文本編輯器打開main.swift。4.2 獲取屏幕截圖macOS 截取主屏幕可以使用 Core Graphics 的CGDisplayCreateImage。這個(gè) API 會(huì)返回一個(gè)CGImage可以直接交給 Vision 處理。import CoreGraphics func captureScreen() - CGImage? { let screenRect CGMainDisplayBounds() guard let image CGDisplayCreateImage(CGMainDisplayID()) else { return nil } return image }CGMainDisplayID()返回主顯示器 IDCGDisplayCreateImage會(huì)生成該顯示器的圖像。如果你想截取某個(gè)區(qū)域可以在生成圖片后使用cropping(to:)裁剪。4.3 對(duì)截圖進(jìn)行 OCR 識(shí)別我們復(fù)用上一節(jié)的recognizeText函數(shù)但輸入變成CGImage避免 NSImage 轉(zhuǎn)換開銷import Vision func recognizeText(from cgImage: CGImage) - String { var resultText let request VNRecognizeTextRequest { request, error in guard error nil else { print(識(shí)別錯(cuò)誤: \(error!.localizedDescription)) return } guard let observations request.results as? [VNRecognizedTextObservation] else { return } for observation in observations { if let candidate observation.topCandidates(1).first { resultText candidate.string \n } } } request.recognitionLevel .accurate request.recognitionLanguages [zh-Hans, en-US] request.usesLanguageCorrection true let handler VNImageRequestHandler(cgImage: cgImage, options: [:]) do { try handler.perform([request]) } catch { print(執(zhí)行失敗: \(error.localizedDescription)) } return resultText }4.4 寫入剪貼板macOS 里寫入剪貼板最簡(jiǎn)單的方式是使用NSPasteboardimport AppKit func copyToPasteboard(_ text: String) { let pasteboard NSPasteboard.general pasteboard.clearContents() pasteboard.setString(text, forType: .string) }注意命令行工具使用 AppKit 需要保證有圖形會(huì)話普通終端運(yùn)行沒(méi)有問(wèn)題。4.5 主程序組裝在main.swift里把這三步串起來(lái)import Foundation import AppKit import Vision import CoreGraphics // ... 上面定義的函數(shù) ... main struct MonkeySee { static func main() { print(正在截取屏幕...) guard let screenImage captureScreen() else { print(截屏失敗) exit(1) } print(正在進(jìn)行 OCR 識(shí)別...) let text recognizeText(from: screenImage) guard !text.isEmpty else { print(沒(méi)有識(shí)別到文字) exit(0) } copyToPasteboard(text) print(識(shí)別完成已復(fù)制以下內(nèi)容到剪貼板) print(-----------------------------) print(text) } }如果你不想用main也可以直接把頂層代碼寫在main.swift中。4.6 編譯運(yùn)行由于 Swift 命令行工具可以直接從源文件編譯執(zhí)行swiftc -o monkey-see main.swift -framework Vision -framework AppKit -framework CoreGraphics然后運(yùn)行./monkey-see首次運(yùn)行可能會(huì)彈出“終端想要截取屏幕圖像”的授權(quán)提示點(diǎn)擊允許后需要重新運(yùn)行。4.7 測(cè)試效果準(zhǔn)備一張包含中英文文字的圖片或者打開任意網(wǎng)頁(yè)運(yùn)行工具后正在截取屏幕... 正在進(jìn)行 OCR 識(shí)別... 識(shí)別完成已復(fù)制以下內(nèi)容到剪貼板 ----------------------------- 這個(gè)網(wǎng)站使用 Cookie 來(lái)增強(qiáng)您的瀏覽體驗(yàn)。 Hello, welcome to my blog!打開文本編輯器粘貼就能看到完整內(nèi)容。5. 進(jìn)階實(shí)現(xiàn)矩形區(qū)域 OCR 和快捷鍵喚起整屏識(shí)別雖然簡(jiǎn)單但實(shí)際使用時(shí)往往只需要識(shí)別某一塊區(qū)域。比如彈窗中的錯(cuò)誤信息、視頻字幕、表格中的某一列。下面我們?cè)黾訁^(qū)域選擇能力。5.1 使用screencapture命令配合區(qū)域截圖最簡(jiǎn)單的方式是調(diào)用系統(tǒng)自帶的screencapture命令行工具。它可以讓你手動(dòng)框選區(qū)域。screencapture -i /tmp/ocr_selection.png如果希望截取后光標(biāo)變成十字準(zhǔn)線并允許用戶拖動(dòng)選擇區(qū)域使用-i交互模式。截圖成功后生成的 PNG 文件再交給 OCR 識(shí)別。5.2 Swift 調(diào)用screencapture在 Swift 中可以用Process執(zhí)行系統(tǒng)命令import Foundation func captureSelection() - URL? { let url URL(fileURLWithPath: /tmp/ocr_selection.png) let process Process() process.executableURL URL(fileURLWithPath: /usr/sbin/screencapture) process.arguments [-i, url.path] do { try process.run() process.waitUntilExit() if FileManager.default.fileExists(atPath: url.path) { return url } } catch { print(截屏失敗: \(error)) } return nil }注意screencapture在較新的 macOS 中路徑通常是/usr/sbin/screencapture也可能位于/sbin建議用xcrun --find screencapture查找。5.3 從文件加載圖片并識(shí)別拿到截圖文件后用 NSImage 加載if let url captureSelection() { guard let image NSImage(contentsOf: url), let cgImage image.cgImage(forProposedRect: nil, context: nil, hints: nil) else { print(無(wú)法加載截圖) exit(1) } let text recognizeText(from: cgImage) copyToPasteboard(text) print(text) }5.4 綁定快捷鍵如果你希望按下某個(gè)快捷鍵就啟動(dòng)“區(qū)域 OCR”流程可以使用全局熱鍵庫(kù)比如Carbon 的RegisterEventHotKey第三方庫(kù)HotKeySwiftPMmacOS 自帶 Shortcuts 快捷指令。用 Carbon 實(shí)現(xiàn)全局快捷鍵比較繁瑣這里給出思路。更推薦使用HotKey這個(gè)開源庫(kù)它封裝了事件監(jiān)聽使用起來(lái)更現(xiàn)代。import HotKey let hotKey HotKey(key: .space, modifiers: [.control]) hotKey.keyDownHandler { // 執(zhí)行區(qū)域截圖和 OCR startRegionCaptureAndRecognize() }注意第三方庫(kù)需要額外集成如果是個(gè)人學(xué)習(xí)完全可以用 Automator 或者 BetterTouchTool 去綁定快捷鍵。5.5 權(quán)限補(bǔ)充使用screencapture -i時(shí)系統(tǒng)同樣會(huì)要求屏幕錄制權(quán)限。如果出現(xiàn)黑屏或無(wú)法截圖請(qǐng)檢查權(quán)限設(shè)置。6. 常見(jiàn)問(wèn)題與排查思路6.1 問(wèn)題對(duì)照表問(wèn)題現(xiàn)象常見(jiàn)原因解決思路截屏返回空?qǐng)D沒(méi)有屏幕錄制權(quán)限系統(tǒng)設(shè)置中勾選終端的屏幕錄制權(quán)限識(shí)別不到任何文字圖片中沒(méi)有文字 / 識(shí)別語(yǔ)言未配置換測(cè)試圖片添加語(yǔ)言參數(shù)中文識(shí)別亂碼recognitionLanguages只設(shè)置了en-US添加zh-Hans坐標(biāo)錯(cuò)位Vision 坐標(biāo)系與 AppKit 不一致轉(zhuǎn)換坐標(biāo)y 1 - normalizedY運(yùn)行效率低使用.accurate且圖片過(guò)大調(diào)整為.fast或縮小圖片尺寸命令行工具無(wú)法使用 AppKit未導(dǎo)入AppKit框架編譯時(shí)加-framework AppKit彈出安全提示系統(tǒng)首次請(qǐng)求屏幕錄制權(quán)限點(diǎn)擊允許后重啟終端6.2 識(shí)別不了中文怎么辦首先確認(rèn)系統(tǒng)版本。macOS 12 以下對(duì)中文支持有限建議升級(jí)系統(tǒng)。其次在請(qǐng)求中明確指定中文request.recognitionLanguages [zh-Hans]如果仍無(wú)效用下面代碼查詢當(dāng)前可用的識(shí)別語(yǔ)言let supported try? VNRecognizeTextRequest.supportedRecognitionLanguages(for: .accurate, revision: VNRecognizeTextRequestRevision3) print(supported ?? [])輸出結(jié)果會(huì)列出所有支持的語(yǔ)言代碼。6.3 截屏權(quán)限出現(xiàn)“系統(tǒng)數(shù)據(jù)占用過(guò)大”或無(wú)法截取這和 OCR 本身無(wú)關(guān)但很多用戶會(huì)遇到。如果你的 macOS 系統(tǒng)提示“系統(tǒng)數(shù)據(jù)占用過(guò)大”可以檢查“屏幕錄制”權(quán)限列表是否有殘留的已卸載 App。清理方法重置終端權(quán)限或重啟系統(tǒng)。如果鼠標(biāo)光標(biāo)在screencapture -i交互模式下不顯示可能是全屏截圖權(quán)限未開啟或者正在使用虛擬機(jī)。虛擬機(jī)環(huán)境下屏幕捕獲行為與真實(shí) macOS 不同請(qǐng)參考虛擬機(jī)的顯示驅(qū)動(dòng)配置。6.4 OCR 識(shí)別結(jié)果順序不對(duì)Vision 返回的觀察結(jié)果并不是絕對(duì)按閱讀順序排列的。解決辦法是手動(dòng)排序let sortedObservations observations.sorted { a, b in if abs(a.boundingBox.midY - b.boundingBox.midY) 0.01 { return a.boundingBox.midY b.boundingBox.midY } else { return a.boundingBox.minX b.boundingBox.minX } }由于 Vision 坐標(biāo)原點(diǎn)在左下角midY越大表示位置越靠上。按從下到上不這里我們是要按閱讀順序先按 y 降序上到下同一行內(nèi)按 x 升序左到右。6.5 編譯時(shí)找不到 Vision 框架確保命令行編譯時(shí)添加了-framework Visionswiftc -o monkey-see main.swift -framework Vision -framework AppKit -framework CoreGraphics如果你使用 SwiftPM則需要在Package.swift中鏈接系統(tǒng)框架。7. 最佳實(shí)踐與工程建議7.1 合理選擇識(shí)別精度如果你的應(yīng)用需要實(shí)時(shí)處理視頻幀建議使用.fast并在每幀之間做節(jié)流。對(duì)于靜態(tài)截圖.accurate更合適。7.2 提高識(shí)別準(zhǔn)確率識(shí)別前對(duì)圖片做二值化或增強(qiáng)對(duì)比度將圖片縮放至合適大小過(guò)大或過(guò)小都會(huì)影響效果對(duì)旋轉(zhuǎn)的文字設(shè)置recognitionLevel .accurate但仍有限度對(duì)結(jié)果做后處理例如去掉多余空格、修正標(biāo)點(diǎn)。7.3 隱私與安全不要把截屏圖片明文保存在磁盤上用完即刪如果網(wǎng)絡(luò)傳輸 OCR 結(jié)果務(wù)必加密如果你的 App 會(huì)處理敏感數(shù)據(jù)在隱私政策中明確說(shuō)明在用戶授權(quán)前不要觸發(fā)截圖否則可能被系統(tǒng)拒絕。7.4 處理多語(yǔ)言建議根據(jù)用戶系統(tǒng)語(yǔ)言動(dòng)態(tài)設(shè)置識(shí)別語(yǔ)言而不是寫死??梢酝ㄟ^(guò)Locale.preferredLanguages獲取當(dāng)前語(yǔ)言映射到 Vision 的語(yǔ)言代碼。7.5 內(nèi)存管理Vision 處理大圖時(shí)會(huì)占用較多內(nèi)存。在命令行工具中識(shí)別完成后及時(shí)釋放對(duì)象。如果是 iOS/macOS App建議將識(shí)別任務(wù)放到后臺(tái)隊(duì)列DispatchQueue.global(qos: .userInitiated).async { let text recognizeText(from: cgImage) DispatchQueue.main.async { self.textView.string text } }7.6 日志與錯(cuò)誤處理生產(chǎn)工具一定要有完整的錯(cuò)誤日志。可以把每次識(shí)別耗時(shí)、識(shí)別語(yǔ)言、候選文字?jǐn)?shù)量記錄下來(lái)方便后續(xù)調(diào)優(yōu)。7.7 打包成 App如果你把工具分發(fā)給同事使用可以打包成.app并在Info.plist聲明權(quán)限。使用osascript或 Automator 也能快速做成“服務(wù)”菜單項(xiàng)無(wú)需 Xcode。7.8 與最新系統(tǒng)兼容macOS Sequoia 發(fā)布后很多用戶遇到“若要打開此 App你需要從 macOS 恢復(fù)啟動(dòng)并將安全策略更改為完整安全”的問(wèn)題。這本質(zhì)上是自定義內(nèi)核擴(kuò)展或未簽名 App 的安全策略設(shè)置。對(duì)普通 OCR 工具來(lái)說(shuō)建議使用 Developer ID 簽名避免用戶被安全策略卡住。7.9 性能優(yōu)化方向如果你要做“全局 OCR 搜索”這類工具可以考慮監(jiān)聽屏幕變化增量識(shí)別使用VNImageRequestHandler的regionOfInterest只識(shí)別變化區(qū)域使用 GPU 加速但 Vision 默認(rèn)已經(jīng)使用系統(tǒng)加速能力建立文字緩存避免重復(fù)識(shí)別。8. 總結(jié)與下一步學(xué)習(xí)方向通過(guò)本文的實(shí)戰(zhàn)你已經(jīng)掌握了 macOS 原生 OCR 的核心鏈路使用VNRecognizeTextRequest識(shí)別圖片文字使用CGDisplayCreateImage或screencapture截取屏幕使用NSPasteboard寫入剪貼板處理屏幕錄制權(quán)限通過(guò)識(shí)別語(yǔ)言參數(shù)解決中文支持問(wèn)題。這套方案非常適合做個(gè)人效率工具比如“截圖 OCR”“屏幕取詞”“離線文字提取”。如果想繼續(xù)深入可以嘗試在 iOS 上使用同樣的 Vision API 實(shí)現(xiàn)拍照取詞結(jié)合 Core ML 做自定義文字分類利用 Live Text 的底層能力做更聰明的 OCR 應(yīng)用把 Swift 代碼封裝成命令行工具通過(guò) Python 調(diào)用形成更靈活的自動(dòng)化腳本。關(guān)于 Python 調(diào)用可以借助PyObjC框架但需要安裝對(duì)應(yīng) macOS 版本支持的 pyobjc-framework-Vision 包。環(huán)境配置時(shí)要注意 Python 版本與 PyObjC 的兼容性建議在虛擬環(huán)境中安裝。最后提醒一點(diǎn)屏幕錄制權(quán)限在開發(fā)調(diào)試階段經(jīng)常被忽略一旦發(fā)現(xiàn)截屏全黑優(yōu)先檢查“隱私與安全性”里的授權(quán)列表。調(diào)試完成后把權(quán)限限定在最小范圍保障用戶隱私。如果你也打算做一個(gè)類似的“看到什么就復(fù)制什么”的小工具不妨先從今天的示例改造起。加上一個(gè)快捷鍵再配合區(qū)域截圖就是一個(gè)相當(dāng)順手的日常效率工具了。