brl2stl
Turn braille into plastic. brl2stl converts BRF braille files — or plain text — into 3D-printable STL/3MF models: signs, labels, flashcards, book pages, even paper-embossing jigs. Cross-platform, zero required dependencies, with a desktop app, a CLI, and a web UI.
⠨⠃⠗⠇⠆⠎⠞⠇ → ▄▄▖▄▄▄▖▄ → 🖨️
Quick start
Pick whichever is easiest for you:
Desktop app (easiest)
# grab brl2stl-gui.exe / brl2stl-gui.dmg from the Releases page - no
# install needed. Or run from source:
git clone https://github.com/leavesofgrass/brl2stl
cd brl2stl
pip install .[gui]
brl2stl gui
(brl2stl is not on PyPI yet - install from a clone or use a release binary.)
Type your text (or drop a .brf file on the window), watch the live
preview, press Export model, slice, print. Standalone apps that need no
Python at all build with PyInstaller: scripts/build-exe.ps1 (Windows
exe, liblouis bundled from the official win64 release),
scripts/build-macos.sh (macOS .app + .dmg, liblouis bundled
from Homebrew), scripts/build-exe.sh (Linux binary; liblouis via your
package manager). A GitHub Actions workflow
(.github/workflows/build.yml) tests on all three OSes and builds
smoke-verified Windows + macOS artifacts, attaching both to a release on
every v* tag.
Command line
git clone https://github.com/leavesofgrass/brl2stl && cd brl2stl
pip install .
brl2stl document.brf # one STL per page
brl2stl --text "Room 12" -o sign.stl # quick label
brl2stl document.brf --info # sizes only, writes nothing
Docker (nothing to install but Docker)
docker build -t brl2stl .
docker compose up # web UI at http://localhost:8080
./scripts/brl2stl.sh document.brf # CLI (Windows: scripts\brl2stl.cmd)
Text input defaults to contracted UEB Grade 2 whenever liblouis is installed — it always is in the Docker image — and falls back to the built-in uncontracted Grade 1 translator (with a warning) otherwise. Dimensions default to the ADA 703.3 signage standard.
Documentation
Step-by-step guides live in docs/: getting started, the desktop app, the CLI reference, Docker & web UI, input formats & translation, the printing guide, the emboss jig guide, building the standalone app, and the developer guide.
Options
| Option | What it does |
|---|---|
--preset ada|marburg|nls|jumbo |
dimension standards (ADA 703.3 signage is the default; Marburg Medium is the worldwide embosser standard) |
--dot-height/-diameter/-spacing, --cell-spacing, --line-spacing, --plate-thickness, --margin |
override any dimension (mm) |
--dot-shape dome|cone|cylinder |
dome is the tactile standard; cones/cylinders can print crisper on some FDM machines |
--mirror |
mirror image, for embossing dies or printing braille on a model's back face |
--counter |
counter plate: dot-shaped recesses instead of raised dots — the female die of a paper-embossing jig (pair with a --mirror dot plate) |
--hole left|both, --hole-diameter |
keyring / jig-bolt holes in extended margins |
--corner-radius |
rounded plate corners |
--booklet |
joins a multi-page document into one print-in-place model with folding hinges |
--nameplate [TEXT], --letter-height |
nameplate mode: raised uppercase print letters above the braille — ADA signs require tactile characters and braille; defaults to the input text |
--pages 1,3-5 |
convert only some pages |
-f binary|ascii|3mf |
output format |
--resolution low|medium|high |
mesh density |
--text, --text-file, --wrap |
plain-text input instead of BRF |
--louis-table |
text translation table; default auto = UEB Grade 2 (en-ueb-g2.ctb) when liblouis is installed, built-in Grade 1 otherwise; none forces Grade 1 |
--preview |
print the braille as Unicode dots in the terminal |
8-dot (computer) braille is supported via Unicode braille input (U+2800–U+28FF); dots 7/8 get a fourth row automatically.
Printing tips
- Layer height 0.1–0.15 mm — dots are only ~0.8 mm tall.
- A 0.4 mm nozzle works; 0.25 mm renders domes noticeably better.
- Print dots facing up, no supports needed.
- PETG and PLA both work; PETG wears better for heavy use.
- If dots feel faint, raise
--dot-heightto 0.9 mm — plastic reads best slightly taller than the paper-embossing standards.
What's a BRF file?
The exchange format of braille embossers: plain ASCII where each character is one braille cell (Braille ASCII / NABCC), form-feed between pages. The content is already translated braille — usually contracted Grade 2 — which brl2stl renders verbatim. Get BRFs from your transcriber, NLS BARD, or make your own from text with liblouis.
Development
git clone https://github.com/leavesofgrass/brl2stl && cd brl2stl
PYTHONPATH=src python -m unittest discover -s tests # zero-dep test suite
The mesh generator is pure stdlib Python. Every generated solid is
verified watertight (each edge shared by exactly two opposite-wound
triangles) by the test suite, and the Docker build fails if any test
fails. See docs/PLAN.md for architecture.
License
MIT. Copyright (c) 2026 Jon Pielaet. See LICENSE.
Qt note: the desktop app uses PySide6 (LGPLv3), which permits MIT apps — the official binaries bundle Qt's shared libraries unmodified per the LGPL. If you build with the optional PyQt6 fallback instead, PyQt6's GPLv3 governs distribution of that combination. The bundled liblouis is LGPL-2.1+ and is invoked as a separate program.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file brl2stl-0.1.0.tar.gz.
File metadata
- Download URL: brl2stl-0.1.0.tar.gz
- Upload date:
- Size: 50.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
316def251a75e7e3b86f41ef0dca2e6b0e49858c4c8393f75a32182e58ca1185
|
|
| MD5 |
eca549b0d16c9fd75ff64def92a9352b
|
|
| BLAKE2b-256 |
4456bd24539afe27b45a12073b876c2cd8187f611de4825abb4ce2d6977f8ed1
|
Provenance
The following attestation bundles were made for brl2stl-0.1.0.tar.gz:
Publisher:
build.yml on leavesofgrass/brl2stl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
brl2stl-0.1.0.tar.gz -
Subject digest:
316def251a75e7e3b86f41ef0dca2e6b0e49858c4c8393f75a32182e58ca1185 - Sigstore transparency entry: 2388706292
- Sigstore integration time:
-
Permalink:
leavesofgrass/brl2stl@0fd41a7814e4a8b9dbaba45894d71edd14881d82 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/leavesofgrass
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build.yml@0fd41a7814e4a8b9dbaba45894d71edd14881d82 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file brl2stl-0.1.0-py3-none-any.whl.
File metadata
- Download URL: brl2stl-0.1.0-py3-none-any.whl
- Upload date:
- Size: 46.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b8fe030d0ed9c503b288b8bbd08d70d2c8d5237453e6fbe4b799e40b8662c45e
|
|
| MD5 |
b288e875bf1f3855e708b7a6da6bb4fe
|
|
| BLAKE2b-256 |
3e9316aa2b6cdbd14671a1971f7d4461dd07a0bcd48ab0d8f4187aecce3ff604
|
Provenance
The following attestation bundles were made for brl2stl-0.1.0-py3-none-any.whl:
Publisher:
build.yml on leavesofgrass/brl2stl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
brl2stl-0.1.0-py3-none-any.whl -
Subject digest:
b8fe030d0ed9c503b288b8bbd08d70d2c8d5237453e6fbe4b799e40b8662c45e - Sigstore transparency entry: 2388706363
- Sigstore integration time:
-
Permalink:
leavesofgrass/brl2stl@0fd41a7814e4a8b9dbaba45894d71edd14881d82 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/leavesofgrass
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build.yml@0fd41a7814e4a8b9dbaba45894d71edd14881d82 -
Trigger Event:
workflow_dispatch
-
Statement type: