use std::sync::Arc;
use ocrs::{OcrEngine, OcrEngineParams};
use rten::Model;
use crate::error::{Error, Result};
pub(crate) type EngineResult = std::result::Result<Arc<OcrEngine>, String>;
pub(super) fn load_engine_blocking(
detection_path: std::path::PathBuf,
recognition_path: std::path::PathBuf,
) -> Result<Arc<OcrEngine>> {
if cfg!(debug_assertions) {
tracing::warn!(
"visual: waydriver was compiled in a dev/debug profile — rten OCR inference \
is ~30x slower unoptimized (minutes per full-frame pass instead of seconds), \
and the 120s visual auto-wait default assumes an optimized build. If OCR is \
slow, add this to your WORKSPACE ROOT Cargo.toml (optimizes dependencies \
only; your own code stays fast to build):\n\n\
[profile.dev.package.\"*\"]\n\
opt-level = 3\n\n\
Already applied an override like that? Then OCR is fast and this warning is \
a false positive (opt-level overrides don't clear cfg(debug_assertions)) — \
ignore it."
);
}
let started = std::time::Instant::now();
tracing::info!(
detection = %detection_path.display(),
recognition = %recognition_path.display(),
"visual: loading ocrs engine"
);
let detection_model = Model::load_file(&detection_path).map_err(|e| {
Error::visual(format!(
"failed to load detection model {}: {e}",
detection_path.display()
))
})?;
let recognition_model = Model::load_file(&recognition_path).map_err(|e| {
Error::visual(format!(
"failed to load recognition model {}: {e}",
recognition_path.display()
))
})?;
let engine = OcrEngine::new(OcrEngineParams {
detection_model: Some(detection_model),
recognition_model: Some(recognition_model),
..Default::default()
})
.map_err(|e| Error::visual(format!("failed to construct ocrs engine: {e}")))?;
tracing::info!(
elapsed_ms = started.elapsed().as_millis(),
"visual: ocrs engine ready"
);
Ok(Arc::new(engine))
}
pub(crate) async fn ensure_engine() -> EngineResult {
tokio::task::spawn_blocking(move || -> Result<Arc<OcrEngine>> {
let (det, rec) = super::models::ensure_models()?;
load_engine_blocking(det, rec)
})
.await
.map_err(|join_err| format!("ocrs engine init task panicked: {join_err}"))?
.map_err(|e| e.to_string())
}