fix: EasyOCR启动异常+超时保护+消息搅和隔离
1. 修复负冷却时间bug:启动失败时若未设置冷却,现在设置30s冷却 2. EasyOCR worker添加超时保护:readtext()使用concurrent.futures包装,30s超时 3. Windows OCR消息搅和隔离:EasyOCR超时+Windows OCR多时间戳→返回空结果 4. 添加easyocr_worker_state.json到.gitignore
This commit is contained in:
@@ -72,3 +72,4 @@ test_*.txt
|
||||
_radical_*.txt
|
||||
unicode_radicals.md.bak
|
||||
easyocr_worker_state.json
|
||||
easyocr_worker_state.json
|
||||
|
||||
+21
-3
@@ -286,8 +286,10 @@ def _init_reader():
|
||||
return reader
|
||||
|
||||
|
||||
def _process_image(img_b64: str, reader) -> str:
|
||||
"""解码 base64 图片 → EasyOCR 识别 → 返回空格拼接文本。"""
|
||||
def _process_image(img_b64: str, reader, timeout: float = 30.0) -> str:
|
||||
"""解码 base64 图片 → EasyOCR 识别 → 返回空格拼接文本。
|
||||
timeout: 单张图片OCR超时秒数,防止GPU/CPU推理卡死。
|
||||
"""
|
||||
if reader is None:
|
||||
return ""
|
||||
raw = base64.b64decode(img_b64)
|
||||
@@ -296,7 +298,23 @@ def _process_image(img_b64: str, reader) -> str:
|
||||
if img.mode != "RGBA":
|
||||
img = img.convert("RGBA")
|
||||
img_np = np.array(img)
|
||||
results = reader.readtext(img_np)
|
||||
|
||||
# ⭐ 超时保护:用 concurrent.futures 包装 readtext,防止GPU推理卡死
|
||||
from concurrent.futures import ThreadPoolExecutor, TimeoutError as FuturesTimeoutError
|
||||
with ThreadPoolExecutor(max_workers=1) as executor:
|
||||
future = executor.submit(reader.readtext, img_np)
|
||||
try:
|
||||
results = future.result(timeout=timeout)
|
||||
except FuturesTimeoutError:
|
||||
sys.stderr.write(f"[easyocr_worker] readtext 超时({timeout}s),放弃本次OCR\n")
|
||||
sys.stderr.flush()
|
||||
_write_crash_log(f"{datetime.now()} [easyocr_worker] readtext 超时({timeout}s)")
|
||||
return ""
|
||||
except Exception as e:
|
||||
sys.stderr.write(f"[easyocr_worker] readtext 异常: {e}\n")
|
||||
sys.stderr.flush()
|
||||
raise
|
||||
|
||||
return "\n".join([r[1] for r in results]).strip()
|
||||
|
||||
|
||||
|
||||
+12
@@ -2030,6 +2030,9 @@ class MessageMonitor:
|
||||
# 重置计数器(冷却后重试重新计数)
|
||||
self._easyocr_consecutive_startup_failures = 0
|
||||
else:
|
||||
# ⭐ 短冷却:未达阈值时也设30s冷却,避免反复启动失败刷屏
|
||||
if self._easyocr_retry_until <= time.time():
|
||||
self._easyocr_retry_until = time.time() + 30
|
||||
logger.debug(f"[ocr] EasyOCR 第{self._easyocr_consecutive_startup_failures}次启动失败,"
|
||||
f"冷却({int(self._easyocr_retry_until - time.time())}s)")
|
||||
return None
|
||||
@@ -2421,6 +2424,15 @@ class MessageMonitor:
|
||||
wt = win_text[0]
|
||||
et = easy_text[0]
|
||||
|
||||
# ⭐ EasyOCR超时+Windows OCR混合消息检测:当EasyOCR超时且Windows OCR结果包含
|
||||
# 多个时间戳(表明是多条消息混合),返回空结果,避免消息搅和
|
||||
if not et and wt:
|
||||
timestamps = re.findall(r'\d{1,2}:\d{1,2}', wt)
|
||||
if len(timestamps) >= 2:
|
||||
logger.warning(f"[{platform}] EasyOCR超时+Windows OCR检测到{len(timestamps)}个时间戳"
|
||||
f"({timestamps[:3]}...),疑似消息混合,跳过本轮避免搅和")
|
||||
return ("", "")
|
||||
|
||||
# 日志(原始输出逐行记录,用於長期對比兩引擎能力)
|
||||
if wt:
|
||||
for i, l in enumerate(wt.split('\n')):
|
||||
|
||||
Reference in New Issue
Block a user