This skill serveslegal material OCR. The default goal is not to return a temporary piece of text, but to:
- Convert local PDFs / images into Markdown that can continue to be edited and analyzed.
- Under
archive/, keep a complete archive for review, traceability, and secondary processing.
When to use
Use this skill in the following scenarios:
- Need to convert scanned PDFs such as case files, medical records, evidentiary materials, court notices, financial reports, and receipts into Markdown.
- The document contains tables, seals, headers and footers, multi-column layouts, formulas, or complex layouts.
- Want to keep an archive within the skill to accumulate original files, Markdown, structured JSON, and batch results.
- Will continue to do legal analysis, evidence excerpts, knowledge base ingestion, or RAG chunking afterwards.
Do not prioritize this skill in the following scenarios:
- Just quickly reading a short piece of clear text, and Markdown and archiving are not needed.
- Just copying text from a screenshot, where speed matters more than structured quality.
- The input is not a PDF / common image format.
Main outputs
There are only two default main outputs:
- Markdown file: saved in the same directory as the source file, by default with the same name as the original file and extension
.md - archive directory: saved in
paddle-ocr/archive/时间戳_文件名/
The archive by default contains:
- A copy of the original input file
- Final
result.md - Final
result.json - Batch-level
batches/*.json - Extracted image assets
metadata.json
Dependencies
System dependencies
| Dependency | Installation method |
|---|---|
python3 |
Usually built in on macOS |
uv |
macOS: brew install uv |
Python packages
The script uses uv run for execution; dependencies are written at the top of the script and do not need to be maintained separately in requirements.txt。
First-time configuration
Obtain API information
- Open the PaddleOCR official website
- Go to the API page of the corresponding model
- Copy from the sample code:
API_URLAccess Token
Configuration method
Prefer editing config/.env:
cd paddle-ocr/config
cp .env.example .env
nano .env
Required fields:
PADDLEOCR_DOC_PARSING_API_URLPADDLEOCR_ACCESS_TOKEN
Common commands
Main workflow: generate Markdown + archive
Run in the skill root directory:
uv run scripts/convert.py "/path/to/legal-document.pdf"
Or continue to use the legacy entry point:
/usr/bin/osascript -l JavaScript scripts/convert.js "/path/to/legal-document.pdf"
Optional parameters:
uv run scripts/convert.py "/path/to/legal-document.pdf" --pages "1-20"
uv run scripts/convert.py "/path/to/legal-document.pdf" --output "/tmp/output.md"
uv run scripts/convert.py "/path/to/legal-document.pdf" --archive-name "某案卷宗-证据一"
Low-level debugging: call only the parsing API and output structured JSON
uv run scripts/layout_caller.py --file-path "/path/to/legal-document.pdf" --pretty
uv run scripts/layout_caller.py --file-url "https://example.com/document.pdf" --stdout --pretty
Use this low-level script when you only want to inspect the raw API results, or when you will parse table/coordinate information yourself later.
Self-check
uv run scripts/smoke_test.py --skip-api-test
uv run scripts/smoke_test.py
Split page numbers
uv run scripts/split_pdf.py input.pdf output.pdf --pages "1-5,8,10-12"
Legal PDF workflow
Work in the following order:
- Prefer using
scripts/convert.py。 - If only some page numbers are needed, first pass
--pagesto avoid uploading the entire file. - For large volumes, the script will automatically make batch requests according to the configuration and then merge them into a single Markdown.
- When review is needed, go to
archive/View:output/result.mdoutput/result.jsonmetadata.jsonbatches/*.json
Large File Strategy
This skill defaults to aconservative batching strategy:
- PDF page count exceeds
PADDLEOCR_BATCH_PAGESwhen automatically batched - Estimated Base64 size exceeds
PADDLEOCR_MAX_BASE64_MBwhen automatically batched
This means it may split earlier than the official limit, but it usually reduces the failure rate for long case files, merged medical records, and documents with unstable scan quality.
Output Description
Markdown
- By default, saved to the same directory as the source file
- If
--outputis passed and it is a.mdfile path, then save to the specified path - If
--outputis a directory, then generate the same-named.md
archive
Default archive directory structure:
archive/
└── 20260405_153000_文件名/
├── input/
│ └── 原文件.pdf
├── output/
│ ├── result.md
│ ├── result.json
│ └── images/
├── batches/
│ ├── batch_001_1-40.json
│ └── batch_002_41-67.json
└── metadata.json
Configuration Items
Edit config/.env:
| Option | Default Value | Description |
|---|---|---|
PADDLEOCR_DOC_PARSING_API_URL |
Empty | The complete layout-parsing endpoint required by the official service |
PADDLEOCR_ACCESS_TOKEN |
Empty | Official Access Token |
PADDLEOCR_DOC_ORIENTATION |
false |
Whether to enable orientation classification |
PADDLEOCR_DOC_UNWARP |
false |
Whether to enable dewarping |
PADDLEOCR_CHART_RECOG |
false |
Whether to enable chart recognition |
PADDLEOCR_DOC_PARSING_TIMEOUT |
600 |
Timeout in seconds for a single request |
PADDLEOCR_BATCH_PAGES |
40 |
PDF auto-batching page threshold and batch size |
PADDLEOCR_MAX_BASE64_MB |
20 |
Conservative size threshold for triggering batching |
PADDLEOCR_LOG_LEVEL |
medium |
low / medium / high |
Result Structure
If you need to understand the underlying JSON wrapper format, read:
references/output_schema.md
Troubleshooting
| Problem | Solution |
|---|---|
| API not configured | First add config/.env, then run uv run scripts/smoke_test.py --skip-api-test |
| 403 / Token error | Update PADDLEOCR_ACCESS_TOKEN |
| Request timeout | Increase PADDLEOCR_DOC_PARSING_TIMEOUT, or reduce the page range |
| Large PDF failure | Use --pages to narrow the range, or let the script automatically batch |
| Markdown is empty | Go to archive/ to view batches/*.json and metadata.json, to confirm whether the original file quality is too poor |
| Need to see raw coordinates and table structure | Use scripts/layout_caller.py, and read result.result.layoutParsingResults[*].prunedResult |
Integration Roadmap
This skill will be integrated with mineru-ocr into a unified legal-ocr Skill, supporting dual backends (PaddleOCR + MinerU), automatic routing, and a legal post-processing pipeline.
See the full plan at docs/ROADMAP_LEGAL_OCR.md。
Maintenance Recommendations
After modifying this skill, update in sync:
TASKS.mdDECISIONS.mdCHANGELOG.md