From 843e230af6ddb9f6d9e576efdd842c306c3eb837 Mon Sep 17 00:00:00 2001 From: icarus Date: Sat, 23 Aug 2025 13:14:32 +0800 Subject: [PATCH 1/3] =?UTF-8?q?refactor(ocr):=20=E4=BF=AE=E6=94=B9ocrProvi?= =?UTF-8?q?derCapabilityRecord=E7=B1=BB=E5=9E=8B=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 允许只定义部分能力 --- src/renderer/src/types/ocr.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/renderer/src/types/ocr.ts b/src/renderer/src/types/ocr.ts index c7870a95f4..c7e53f24a6 100644 --- a/src/renderer/src/types/ocr.ts +++ b/src/renderer/src/types/ocr.ts @@ -21,7 +21,7 @@ export const isOcrProviderCapability = (cap: string): cap is OcrProviderCapabili return Object.hasOwn(OcrProviderCapabilities, cap) } -export type OcrProviderCapabilityRecord = Record +export type OcrProviderCapabilityRecord = Partial> export type OcrProvider = { id: string @@ -59,7 +59,7 @@ export type ImageOcrProvider = OcrProvider & { } export const isImageOcrProvider = (p: OcrProvider): p is ImageOcrProvider => { - return p.capabilities.image + return p.capabilities.image === true } export type SupportedOcrFile = ImageFileMetadata From bfb64522cdfef955e768e9d4aeff1f44e1fa05da Mon Sep 17 00:00:00 2001 From: icarus Date: Sat, 23 Aug 2025 13:26:09 +0800 Subject: [PATCH 2/3] =?UTF-8?q?refactor(ocr):=20=E5=B0=86Tesseract?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E9=85=8D=E7=BD=AE=E7=A7=BB=E8=87=B3=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E5=86=85=E9=83=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将语言列表和下载URL常量从共享配置移至Tesseract服务内部 使用常量定义图片大小阈值以提高可读性 --- packages/shared/config/constant.ts | 6 ------ .../services/ocr/tesseract/TesseractService.ts | 16 ++++++++++++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/shared/config/constant.ts b/packages/shared/config/constant.ts index 9240bb73f5..82b78459a5 100644 --- a/packages/shared/config/constant.ts +++ b/packages/shared/config/constant.ts @@ -197,12 +197,6 @@ export enum FeedUrl { GITHUB_LATEST = 'https://github.com/CherryHQ/cherry-studio/releases/latest/download' } -export const tesseractLangs = ['chi_sim', 'chi_tra', 'eng'] -export enum TesseractLangsDownloadUrl { - CN = 'https://gitcode.com/beyondkmp/tessdata/releases/download/4.1.0/', - GLOBAL = 'https://github.com/tesseract-ocr/tessdata/raw/main/' -} - export enum UpgradeChannel { LATEST = 'latest', // 最新稳定版本 RC = 'rc', // 公测版本 diff --git a/src/main/services/ocr/tesseract/TesseractService.ts b/src/main/services/ocr/tesseract/TesseractService.ts index 2472f02fba..06f460dfea 100644 --- a/src/main/services/ocr/tesseract/TesseractService.ts +++ b/src/main/services/ocr/tesseract/TesseractService.ts @@ -1,6 +1,6 @@ import { loggerService } from '@logger' import { getIpCountry } from '@main/utils/ipService' -import { MB, TesseractLangsDownloadUrl } from '@shared/config/constant' +import { MB } from '@shared/config/constant' import { FileMetadata, ImageFileMetadata, isImageFile, OcrResult } from '@types' import { app } from 'electron' import fs from 'fs' @@ -114,13 +114,21 @@ const logger = loggerService.withContext('TesseractService') // 'yi-us': 'yid' // } +// config +const MB_SIZE_THRESHOLD = 50 +const tesseractLangs = ['chi_sim', 'chi_tra', 'eng'] +enum TesseractLangsDownloadUrl { + CN = 'https://gitcode.com/beyondkmp/tessdata/releases/download/4.1.0/', + GLOBAL = 'https://github.com/tesseract-ocr/tessdata/raw/main/' +} + export class TesseractService { private worker: Tesseract.Worker | null = null async getWorker(): Promise { if (!this.worker) { // for now, only support limited languages - this.worker = await createWorker(['chi_sim', 'chi_tra', 'eng'], undefined, { + this.worker = await createWorker(tesseractLangs, undefined, { langPath: await this._getLangPath(), cachePath: await this._getCacheDir(), gzip: false, @@ -133,8 +141,8 @@ export class TesseractService { async imageOcr(file: ImageFileMetadata): Promise { const worker = await this.getWorker() const stat = await fs.promises.stat(file.path) - if (stat.size > 50 * MB) { - throw new Error('This image is too large (max 50MB)') + if (stat.size > MB_SIZE_THRESHOLD * MB) { + throw new Error(`This image is too large (max ${MB_SIZE_THRESHOLD}MB)`) } const buffer = await fs.promises.readFile(file.path) const result = await worker.recognize(buffer) From f3da4a6e36d7a9e908dee87365ccc9e0f4ddcd55 Mon Sep 17 00:00:00 2001 From: icarus Date: Sat, 23 Aug 2025 13:45:21 +0800 Subject: [PATCH 3/3] =?UTF-8?q?refactor(ocr):=20=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=20SupportedOcrFile=20=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=20FileMetadata?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 更新 OCR 服务及其 Tesseract 实现,使用 SupportedOcrFile 类型替代原有的 FileMetadata 类型,以提高类型安全性和一致性。同时在 OcrService 中添加重复注册的警告日志。 --- src/main/services/ocr/OcrService.ts | 10 ++++++++-- src/main/services/ocr/tesseract/TesseractService.ts | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/services/ocr/OcrService.ts b/src/main/services/ocr/OcrService.ts index d709115b9c..73907574b2 100644 --- a/src/main/services/ocr/OcrService.ts +++ b/src/main/services/ocr/OcrService.ts @@ -1,13 +1,19 @@ -import { BuiltinOcrProviderIds, FileMetadata, OcrProvider, OcrResult, SupportedOcrFile } from '@types' +import { loggerService } from '@logger' +import { BuiltinOcrProviderIds, OcrProvider, OcrResult, SupportedOcrFile } from '@types' import { tesseractService } from './tesseract/TesseractService' -type OcrHandler = (file: FileMetadata) => Promise +type OcrHandler = (file: SupportedOcrFile) => Promise + +const logger = loggerService.withContext('OcrService') export class OcrService { private registry: Map = new Map() register(providerId: string, handler: OcrHandler): void { + if (this.registry.has(providerId)) { + logger.warn(`Provider ${providerId} has existing handler. Overwrited.`) + } this.registry.set(providerId, handler) } diff --git a/src/main/services/ocr/tesseract/TesseractService.ts b/src/main/services/ocr/tesseract/TesseractService.ts index 06f460dfea..77225d4afe 100644 --- a/src/main/services/ocr/tesseract/TesseractService.ts +++ b/src/main/services/ocr/tesseract/TesseractService.ts @@ -1,7 +1,7 @@ import { loggerService } from '@logger' import { getIpCountry } from '@main/utils/ipService' import { MB } from '@shared/config/constant' -import { FileMetadata, ImageFileMetadata, isImageFile, OcrResult } from '@types' +import { ImageFileMetadata, isImageFile, OcrResult, SupportedOcrFile } from '@types' import { app } from 'electron' import fs from 'fs' import path from 'path' @@ -149,7 +149,7 @@ export class TesseractService { return { text: result.data.text } } - async ocr(file: FileMetadata): Promise { + async ocr(file: SupportedOcrFile): Promise { if (!isImageFile(file)) { throw new Error('Only image files are supported currently') }