128 lines
2.7 KiB
TypeScript
128 lines
2.7 KiB
TypeScript
|
|
/**
|
||
|
|
* OCR Provider Base Interface
|
||
|
|
* OCR 提供商基础接口
|
||
|
|
*/
|
||
|
|
|
||
|
|
import { resolveImagePath } from '../../lib/path';
|
||
|
|
|
||
|
|
export interface OCRRecognitionResult {
|
||
|
|
/** 识别的文本内容 */
|
||
|
|
text: string;
|
||
|
|
/** 置信度 (0-1) */
|
||
|
|
confidence: number;
|
||
|
|
/** 处理耗时 (毫秒) */
|
||
|
|
duration?: number;
|
||
|
|
/** 额外信息 */
|
||
|
|
extra?: Record<string, unknown>;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface OCRProviderConfig {
|
||
|
|
/** 超时时间 (毫秒) */
|
||
|
|
timeout?: number;
|
||
|
|
/** 语言代码 (chi_sim, eng 等) */
|
||
|
|
language?: string;
|
||
|
|
/** 额外配置 */
|
||
|
|
extras?: Record<string, unknown>;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface IImageSource {
|
||
|
|
/** 图片本地路径 */
|
||
|
|
path?: string;
|
||
|
|
/** 图片 Buffer */
|
||
|
|
buffer?: Buffer;
|
||
|
|
/** 图片 Base64 */
|
||
|
|
base64?: string;
|
||
|
|
/** 图片 URL */
|
||
|
|
url?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* OCR Provider 抽象基类
|
||
|
|
* 所有 OCR 提供商都需要实现此接口
|
||
|
|
*/
|
||
|
|
export abstract class BaseOCRProvider {
|
||
|
|
protected config: OCRProviderConfig;
|
||
|
|
|
||
|
|
constructor(config: OCRProviderConfig = {}) {
|
||
|
|
this.config = {
|
||
|
|
timeout: 30000,
|
||
|
|
language: 'chi_sim+eng',
|
||
|
|
...config,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Provider 名称
|
||
|
|
*/
|
||
|
|
abstract getName(): string;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Provider 类型 (local | cloud)
|
||
|
|
*/
|
||
|
|
abstract getType(): 'local' | 'cloud';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 检查 Provider 是否可用
|
||
|
|
*/
|
||
|
|
abstract isAvailable(): Promise<boolean> | boolean;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 执行 OCR 识别
|
||
|
|
* @param source 图片来源 (路径/Buffer/Base64/URL)
|
||
|
|
* @param options 可选配置
|
||
|
|
*/
|
||
|
|
abstract recognize(
|
||
|
|
source: IImageSource,
|
||
|
|
options?: OCRProviderConfig
|
||
|
|
): Promise<OCRRecognitionResult>;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 批量识别
|
||
|
|
*/
|
||
|
|
async batchRecognize(
|
||
|
|
sources: IImageSource[],
|
||
|
|
options?: OCRProviderConfig
|
||
|
|
): Promise<OCRRecognitionResult[]> {
|
||
|
|
const results: OCRRecognitionResult[] = [];
|
||
|
|
|
||
|
|
for (const source of sources) {
|
||
|
|
try {
|
||
|
|
const result = await this.recognize(source, options);
|
||
|
|
results.push(result);
|
||
|
|
} catch (error) {
|
||
|
|
results.push({
|
||
|
|
text: '',
|
||
|
|
confidence: 0,
|
||
|
|
duration: 0,
|
||
|
|
extra: { error: error instanceof Error ? error.message : String(error) },
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return results;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 获取推荐配置
|
||
|
|
*/
|
||
|
|
getRecommendations(): {
|
||
|
|
maxImageSize?: number;
|
||
|
|
supportedFormats?: string[];
|
||
|
|
notes?: string;
|
||
|
|
} {
|
||
|
|
return {
|
||
|
|
maxImageSize: 10 * 1024 * 1024, // 10MB
|
||
|
|
supportedFormats: ['jpg', 'jpeg', 'png', 'webp', 'bmp', 'gif'],
|
||
|
|
notes: '建议图片分辨率不低于 300dpi',
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 解析图片路径
|
||
|
|
* 将数据库路径转换为绝对路径
|
||
|
|
*/
|
||
|
|
protected resolveImagePath(imagePath: string): string {
|
||
|
|
return resolveImagePath(imagePath);
|
||
|
|
}
|
||
|
|
}
|