Hãy xây dựng một ứng dụng desktop Windows hoàn chỉnh có giao diện đồ họa cho OCRmyPDF, giúp người dùng biến PDF scan dạng ảnh thành PDF có thể:
- select text;
- copy/paste;
- Ctrl+F;
- search;
- giữ hình ảnh và bố cục PDF gốc;
- OCR tiếng Việt, tiếng Anh và nhiều ngôn ngữ khác.
Tên project/repository tạm thời:
ocrmypdf-gui
Tên app hiển thị:
OCRmyPDF GUI
Đây phải là một ứng dụng Windows thực sự có thể dùng hàng ngày, không phải demo UI.
Ưu tiên:
Dễ dùng
Ổn định
Không treo GUI
Hiển thị tiến trình rõ ràng
Xử lý lỗi tốt
Batch processing
Không bắt người dùng phải nhớ command line
Sử dụng:
Python 3.14
PySide6
OCRmyPDF
Tesseract OCR
pikepdf
PyInstaller
Có thể thêm dependency nhỏ nếu thực sự cần.
Không sử dụng Electron.
Không viết lại OCR engine.
OCRmyPDF phải là backend OCR chính.
Thiết kế theo cấu trúc:
┌──────────────────────────────┐
│ PySide6 GUI │
│ │
│ File Queue │
│ OCR Settings │
│ Progress │
│ Logs │
└──────────────┬───────────────┘
│
│ IPC
▼
┌──────────────────────────────┐
│ OCR Worker │
│ │
│ OCRmyPDF Python API │
│ OcrOptions │
│ Progress Reporter │
└──────────────┬───────────────┘
│
┌───────┴────────┐
▼ ▼
Tesseract PDF backend
Không chạy OCR trực tiếp trên GUI thread.
OCR phải chạy trong process riêng.
Nếu OCR worker crash thì GUI không được crash theo.
OCRmyPDF hiện có API Python chính thức và tài liệu cũng đề xuất child process cho ứng dụng tích hợp.
Đầu tiên chưa cần làm UI quá đẹp. Làm backend thật chắc trước.
Khi app mở lần đầu, tự kiểm tra:
Python runtime
OCRmyPDF
Tesseract
Ghostscript nếu pipeline cần
Tesseract tessdata
Kiểm tra version của:
OCRmyPDF
Tesseract
Ghostscript
Hiển thị trạng thái:
✓ OCRmyPDF 17.x
✓ Tesseract 5.x
✓ Ghostscript 10.x
✓ English language
✓ Vietnamese language
hoặc:
✕ Vietnamese language data missing
Không được chỉ hiện:
Process exited with code 3
mà phải chuyển thành lỗi dễ hiểu.
Ví dụ:
Vietnamese OCR is not installed.
Missing Tesseract language:
vie
Install Vietnamese language data to use this option.
Chạy hoặc lấy thông tin tương đương:
tesseract --list-langs
Parse thành danh sách.
Ví dụ:
eng
vie
chi_sim
chi_tra
jpn
kor
fra
deu
...
GUI chỉ cho phép chọn language đã cài.
Các lựa chọn mặc định:
Vietnamese
English
Vietnamese + English
Map:
Vietnamese → vie
English → eng
Vietnamese + English → vie+eng
Sau này cho phép chọn nhiều language.
OCRmyPDF hỗ trợ nhiều ngôn ngữ kết hợp như eng+fra, nhưng language data tương ứng phải có trong OCR engine.
Tạo riêng:
ocr_worker.py
Worker nhận một JSON job.
Ví dụ logic:
{
"input": "...",
"output": "...",
"languages": ["vie", "eng"],
"deskew": true,
"rotate_pages": true,
"pages": null,
"timeout": 180,
"mode": "skip"
}Sau đó chuyển thành OcrOptions.
Ưu tiên dùng:
from ocrmypdf import OcrOptionsthay vì ghép một command string khổng lồ.
Worker gửi event về GUI theo dạng có cấu trúc.
Ví dụ:
{"type":"started"}{
"type":"progress",
"current":51,
"total":382,
"stage":"OCR"
}{
"type":"warning",
"page":51,
"message":"Tesseract timeout"
}{
"type":"completed",
"output":"..."
}{
"type":"failed",
"message":"..."
}Không phụ thuộc hoàn toàn vào regex đọc progress bar terminal nếu có thể tránh.
Nghiên cứu custom ProgressBar plugin của OCRmyPDF để lấy progress một cách sạch.
Thiết kế giao diện như một desktop utility hiện đại, tối giản.
Không nhồi quá nhiều setting lên màn hình chính.
Layout:
┌───────────────────────────────────────────────────────────┐
│ OCRmyPDF GUI ⚙ Settings │
├───────────────────────────────────────────────────────────┤
│ │
│ Drop PDF files here │
│ │
│ or │
│ │
│ [ Choose Files ] │
│ │
├───────────────────────────────────────────────────────────┤
│ Files │
│ │
│ textbook.pdf Ready │
│ document.pdf Ready │
│ scan.pdf Ready │
│ │
├───────────────────────────────────────────────────────────┤
│ OCR Language │
│ [ Vietnamese + English ▼ ] │
│ │
│ Preset │
│ [ Standard ▼ ] │
│ │
│ ☑ Auto rotate │
│ ☑ Fix tilted pages │
│ │
│ [ Start OCR ] │
└───────────────────────────────────────────────────────────┘
Phải hỗ trợ:
1 PDF
nhiều PDF
folder
Khi kéo folder vào:
- tìm tất cả
.pdf; - hỏi có thêm toàn bộ vào queue không.
Không cho duplicate job nếu cùng input + output.
Mỗi file là một job.
Các trạng thái:
Waiting
Processing
Completed
Failed
Cancelled
Skipped
Mỗi row hiển thị:
filename
pages
size
status
progress
output location
Ví dụ:
Giáo trình.pdf
382 pages
84.2 MB
OCR 51 / 382
13%
Mặc định:
input.pdf
→
input (OCR).pdf
Nếu file tồn tại:
input (OCR 2).pdf
input (OCR 3).pdf
Không overwrite im lặng.
Có setting:
Output folder:
○ Same folder as input
○ Custom folder
Phần setting thường dùng:
Vietnamese
English
Vietnamese + English
Custom
Map tới chức năng:
rotate_pages
Map:
deskew
OCRmyPDF phân biệt rotate-pages cho orientation sai 90/180/270 độ và deskew cho scan chỉ bị nghiêng nhẹ.
Tạo dropdown:
OCR Mode
Options:
mode = skip
Dùng cho PDF có vài trang đã có text.
mode = redo
Thay OCR layer cũ.
mode = force
Rasterize rồi OCR lại.
Hiển thị tooltip giải thích.
OCRmyPDF v17 hiện gom các hành vi này vào --mode skip, redo, force; các flag cũ vẫn là alias.
Tạo ba preset dễ hiểu.
auto rotate OFF
deskew OFF
optimization low
Ưu tiên tốc độ.
Vietnamese + English
auto rotate ON
deskew ON
normal optimization
Default.
auto rotate ON
deskew ON
oversample
OCR timeout cao hơn
Không tự bật các filter có khả năng phá hình.
Đặc biệt không mặc định bật clean-final hoặc remove-background, vì OCRmyPDF cảnh báo các chức năng xử lý ảnh này có thể tạo artifact hoặc loại mất nội dung.
Đây là phần quan trọng nhất.
Trường hợp thực tế cần giải quyết là PDF hàng trăm trang có thể chạy bình thường tới một trang nào đó rồi rất lâu.
Khi OCR:
Giáo trình CNXHKH.pdf
OCR processing
██████████████░░░░░░░░░░░░░░░
Page 51 / 382
13%
Elapsed: 04:32
Estimated remaining: 28:14
Current stage:
Recognizing text
[ Cancel ]
Hiển thị:
Current page
Total pages
Percent
Current stage
Elapsed time
Estimated remaining
Average seconds/page
ETA nên là moving average, không lấy average toàn job một cách cứng nhắc.
Progress có thể hiển thị các stage như:
Analyzing PDF
Preprocessing
Detecting orientation
Deskewing
OCR
Generating PDF
Optimizing
Finalizing
Không để người dùng tưởng app treo khi OCR xong nhưng đang optimize.
Nếu một page chạy quá lâu:
Page 51 is taking longer than usual.
Nếu timeout:
OCR skipped on page 51 because it exceeded the configured timeout.
The original page will remain in the output PDF.
Expose setting:
Maximum OCR time per page
Default:
180 seconds
Options:
30 sec
60 sec
120 sec
180 sec
300 sec
Unlimited / advanced
OCRmyPDF có tesseract-timeout; trang bị skip bởi timeout sẽ không có OCR text tương ứng trong sidecar.
Đây là feature bắt buộc.
Cho phép:
All pages
hoặc:
Selected pages
Input:
1-50,52-100
hoặc:
3-end
OCRmyPDF hỗ trợ page list/range như 2,3,13-17 và token end.
Validate input ngay trong GUI.
Sai:
1--50
abc
52-20
thì báo trước khi chạy.
Thêm một UI thân thiện hơn:
Pages to exclude:
[ 51,124 ]
App tự convert thành page selection tương ứng.
Ví dụ file 200 trang:
exclude = 51
→
1-50,52-end
Rất hữu ích cho scan lỗi.
Nếu job fail:
OCR failed on page 51
hiện:
[ Retry ]
[ Retry without page 51 ]
[ Change settings ]
[ View log ]
Không bắt người dùng tự mở terminal.
Nút Cancel phải:
- gửi terminate signal cho worker;
- chờ graceful shutdown;
- nếu worker không thoát thì kill;
- cleanup temporary files;
- giữ GUI responsive;
- đánh dấu job
Cancelled.
Không để lại process Tesseract zombie nếu có thể tránh.
Không cần true pause giữa một PDF trong MVP.
Không giả vờ pause bằng cách suspend process tùy tiện.
Chỉ hỗ trợ:
Pause Queue
nghĩa là:
job hiện tại hoàn tất
→ không chạy job tiếp theo
Sau này mới nghiên cứu resume giữa file.
Cho phép queue:
Book 1.pdf
Book 2.pdf
Book 3.pdf
...
Book 50.pdf
Mặc định xử lý mỗi lúc một PDF để tránh ăn sạch RAM/CPU.
Advanced option:
Concurrent files:
1
Không khuyến khích >1.
OCRmyPDF bản thân có worker processes và tham số giới hạn jobs, vì vậy không nên vô tình tạo quá nhiều tầng parallelism.
Advanced:
CPU workers
Auto
1
2
4
8
Map đến:
jobs
Default:
Auto
Checkbox:
☐ Also export recognized text (.txt)
Output:
book (OCR).pdf
book (OCR).txt
OCRmyPDF hỗ trợ sidecar text song song với output PDF.
Advanced:
Output format
Auto
PDF
PDF/A
Default:
Auto
Không bắt user phổ thông phải hiểu PDF/A.
Setting:
PDF optimization
None
Standard
High
Maximum
Map:
0
1
2
3
Default:
Standard
OCRmyPDF hiện dùng optimization level 0–3, với 1 là mặc định.
Main screen chỉ hiện lỗi dễ hiểu.
Có nút:
View detailed log
Mở drawer/panel:
13:42:01 Loading PDF
13:42:04 Page 1 complete
...
13:46:20 Page 51 Tesseract timeout
...
Actions:
Copy log
Save log
Clear
Không spam terminal ngoài app.
Lưu lịch sử gần đây:
Input
Output
Date
Duration
Pages
Status
Settings
Ví dụ:
Giáo trình.pdf
Completed
382 pages
21m 42s
vie+eng
Cho phép:
Open output
Open folder
Run again
Remove from history
Lưu bằng JSON hoặc SQLite.
Nếu history bắt đầu phức tạp, dùng SQLite.
Lưu:
language
output folder
OCR mode
timeout
preset
jobs
output type
optimization
window size
theme
Dùng:
QSettings
hoặc config JSON nếu kiến trúc phù hợp hơn.
Lần đầu mở app:
Welcome to OCRmyPDF GUI
Checking OCR components...
Sau đó:
OCRmyPDF ✓
Tesseract ✓
English ✓
Vietnamese ✕
Nếu thiếu component:
Fix
Locate manually
Refresh
Không tự tải/chạy installer hệ thống mà không hỏi user.
Nếu thiếu vie:
Vietnamese language pack is missing.
Có:
[ Installation instructions ]
Hoặc nếu triển khai download tự động:
[ Install Vietnamese ]
Nhưng phải:
- tải từ nguồn chính thức;
- kiểm tra lỗi download;
- xử lý permission
Program Files; - không yêu cầu chạy toàn app bằng Administrator;
- nếu cần elevation thì chỉ elevate đúng helper operation.
Khi select một PDF, hiện:
382 pages
84.3 MB
Scanned PDF
No searchable text detected
Nếu có text:
Text already detected on some pages
Có thể dùng pikepdf/PDF inspection để lấy metadata.
Bắt buộc:
- không modify input file trừ khi user chủ động chọn overwrite;
- output trước tiên ghi vào temporary path;
- chỉ move/rename thành output chính khi OCR thành công;
- tránh file output corrupt khi app crash;
- xử lý path Unicode;
- xử lý tên tiếng Việt;
- xử lý dấu ngoặc;
- xử lý spaces;
- xử lý path rất dài trên Windows nếu có thể.
Test bắt buộc với:
Giáo trình CNXHKH (bản cũ).pdf
Không cần tray icon.
Đây là utility chạy khi cần.
Tạo build Windows:
OCRmyPDF-GUI.exe
Ưu tiên:
PyInstaller
Build đầu tiên nên dùng:
onedir
thay vì onefile để:
- startup nhanh hơn;
- debug dependency dễ hơn;
- tránh extraction mỗi lần chạy.
Khi project ổn định mới cân nhắc:
onefile
Cần phân biệt rõ:
Có thể bundle:
PySide6
Python runtime
GUI code
OCR integration code
Tesseract/Ghostscript có thể:
A. yêu cầu user cài
hoặc trong tương lai:
B. tạo installer đầy đủ
V1 ưu tiên A.
App phải tự detect và hướng dẫn user nếu thiếu.
Không dành quá nhiều thời gian ngay từ đầu để tạo một installer khổng lồ chứa toàn bộ OCR stack.
Sắp xếp code sạch.
Ví dụ:
ocrmypdf-gui/
│
├── app/
│ ├── main.py
│ │
│ ├── ui/
│ │ ├── main_window.py
│ │ ├── drop_zone.py
│ │ ├── job_widget.py
│ │ ├── progress_widget.py
│ │ ├── settings_dialog.py
│ │ └── log_panel.py
│ │
│ ├── core/
│ │ ├── job.py
│ │ ├── queue_manager.py
│ │ ├── ocr_worker.py
│ │ ├── ocr_options.py
│ │ ├── progress.py
│ │ └── page_ranges.py
│ │
│ ├── services/
│ │ ├── dependency_checker.py
│ │ ├── tesseract_service.py
│ │ ├── pdf_service.py
│ │ └── history_service.py
│ │
│ ├── models/
│ │ ├── job.py
│ │ └── settings.py
│ │
│ ├── utils/
│ │ ├── paths.py
│ │ ├── logging.py
│ │ └── exceptions.py
│ │
│ └── resources/
│
├── tests/
│ ├── test_page_ranges.py
│ ├── test_output_paths.py
│ ├── test_dependencies.py
│ ├── test_jobs.py
│ └── test_ocr_options.py
│
├── scripts/
│ └── build_windows.ps1
│
├── pyproject.toml
├── requirements.txt
├── README.md
├── LICENSE
└── .gitignore
Có thể thay đổi structure nếu Codex tìm được architecture hợp lý hơn, nhưng không được nhét toàn bộ app vào một file main.py.
UI phải responsive.
Không bao giờ freeze khi OCR.
Main UI chỉ để các option thường dùng:
Files
Language
Preset
Rotate
Deskew
Output
Start
Các option còn lại đưa vào:
Advanced Settings
Tooltips phải giải thích bằng ngôn ngữ bình thường.
Ví dụ không chỉ ghi:
--deskew
mà ghi:
Fix tilted pages
Straightens pages that were scanned slightly crooked.
Tạo error mapping.
Ví dụ:
MissingDependencyError
→
Tesseract OCR could not be found.
PriorOcrFoundError
→
This PDF already contains text.
Choose Skip existing text, Redo OCR or Force OCR.
OutputFileAccessError
→
The output PDF is currently open in another application.
Close it and try again.
TesseractConfigError
→
The selected OCR language is not installed.
Không hiển thị Python traceback cho user bình thường.
Traceback chỉ vào detailed log.
OCRmyPDF cung cấp các exception/exit codes riêng như MissingDependencyError, PriorOcrFoundError, OutputFileAccessError và TesseractConfigError, nên hãy map chúng thành thông báo UI.
Viết unit test cho:
page range parser
exclude page conversion
output filename generation
duplicate filenames
settings serialization
OCR options conversion
dependency detection
job state transitions
Test integration:
PDF 10 trang scan bình thường.
Expected:
10 pages completed
searchable output
PDF tiếng Việt.
vie
vie+eng
Page range:
1-5,7-end
File có text sẵn.
Test:
skip
redo
force
Tesseract thiếu vie.
GUI phải báo rõ.
Output PDF đang mở.
Không crash.
Cancel OCR giữa chừng.
Worker phải kết thúc.
GUI vẫn dùng được.
PDF vài trăm trang.
Không leak RAM nghiêm trọng.
GUI không freeze.
Project chỉ được coi là hoàn thành khi flow này hoạt động:
Open app
↓
Drag PDF
↓
App detect số trang
↓
Select Vietnamese + English
↓
Enable Auto Rotate
↓
Enable Deskew
↓
Start OCR
↓
Progress hiển thị từng giai đoạn
↓
Có thể Cancel
↓
OCR hoàn thành
↓
Output:
filename (OCR).pdf
↓
Click Open PDF
↓
Text có thể Ctrl+F / select / copy
Ngoài ra:
không terminal window
không GUI freeze
không mất input file
không overwrite im lặng
không để lại file tạm sau khi hoàn thành hoặc hủy
path tiếng Việt hoạt động
batch queue hoạt động
thiếu language pack được báo rõ
worker crash không làm GUI crash
Triển khai theo thứ tự sau:
1. Khởi tạo project và dependency
2. Dependency checker
3. Tesseract language detection
4. PDF metadata inspection
5. Page range parser
6. Output path generator
7. OCR options model
8. OCR worker process
9. Structured IPC events
10. Queue manager
11. GUI main window
12. Drag & drop và file queue
13. Progress screen
14. Cancel và queue pause
15. Error mapping và detailed logs
16. Presets và settings persistence
17. History
18. Batch processing
19. Unit tests và integration tests
20. PyInstaller onedir build
21. Windows smoke test
Mỗi giai đoạn phải chạy được và được kiểm thử trước khi chuyển sang giai đoạn kế tiếp.
- Trước khi viết code, kiểm tra môi trường Python và các dependency hiện có.
- Đọc tài liệu/API version đang cài thay vì đoán tên tham số.
- Không tạo UI giả nếu backend chưa chạy thật.
- Không block GUI thread.
- Không dùng
shell=Truenếu không cần. - Dùng
pathlib.Pathcho mọi thao tác đường dẫn. - Validate input trước khi khởi chạy worker.
- Dùng temporary output rồi mới commit output cuối cùng.
- Mọi subprocess phải có timeout, logging và cleanup phù hợp.
- Không nuốt exception; chuyển lỗi thành event có cấu trúc.
- Không hiển thị traceback thô cho người dùng phổ thông.
- Viết test cho phần parser, path, state machine và options trước khi nối vào UI.
- Sau mỗi mốc lớn, chạy test và sửa lỗi trước khi tiếp tục.
- Cập nhật
README.mdvới hướng dẫn cài Tesseract, Ghostscript, language pack và chạy app. - Ghi rõ giới hạn của MVP, đặc biệt về pause/resume giữa một PDF.
- Cuối cùng tạo bản build Windows và kiểm tra trên máy không có môi trường development.
Kết quả cuối cùng phải gồm:
Source code hoàn chỉnh
Unit tests
Integration tests tối thiểu
README.md
requirements/pyproject configuration
PyInstaller build script
Windows onedir build
Hướng dẫn cài dependency
Hướng dẫn sử dụng nhanh
Khi báo cáo tiến độ, luôn nêu:
Đã hoàn thành phần nào
Đã kiểm thử bằng cách nào
Còn vấn đề nào
Bước tiếp theo là gì
Mục tiêu cuối cùng là người dùng chỉ cần:
Mở OCRmyPDF GUI
Kéo PDF vào
Chọn ngôn ngữ
Bấm Start OCR
và nhận được một PDF có thể tìm kiếm, chọn và sao chép văn bản mà không phải mở terminal hay nhớ command line.