basira-vision 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- basira_vision-0.1.0/.gitignore +13 -0
- basira_vision-0.1.0/CHANGELOG.md +37 -0
- basira_vision-0.1.0/LICENSE +21 -0
- basira_vision-0.1.0/PKG-INFO +344 -0
- basira_vision-0.1.0/README.md +308 -0
- basira_vision-0.1.0/pyproject.toml +88 -0
- basira_vision-0.1.0/src/basira_vision/__init__.py +3 -0
- basira_vision-0.1.0/src/basira_vision/__main__.py +4 -0
- basira_vision-0.1.0/src/basira_vision/cli.py +623 -0
- basira_vision-0.1.0/src/basira_vision/pipeline.py +157 -0
- basira_vision-0.1.0/src/basira_vision/processing/__init__.py +0 -0
- basira_vision-0.1.0/src/basira_vision/processing/pdf_converter.py +91 -0
- basira_vision-0.1.0/src/basira_vision/processing/prompt_loader.py +59 -0
- basira_vision-0.1.0/src/basira_vision/processing/translation.py +59 -0
- basira_vision-0.1.0/src/basira_vision/processing/typst_processor.py +186 -0
- basira_vision-0.1.0/src/basira_vision/prompts/ocr/arabic.txt +18 -0
- basira_vision-0.1.0/src/basira_vision/prompts/ocr/chechen.txt +27 -0
- basira_vision-0.1.0/src/basira_vision/prompts/ocr/english.txt +14 -0
- basira_vision-0.1.0/src/basira_vision/prompts/ocr/french.txt +16 -0
- basira_vision-0.1.0/src/basira_vision/prompts/ocr/german.txt +18 -0
- basira_vision-0.1.0/src/basira_vision/prompts/ocr/russian.txt +16 -0
- basira_vision-0.1.0/src/basira_vision/prompts/translate/arabic.txt +41 -0
- basira_vision-0.1.0/src/basira_vision/prompts/translate/chechen.txt +48 -0
- basira_vision-0.1.0/src/basira_vision/prompts/translate/english.txt +41 -0
- basira_vision-0.1.0/src/basira_vision/prompts/translate/french.txt +35 -0
- basira_vision-0.1.0/src/basira_vision/prompts/translate/german.txt +35 -0
- basira_vision-0.1.0/src/basira_vision/prompts/translate/russian.txt +42 -0
- basira_vision-0.1.0/src/basira_vision/providers/__init__.py +14 -0
- basira_vision-0.1.0/src/basira_vision/providers/base.py +46 -0
- basira_vision-0.1.0/src/basira_vision/providers/gemini.py +231 -0
- basira_vision-0.1.0/src/basira_vision/settings.py +37 -0
- basira_vision-0.1.0/src/basira_vision/templates/template.typ +222 -0
- basira_vision-0.1.0/src/basira_vision/ui/__init__.py +90 -0
- basira_vision-0.1.0/src/basira_vision/ui/events.py +116 -0
- basira_vision-0.1.0/src/basira_vision/ui/live.py +316 -0
- basira_vision-0.1.0/src/basira_vision/ui/plain.py +124 -0
- basira_vision-0.1.0/src/basira_vision/ui/state.py +94 -0
- basira_vision-0.1.0/src/basira_vision/utils/__init__.py +0 -0
- basira_vision-0.1.0/src/basira_vision/utils/constants.py +24 -0
- basira_vision-0.1.0/src/basira_vision/utils/errors.py +50 -0
- basira_vision-0.1.0/src/basira_vision/utils/logging.py +64 -0
- basira_vision-0.1.0/src/basira_vision/utils/pages.py +210 -0
- basira_vision-0.1.0/tests/conftest.py +78 -0
- basira_vision-0.1.0/tests/test_cli.py +280 -0
- basira_vision-0.1.0/tests/test_gemini.py +149 -0
- basira_vision-0.1.0/tests/test_page_range.py +22 -0
- basira_vision-0.1.0/tests/test_pages.py +94 -0
- basira_vision-0.1.0/tests/test_prompts.py +50 -0
- basira_vision-0.1.0/tests/test_translation.py +40 -0
- basira_vision-0.1.0/tests/test_typst.py +228 -0
- basira_vision-0.1.0/tests/test_ui.py +105 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project uses
|
|
5
|
+
[Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.1.0] - 2026-11-09
|
|
10
|
+
|
|
11
|
+
First public release.
|
|
12
|
+
|
|
13
|
+
- `basira ocr` and `basira translate` for Arabic, Chechen, English, French,
|
|
14
|
+
German and Russian: vision OCR of scanned PDFs, and page-by-page
|
|
15
|
+
translation with the previous page as context.
|
|
16
|
+
- `basira typst`: A5 book typesetting with Pandoc and an editable Typst
|
|
17
|
+
template that holds all the layout; `--template` uses your own copy.
|
|
18
|
+
The page count is always even: a blank last page is added when needed.
|
|
19
|
+
- `basira export template` and `basira export prompts` write copies of the
|
|
20
|
+
built-in template and prompts to edit.
|
|
21
|
+
- Resumable runs: `--resume` processes only missing or failed pages, so
|
|
22
|
+
chunked `--page-range` runs and retries work. Existing output is never
|
|
23
|
+
replaced without `--resume` or `--force-restart`.
|
|
24
|
+
- Terminal output: a live view with a page-map progress bar, ETA, retry and
|
|
25
|
+
rate-limit countdowns and a summary that names the next command; plain
|
|
26
|
+
logfmt lines when not on a terminal; `--log-format json`.
|
|
27
|
+
- Ctrl-C finishes the current page before stopping; a second Ctrl-C stops
|
|
28
|
+
at once. A run stops after 5 failed pages in a row, and an unreachable
|
|
29
|
+
endpoint or rejected key is reported before the first page.
|
|
30
|
+
- Failed pages keep their reason in the page marker and never reach the
|
|
31
|
+
typeset book; `typst` names them in a warning.
|
|
32
|
+
- Exit codes: 0 done, 3 done with failed pages, 1 error, 2 usage, 130 paused.
|
|
33
|
+
- Custom prompt directories (`--prompts-dir`, `BASIRA_PROMPTS_DIR`).
|
|
34
|
+
- Gemini-protocol gateways via `GEMINI_BASE_URL`.
|
|
35
|
+
|
|
36
|
+
[Unreleased]: https://github.com/gushmazuko/basira-vision/compare/v0.1.0...HEAD
|
|
37
|
+
[0.1.0]: https://github.com/gushmazuko/basira-vision/releases/tag/v0.1.0
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 gushmazuko
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: basira-vision
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Turn a scanned book into a typeset edition in another language: vision OCR, sliding-window translation, Typst typesetting
|
|
5
|
+
Project-URL: Homepage, https://github.com/gushmazuko/basira-vision
|
|
6
|
+
Project-URL: Repository, https://github.com/gushmazuko/basira-vision
|
|
7
|
+
Project-URL: Issues, https://github.com/gushmazuko/basira-vision/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/gushmazuko/basira-vision/blob/main/CHANGELOG.md
|
|
9
|
+
Author: gushmazuko
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: book,gemini,ocr,pandoc,pdf,translation,typst,vision
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering :: Image Recognition
|
|
24
|
+
Classifier: Topic :: Text Processing :: Linguistic
|
|
25
|
+
Requires-Python: >=3.10
|
|
26
|
+
Requires-Dist: click>=8.1
|
|
27
|
+
Requires-Dist: google-genai<3,>=2.23
|
|
28
|
+
Requires-Dist: httpx<1,>=0.28
|
|
29
|
+
Requires-Dist: pillow>=10.0
|
|
30
|
+
Requires-Dist: pydantic-settings>=2.0
|
|
31
|
+
Requires-Dist: pydantic>=2.0
|
|
32
|
+
Requires-Dist: pymupdf>=1.24.3
|
|
33
|
+
Requires-Dist: pyyaml>=6.0
|
|
34
|
+
Requires-Dist: rich>=13.0
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
<h3 align="center">
|
|
38
|
+
<img src="https://raw.githubusercontent.com/gushmazuko/basira-vision/main/assets/basira-vision-wordmark.png" alt="Basira Vision" width="360"><br>
|
|
39
|
+
Scanned book in, a new edition in your language out
|
|
40
|
+
</h3>
|
|
41
|
+
|
|
42
|
+
<p align="center">
|
|
43
|
+
<a href="https://github.com/gushmazuko/basira-vision/actions/workflows/ci.yml"><img src="https://github.com/gushmazuko/basira-vision/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
44
|
+
<img src="https://img.shields.io/badge/python-3.10%2B-3776AB?logo=python&logoColor=white" alt="Python 3.10+">
|
|
45
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-34A853" alt="MIT License"></a>
|
|
46
|
+
</p>
|
|
47
|
+
|
|
48
|
+
Basira Vision is a command-line tool that turns a scanned book into a typeset
|
|
49
|
+
PDF in another language. A vision model reads every page image, the text is
|
|
50
|
+
translated page by page with the previous page as context, and Pandoc + Typst
|
|
51
|
+
lay it out as a book. Between the steps you get plain markdown files to
|
|
52
|
+
review and fix.
|
|
53
|
+
|
|
54
|
+
<p align="center">
|
|
55
|
+
<img src="https://raw.githubusercontent.com/gushmazuko/basira-vision/main/assets/before-after.png" alt="Left: a skewed, noisy scanned page of Alice's Adventures in Wonderland with no text layer. Right: the same page as a typeset Russian edition produced by Basira Vision." width="100%">
|
|
56
|
+
</p>
|
|
57
|
+
|
|
58
|
+
## How it works
|
|
59
|
+
|
|
60
|
+
<p align="center">
|
|
61
|
+
<img src="https://raw.githubusercontent.com/gushmazuko/basira-vision/main/assets/pipeline.svg" alt="Pipeline: scanned PDF → ocr (vision model) → markdown with page markers → translate (sliding-window context) → translated markdown → typst (pandoc + typst) → book PDF" width="100%">
|
|
62
|
+
</p>
|
|
63
|
+
|
|
64
|
+
1. **`basira ocr`** renders each page to an image and has a vision model
|
|
65
|
+
read it. This works where classic OCR struggles: no text layer, skewed or
|
|
66
|
+
noisy scans, complex scripts, diacritics, less common languages.
|
|
67
|
+
Per-language prompts handle details such as reading direction or letters
|
|
68
|
+
models tend to confuse.
|
|
69
|
+
2. **`basira translate`** translates one page at a time and sends the
|
|
70
|
+
finished translation of the previous page along as context. This
|
|
71
|
+
one-page **sliding window** keeps names, terms and voice consistent
|
|
72
|
+
across the book. A failed page clears the window, so one bad page never
|
|
73
|
+
affects the next.
|
|
74
|
+
3. **`basira typst`** typesets the result as an A5 book: title page,
|
|
75
|
+
optional translator's preface, table of contents, running heads,
|
|
76
|
+
footnotes, and an even page count for printing. Everything comes from
|
|
77
|
+
one editable Typst template.
|
|
78
|
+
|
|
79
|
+
Every stage saves after each page and can resume where it stopped.
|
|
80
|
+
|
|
81
|
+
## Install
|
|
82
|
+
|
|
83
|
+
You need Python 3.10+, [Pandoc](https://pandoc.org/installing.html) and
|
|
84
|
+
[Typst](https://github.com/typst/typst#installation) (Pandoc and Typst are
|
|
85
|
+
only used by the `typst` step).
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# macOS
|
|
89
|
+
brew install pandoc typst
|
|
90
|
+
# Debian/Ubuntu (Typst from its releases page or `cargo install typst-cli`)
|
|
91
|
+
sudo apt install pandoc
|
|
92
|
+
# Windows
|
|
93
|
+
winget install JohnMacFarlane.Pandoc Typst.Typst
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The book is set in [PT Serif](https://fonts.google.com/specimen/PT+Serif).
|
|
97
|
+
It comes with macOS; on Linux and Windows download it from Google Fonts.
|
|
98
|
+
|
|
99
|
+
Then install the CLI with [uv](https://docs.astral.sh/uv/) or pipx:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
uv tool install basira-vision # or: pipx install basira-vision
|
|
103
|
+
# latest development version:
|
|
104
|
+
uv tool install git+https://github.com/gushmazuko/basira-vision
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Quick start
|
|
108
|
+
|
|
109
|
+
Get an API key from [Google AI Studio](https://aistudio.google.com/) and
|
|
110
|
+
export it, or put it in a `.env` file in the directory you run from:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
export GEMINI_API_KEY=your_key
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# 1. OCR: writes workspace/mybook/mybook.md
|
|
118
|
+
basira ocr mybook.pdf --source-language english
|
|
119
|
+
|
|
120
|
+
# review and fix workspace/mybook/mybook.md, then
|
|
121
|
+
|
|
122
|
+
# 2. Translate: writes workspace/mybook/mybook_russian.md
|
|
123
|
+
basira translate workspace/mybook/mybook.md --target-language russian
|
|
124
|
+
|
|
125
|
+
# review the translation, then
|
|
126
|
+
|
|
127
|
+
# 3. Typeset: writes workspace/mybook/mybook_russian.pdf
|
|
128
|
+
basira typst workspace/mybook/mybook_russian.md --title "Title" --author "Author"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Title and author can also go into the YAML frontmatter at the top of the
|
|
132
|
+
markdown file, so plain `basira typst book.md` is enough.
|
|
133
|
+
|
|
134
|
+
For a long book, work in chunks or stop at any time. `--resume` keeps the
|
|
135
|
+
finished pages and processes only the missing or failed ones:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
basira ocr mybook.pdf --page-range 1-100
|
|
139
|
+
basira ocr mybook.pdf --page-range 101-200 --resume
|
|
140
|
+
basira ocr mybook.pdf --resume # retry pages that failed
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Nothing you have is ever replaced silently: running a command again when
|
|
144
|
+
its output already exists stops and asks for `--resume` (keep it, including
|
|
145
|
+
your edits) or `--force-restart` (delete it and start over).
|
|
146
|
+
|
|
147
|
+
## What you see while it runs
|
|
148
|
+
|
|
149
|
+
<p align="center">
|
|
150
|
+
<img src="https://raw.githubusercontent.com/gushmazuko/basira-vision/main/assets/terminal.svg" alt="basira ocr in a terminal: a header with input and output, a progress bar whose cells map the pages of the book, the page count, elapsed time and estimate, and a line saying the API is rate limiting with a countdown" width="100%">
|
|
151
|
+
</p>
|
|
152
|
+
|
|
153
|
+
- The progress bar is a map of the book: every cell is a page (or a slice
|
|
154
|
+
of a long book), so you see *where* pages failed, not just how many.
|
|
155
|
+
Pages finished in an earlier run are shown dimmer.
|
|
156
|
+
- Below it: what is happening right now, including retry countdowns and
|
|
157
|
+
rate-limit waits; for `translate`, which page is used as context.
|
|
158
|
+
- Only failures are printed permanently, and repeated failures collapse into
|
|
159
|
+
one line. If the endpoint goes down, the run stops after 5 failed pages in
|
|
160
|
+
a row instead of failing the rest of the book.
|
|
161
|
+
- At the end: a summary with the exact command to retry, continue or run the
|
|
162
|
+
next step.
|
|
163
|
+
- **Ctrl-C** once finishes the page in progress (its request is already paid
|
|
164
|
+
for) and pauses; press it again to stop at once. Either way nothing is
|
|
165
|
+
lost: continue with `--resume`.
|
|
166
|
+
|
|
167
|
+
A page that fails is recorded with its reason in the marker and no text,
|
|
168
|
+
`<!-- Page 9 - Error: HTTP 500 INTERNAL -->`, so it never ends up in the
|
|
169
|
+
book. `--resume` retries it, or you can write the text under the marker
|
|
170
|
+
yourself: a page with text counts as done.
|
|
171
|
+
|
|
172
|
+
When the output is not a terminal (`nohup`, `| tee`, CI), each event becomes
|
|
173
|
+
one timestamped line, easy to `tail -f` and `grep`:
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
2026-10-27 20:44:31 ocr ok page=5 progress=5/300 took=2.1s eta=9:58
|
|
177
|
+
2026-10-27 20:44:33 ocr retry page=6 attempt=1/2 wait=1s reason="HTTP 500 INTERNAL"
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
`--log-format json` writes one JSON object per event instead. Progress and
|
|
181
|
+
messages go to stderr; stdout gets only the path of the result, so steps can
|
|
182
|
+
be chained: `basira translate "$(basira ocr book.pdf)" --target-language russian`.
|
|
183
|
+
|
|
184
|
+
Exit codes: `0` done, `3` done but some pages failed, `1` error or stopped,
|
|
185
|
+
`2` invalid usage, `130` paused with Ctrl-C.
|
|
186
|
+
|
|
187
|
+
## Why not just…
|
|
188
|
+
|
|
189
|
+
- **…use Tesseract or another classic OCR engine?** They need clean scans
|
|
190
|
+
and good language data. A vision model copes much better with noise,
|
|
191
|
+
skew, unusual fonts and complex scripts, and it outputs markdown with
|
|
192
|
+
headings and lists instead of raw lines.
|
|
193
|
+
- **…use a PDF-to-markdown tool such as Marker or olmOCR?** They are good
|
|
194
|
+
at extraction, but they stop at markdown. Basira Vision is about the
|
|
195
|
+
whole edition: translation that stays consistent across the book, and
|
|
196
|
+
typesetting.
|
|
197
|
+
- **…upload the PDF to a chatbot?** That works for a few pages. For a whole
|
|
198
|
+
book you lose page structure, consistent terminology between sessions,
|
|
199
|
+
the ability to resume, and a reviewable file between the steps.
|
|
200
|
+
|
|
201
|
+
## Local models and gateways
|
|
202
|
+
|
|
203
|
+
The client speaks the Gemini API protocol (`google-genai`). Set
|
|
204
|
+
`GEMINI_BASE_URL` to send every request to any server that implements the
|
|
205
|
+
same protocol instead of Google, for example a self-hosted gateway. A
|
|
206
|
+
gateway can front a hosted model or a local vision model (Gemma and the
|
|
207
|
+
like):
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
GEMINI_BASE_URL=http://gateway.local:8080 # service root, no /v1 suffix
|
|
211
|
+
GEMINI_MODEL=my-vision-model # a model name the gateway serves
|
|
212
|
+
GEMINI_API_KEY=placeholder # whatever the gateway expects
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
The gateway has to implement the native Gemini endpoint
|
|
216
|
+
`POST /v1beta/models/{model}:generateContent`; an OpenAI-compatible
|
|
217
|
+
`/v1/chat/completions` alone is not enough. The base URL is checked at
|
|
218
|
+
startup: it must be the service root, without `/v1`, `/v1beta` or `/openai`.
|
|
219
|
+
|
|
220
|
+
## Usage
|
|
221
|
+
|
|
222
|
+
Every command documents its options: `basira <command> --help`. All of
|
|
223
|
+
them also take `--log-format auto|live|plain|json` and `-v`/`--verbose`.
|
|
224
|
+
|
|
225
|
+
### `basira ocr PDF_FILE`
|
|
226
|
+
|
|
227
|
+
| Option | Purpose |
|
|
228
|
+
|--------|---------|
|
|
229
|
+
| `--source-language` | OCR prompt: `english` (default), `arabic`, `chechen`, `french`, `german`, `russian`, or your own |
|
|
230
|
+
| `--page-range` | `5` or `1-10`; pages keep their real numbers |
|
|
231
|
+
| `--dpi` | render resolution, 72–600 (default 300; try 600 for poor scans) |
|
|
232
|
+
| `--model`, `-m` | model name, overrides `GEMINI_MODEL` |
|
|
233
|
+
| `--custom-prompt` | prompt text, or a path to a prompt file |
|
|
234
|
+
| `--prompts-dir` | your own prompt directory (see [docs/prompts.md](docs/prompts.md)) |
|
|
235
|
+
| `--output-dir` | workspace directory (default `./workspace`) |
|
|
236
|
+
| `--no-images` | do not keep the rendered page images |
|
|
237
|
+
| `--resume` / `--force-restart` | continue (keeps finished pages, retries failed ones) / delete the output and start over |
|
|
238
|
+
|
|
239
|
+
### `basira translate MARKDOWN_FILE`
|
|
240
|
+
|
|
241
|
+
| Option | Purpose |
|
|
242
|
+
|--------|---------|
|
|
243
|
+
| `--target-language` | `english` (default), `arabic`, `chechen`, `french`, `german`, `russian`, or your own |
|
|
244
|
+
| `--model`, `-m` | model name |
|
|
245
|
+
| `--custom-prompt` | prompt text or file with `{text}`, optionally `{context_section}` and `{source_language}` |
|
|
246
|
+
| `--prompts-dir` | your own prompt directory |
|
|
247
|
+
| `-o`, `--output` | output file (default `<name>_<language>.md` next to the input) |
|
|
248
|
+
| `--resume` / `--force-restart` | continue (keeps finished pages, retries failed ones) / delete the output and start over |
|
|
249
|
+
|
|
250
|
+
### `basira typst MARKDOWN_FILE`
|
|
251
|
+
|
|
252
|
+
All options are optional overrides of the frontmatter and template defaults.
|
|
253
|
+
The PDF is written next to the markdown unless `-o` is given. Pages that
|
|
254
|
+
failed in an earlier step are left out of the book, with a warning that
|
|
255
|
+
names them. A `translator_preface:` path in the frontmatter is relative to
|
|
256
|
+
the markdown file; `--translator-preface` is relative to where you run the
|
|
257
|
+
command. A ready example is [examples/translator_preface.md](examples/translator_preface.md).
|
|
258
|
+
|
|
259
|
+
| Option | Purpose |
|
|
260
|
+
|--------|---------|
|
|
261
|
+
| `--title`, `--author` | book metadata |
|
|
262
|
+
| `--subtitle`, `--version`, `--date` | title-page lines |
|
|
263
|
+
| `--translator-preface` | markdown file inserted after the title page ([example](examples/translator_preface.md)) |
|
|
264
|
+
| `--lang` | document language code (default: from the frontmatter) |
|
|
265
|
+
| `--header` | running header text (default: the title) |
|
|
266
|
+
| `--toc-title`, `--no-toc` | table of contents heading, or no table of contents |
|
|
267
|
+
| `--template` | your own copy of the template (see Customizing) |
|
|
268
|
+
|
|
269
|
+
Page size, margins, fonts and spacing are set in the template, not on the
|
|
270
|
+
command line.
|
|
271
|
+
|
|
272
|
+
## Configuration
|
|
273
|
+
|
|
274
|
+
Environment variables, or a `.env` file in the current directory:
|
|
275
|
+
|
|
276
|
+
| Variable | Purpose |
|
|
277
|
+
|----------|---------|
|
|
278
|
+
| `GEMINI_API_KEY` | API key (required; `GOOGLE_API_KEY` also works) |
|
|
279
|
+
| `GEMINI_MODEL` | model name, default `gemini-3.8-flash` |
|
|
280
|
+
| `GEMINI_BASE_URL` | Gemini-protocol gateway, see above |
|
|
281
|
+
| `BASIRA_OUTPUT_DIR` | workspace directory, default `./workspace` |
|
|
282
|
+
| `BASIRA_PROMPTS_DIR` | your own prompt directory |
|
|
283
|
+
|
|
284
|
+
The workspace holds one folder per book:
|
|
285
|
+
|
|
286
|
+
```
|
|
287
|
+
workspace/mybook/
|
|
288
|
+
├── mybook.md OCR result, one <!-- Page N --> block per page
|
|
289
|
+
├── mybook_russian.md translation
|
|
290
|
+
├── mybook_russian.pdf typeset book
|
|
291
|
+
└── images/ rendered page images
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Customizing
|
|
295
|
+
|
|
296
|
+
Take a copy of the built-in template or prompts, edit it, and point basira
|
|
297
|
+
at it:
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
basira export template # writes ./template.typ
|
|
301
|
+
basira typst book.md --template template.typ
|
|
302
|
+
|
|
303
|
+
basira export prompts # writes ./prompts/ocr/*.txt and ./prompts/translate/*.txt
|
|
304
|
+
basira ocr book.pdf --prompts-dir prompts
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
- **Layout.** [`template.typ`](src/basira_vision/templates/template.typ) is a
|
|
308
|
+
Typst file with Pandoc variables. It sets an A5 book (148×210 mm, 11pt,
|
|
309
|
+
PT Serif); page size, margins, fonts, spacing, title
|
|
310
|
+
page and running heads are all changed there. Keep `horizontalrule` and
|
|
311
|
+
`divider` (scene breaks) in your copy: the converted text calls them.
|
|
312
|
+
- **Languages.** A prompt directory (`--prompts-dir` or `BASIRA_PROMPTS_DIR`)
|
|
313
|
+
is searched before the built-in prompts, so it can change a language or
|
|
314
|
+
add one (`ocr/<language>.txt`, `translate/<language>.txt`). See
|
|
315
|
+
[docs/prompts.md](docs/prompts.md).
|
|
316
|
+
|
|
317
|
+
## Limitations
|
|
318
|
+
|
|
319
|
+
- **Gemini protocol only.** Other models work through a Gemini-compatible
|
|
320
|
+
gateway (see above). There is no native client for OpenAI-compatible APIs.
|
|
321
|
+
- **The translation context is one page.** A name that first appears on
|
|
322
|
+
page 5 and comes back on page 200 is not guaranteed to be translated the
|
|
323
|
+
same way. There is no glossary yet.
|
|
324
|
+
- **Text only.** Illustrations are not carried over, and complex tables or
|
|
325
|
+
multi-column layouts may need manual cleanup in the markdown.
|
|
326
|
+
- **Models make mistakes.** They can skip or invent a line, especially in
|
|
327
|
+
footnotes and damaged areas. Reviewing the markdown between steps is part
|
|
328
|
+
of the workflow, not an optional extra.
|
|
329
|
+
|
|
330
|
+
## Rights and privacy
|
|
331
|
+
|
|
332
|
+
Use Basira Vision on public-domain works, or on works you have the right to
|
|
333
|
+
translate and publish.
|
|
334
|
+
|
|
335
|
+
Page images and text are sent to the model endpoint you configure (Google's
|
|
336
|
+
API by default). Do not process confidential documents with a service you do
|
|
337
|
+
not trust. The tool has no telemetry; the API key is only used to call that
|
|
338
|
+
endpoint.
|
|
339
|
+
|
|
340
|
+
## Documentation
|
|
341
|
+
|
|
342
|
+
- [ARCHITECTURE.md](ARCHITECTURE.md): modules, page files, resume and the sliding window
|
|
343
|
+
- [docs/prompts.md](docs/prompts.md): prompt templates and adding languages
|
|
344
|
+
- [CHANGELOG.md](CHANGELOG.md)
|