refactor: Improve linux build for system-ocr (#9775)

* refactor(ocr): streamline OCR service registration and improve image preprocessing

- Simplified the registration of the system OCR service by removing the conditional check for Linux.
- Updated SystemOcrService to directly import necessary modules, enhancing clarity.
- Refactored image preprocessing to use a static import of the 'sharp' library for better performance.

* add patch for system-ocr

* add patch

* add patch again

* add patch

* delete setting

* delete i18n

* lint error

* add isLinux

* Revert "delete i18n"

This reverts commit 173e65bbd0.

* Revert "delete setting"

This reverts commit de39c76f83.

* fix: add system check for error message

---------

Co-authored-by: icarus <eurfelux@gmail.com>
This commit is contained in:
beyondkmp 2025-09-02 12:59:14 +08:00 committed by GitHub
parent 001253b32d
commit 5ce7261678
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 61 additions and 17 deletions

View File

@ -0,0 +1,30 @@
diff --git a/index.js b/index.js
index dc071739e79876dff88e1be06a9168e294222d13..b9df7525c62bdf777e89e732e1b0c81f84d872f2 100644
--- a/index.js
+++ b/index.js
@@ -380,7 +380,7 @@ if (!nativeBinding || process.env.NAPI_RS_FORCE_WASI) {
}
}
-if (!nativeBinding) {
+if (!nativeBinding && process.platform !== 'linux') {
if (loadErrors.length > 0) {
throw new Error(
`Cannot find native binding. ` +
@@ -392,6 +392,13 @@ if (!nativeBinding) {
throw new Error(`Failed to load native binding`)
}
-module.exports = nativeBinding
-module.exports.OcrAccuracy = nativeBinding.OcrAccuracy
-module.exports.recognize = nativeBinding.recognize
+if (process.platform === 'linux') {
+ module.exports = {OcrAccuracy: {
+ Fast: 0,
+ Accurate: 1
+ }, recognize: () => Promise.resolve({text: '', confidence: 1.0})}
+}else{
+ module.exports = nativeBinding
+ module.exports.OcrAccuracy = nativeBinding.OcrAccuracy
+ module.exports.recognize = nativeBinding.recognize
+}

View File

@ -72,7 +72,7 @@
"dependencies": { "dependencies": {
"@libsql/client": "0.14.0", "@libsql/client": "0.14.0",
"@libsql/win32-x64-msvc": "^0.4.7", "@libsql/win32-x64-msvc": "^0.4.7",
"@napi-rs/system-ocr": "^1.0.2", "@napi-rs/system-ocr": "patch:@napi-rs/system-ocr@npm%3A1.0.2#~/.yarn/patches/@napi-rs-system-ocr-npm-1.0.2-59e7a78e8b.patch",
"@strongtz/win32-arm64-msvc": "^0.4.7", "@strongtz/win32-arm64-msvc": "^0.4.7",
"graceful-fs": "^4.2.11", "graceful-fs": "^4.2.11",
"jsdom": "26.1.0", "jsdom": "26.1.0",

View File

@ -7,15 +7,12 @@ const allArm64 = {
'@img/sharp-darwin-arm64': '0.34.3', '@img/sharp-darwin-arm64': '0.34.3',
'@img/sharp-win32-arm64': '0.34.3', '@img/sharp-win32-arm64': '0.34.3',
'@img/sharp-linux-arm64': '0.34.3', '@img/sharp-linux-arm64': '0.34.3',
'@img/sharp-linuxmusl-arm64': '0.34.3',
'@img/sharp-libvips-darwin-arm64': '1.2.0', '@img/sharp-libvips-darwin-arm64': '1.2.0',
'@img/sharp-libvips-linux-arm64': '1.2.0', '@img/sharp-libvips-linux-arm64': '1.2.0',
'@img/sharp-libvips-linuxmusl-arm64': '1.2.0',
'@libsql/darwin-arm64': '0.4.7', '@libsql/darwin-arm64': '0.4.7',
'@libsql/linux-arm64-gnu': '0.4.7', '@libsql/linux-arm64-gnu': '0.4.7',
'@libsql/linux-arm64-musl': '0.4.7',
'@strongtz/win32-arm64-msvc': '0.4.7', '@strongtz/win32-arm64-msvc': '0.4.7',
'@napi-rs/system-ocr-darwin-arm64': '1.0.2', '@napi-rs/system-ocr-darwin-arm64': '1.0.2',
@ -25,16 +22,13 @@ const allArm64 = {
const allX64 = { const allX64 = {
'@img/sharp-darwin-x64': '0.34.3', '@img/sharp-darwin-x64': '0.34.3',
'@img/sharp-linux-x64': '0.34.3', '@img/sharp-linux-x64': '0.34.3',
'@img/sharp-linuxmusl-x64': '0.34.3',
'@img/sharp-win32-x64': '0.34.3', '@img/sharp-win32-x64': '0.34.3',
'@img/sharp-libvips-darwin-x64': '1.2.0', '@img/sharp-libvips-darwin-x64': '1.2.0',
'@img/sharp-libvips-linux-x64': '1.2.0', '@img/sharp-libvips-linux-x64': '1.2.0',
'@img/sharp-libvips-linuxmusl-x64': '1.2.0',
'@libsql/darwin-x64': '0.4.7', '@libsql/darwin-x64': '0.4.7',
'@libsql/linux-x64-gnu': '0.4.7', '@libsql/linux-x64-gnu': '0.4.7',
'@libsql/linux-x64-musl': '0.4.7',
'@libsql/win32-x64-msvc': '0.4.7', '@libsql/win32-x64-msvc': '0.4.7',
'@napi-rs/system-ocr-darwin-x64': '1.0.2', '@napi-rs/system-ocr-darwin-x64': '1.0.2',

View File

@ -2,6 +2,7 @@ import { loggerService } from '@logger'
import { isLinux } from '@main/constant' import { isLinux } from '@main/constant'
import { BuiltinOcrProviderIds, OcrHandler, OcrProvider, OcrResult, SupportedOcrFile } from '@types' import { BuiltinOcrProviderIds, OcrHandler, OcrProvider, OcrResult, SupportedOcrFile } from '@types'
import { systemOcrService } from './builtin/SystemOcrService'
import { tesseractService } from './builtin/TesseractService' import { tesseractService } from './builtin/TesseractService'
const logger = loggerService.withContext('OcrService') const logger = loggerService.withContext('OcrService')
@ -34,7 +35,4 @@ export const ocrService = new OcrService()
// Register built-in providers // Register built-in providers
ocrService.register(BuiltinOcrProviderIds.tesseract, tesseractService.ocr.bind(tesseractService)) ocrService.register(BuiltinOcrProviderIds.tesseract, tesseractService.ocr.bind(tesseractService))
if (!isLinux) { !isLinux && ocrService.register(BuiltinOcrProviderIds.system, systemOcrService.ocr.bind(systemOcrService))
const { systemOcrService } = require('./builtin/SystemOcrService')
ocrService.register(BuiltinOcrProviderIds.system, systemOcrService.ocr.bind(systemOcrService))
}

View File

@ -1,5 +1,6 @@
import { isLinux, isWin } from '@main/constant' import { isLinux, isWin } from '@main/constant'
import { loadOcrImage } from '@main/utils/ocr' import { loadOcrImage } from '@main/utils/ocr'
import { OcrAccuracy, recognize } from '@napi-rs/system-ocr'
import { import {
ImageFileMetadata, ImageFileMetadata,
isImageFileMetadata as isImageFileMetadata, isImageFileMetadata as isImageFileMetadata,
@ -20,8 +21,6 @@ export class SystemOcrService extends OcrBaseService {
if (isLinux) { if (isLinux) {
return { text: '' } return { text: '' }
} }
const { OcrAccuracy, recognize } = require('@napi-rs/system-ocr')
const buffer = await loadOcrImage(file) const buffer = await loadOcrImage(file)
const langs = isWin ? options?.langs : undefined const langs = isWin ? options?.langs : undefined
const result = await recognize(buffer, OcrAccuracy.Accurate, langs) const result = await recognize(buffer, OcrAccuracy.Accurate, langs)

View File

@ -1,8 +1,8 @@
import { ImageFileMetadata } from '@types' import { ImageFileMetadata } from '@types'
import { readFile } from 'fs/promises' import { readFile } from 'fs/promises'
import sharp from 'sharp'
const preprocessImage = async (buffer: Buffer): Promise<Buffer> => { const preprocessImage = async (buffer: Buffer): Promise<Buffer> => {
const sharp = require('sharp')
return sharp(buffer) return sharp(buffer)
.grayscale() // 转为灰度 .grayscale() // 转为灰度
.normalize() .normalize()

View File

@ -47,12 +47,14 @@ const OcrImageSettings = ({ setProvider }: Props) => {
})) }))
}, [getOcrProviderName, imageProviders, platformSupport]) }, [getOcrProviderName, imageProviders, platformSupport])
const isSystem = imageProvider.id === BuiltinOcrProviderIds.system
return ( return (
<> <>
<SettingRow> <SettingRow>
<SettingRowTitle>{t('settings.tool.ocr.image_provider')}</SettingRowTitle> <SettingRowTitle>{t('settings.tool.ocr.image_provider')}</SettingRowTitle>
<div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}> <div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>
{!platformSupport && <ErrorTag message={t('settings.tool.ocr.error.not_system')} />} {!platformSupport && isSystem && <ErrorTag message={t('settings.tool.ocr.error.not_system')} />}
<Select <Select
value={imageProvider.id} value={imageProvider.id}
style={{ width: '200px' }} style={{ width: '200px' }}

View File

@ -4761,7 +4761,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@napi-rs/system-ocr@npm:^1.0.2": "@napi-rs/system-ocr@npm:1.0.2":
version: 1.0.2 version: 1.0.2
resolution: "@napi-rs/system-ocr@npm:1.0.2" resolution: "@napi-rs/system-ocr@npm:1.0.2"
dependencies: dependencies:
@ -4782,6 +4782,27 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@napi-rs/system-ocr@patch:@napi-rs/system-ocr@npm%3A1.0.2#~/.yarn/patches/@napi-rs-system-ocr-npm-1.0.2-59e7a78e8b.patch":
version: 1.0.2
resolution: "@napi-rs/system-ocr@patch:@napi-rs/system-ocr@npm%3A1.0.2#~/.yarn/patches/@napi-rs-system-ocr-npm-1.0.2-59e7a78e8b.patch::version=1.0.2&hash=407396"
dependencies:
"@napi-rs/system-ocr-darwin-arm64": "npm:1.0.2"
"@napi-rs/system-ocr-darwin-x64": "npm:1.0.2"
"@napi-rs/system-ocr-win32-arm64-msvc": "npm:1.0.2"
"@napi-rs/system-ocr-win32-x64-msvc": "npm:1.0.2"
dependenciesMeta:
"@napi-rs/system-ocr-darwin-arm64":
optional: true
"@napi-rs/system-ocr-darwin-x64":
optional: true
"@napi-rs/system-ocr-win32-arm64-msvc":
optional: true
"@napi-rs/system-ocr-win32-x64-msvc":
optional: true
checksum: 10c0/c1e336b3d506dd771c72b1bddc94e4a9ddeae5292222a7485d66dd0c11eed5d2a37cc7ea338f229e7d4abad276966658bdb4a2b322c9d6a0349dad6e65fcea51
languageName: node
linkType: hard
"@napi-rs/wasm-runtime@npm:^0.2.4": "@napi-rs/wasm-runtime@npm:^0.2.4":
version: 0.2.12 version: 0.2.12
resolution: "@napi-rs/wasm-runtime@npm:0.2.12" resolution: "@napi-rs/wasm-runtime@npm:0.2.12"
@ -9406,7 +9427,7 @@ __metadata:
"@mistralai/mistralai": "npm:^1.7.5" "@mistralai/mistralai": "npm:^1.7.5"
"@modelcontextprotocol/sdk": "npm:^1.17.0" "@modelcontextprotocol/sdk": "npm:^1.17.0"
"@mozilla/readability": "npm:^0.6.0" "@mozilla/readability": "npm:^0.6.0"
"@napi-rs/system-ocr": "npm:^1.0.2" "@napi-rs/system-ocr": "patch:@napi-rs/system-ocr@npm%3A1.0.2#~/.yarn/patches/@napi-rs-system-ocr-npm-1.0.2-59e7a78e8b.patch"
"@notionhq/client": "npm:^2.2.15" "@notionhq/client": "npm:^2.2.15"
"@opentelemetry/api": "npm:^1.9.0" "@opentelemetry/api": "npm:^1.9.0"
"@opentelemetry/core": "npm:2.0.0" "@opentelemetry/core": "npm:2.0.0"