Files
MeshTerm/scripts/README.md
T
Jean-Pierre MartineauandClaude Opus 5.5 fc7fd17554 The videos for Instagram come from a script
scripts/reels.py makes one vertical video of MeshTerm for each feature, from the demo mesh: 1080×1920, with subtitles in the picture and no sound, then a card with the wordmark and the website. The terminal has 72 columns, so its text is as large as a phone lets it be. It also writes a cover for the Reel and a caption for the post. The first video is the chat: the conversations, a live message, the paths of a message, a mention and its answer, and a link as a QR code.

screenshots.py now takes the grid of the terminal set as an argument, and its painter draws a full-width character that no font has (the "#" of a hashtag channel) as its ASCII form, instead of a box.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 13:03:36 -04:00

143 lines
9.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# scripts/
These are tools for the repository. None of them is in the wheel.
| Script | What it is for |
|---|---|
| `basemap-doctor.py` | Finds why a user's map has no basemap: certificates, DNS, proxy, or colour depth |
| `cardputer-zero/` | `build-deb.sh` builds the Debian package for M5Stack's app store. Run it on the Cardputer Zero or on another arm64 Debian 13 system. `store/` holds the listing for the store (`app-builder.json`, which `czdev publish` reads), its icon, and its screenshots. `screenshot.py` saves the display of a Cardputer as a 320×170 PNG over SSH, as the store wants a screenshot. `store-publish.py` sends a package to the store with M5Stack's `czdev`, with two corrections. The release workflow runs it after each release. `launcher-entry.sh` puts a source checkout in the Cardputer Zero's app launcher. `remove` takes it out. `meshterm.png` is the package's icon: the website's logo, at the launcher's 100×100 size. `meshterm-dev.png` is its negative, for the checkout's entry, so that the two entries look different. `type-text.py` types a pasted string (an API key, a Wi-Fi password) on the Cardputer's keyboard from another computer, over SSH |
| `screenshots.py` | Makes the screenshots of the website from the demo mesh (`--demo`): the main menu, the chat, the paths of a message, and the map, for the terminal, the Cardputer Zero, and the PicoCalc. They are the same at each run. The result goes to `docs/screenshots/<set>/`. It also draws the two wordmarks of the splash into `docs/screenshots/splash/`, which the website uses as its splash |
| `video.py` | Makes the demo video of the website from the demo mesh: a tour of less than two minutes in the terminal, with its poster and its play card. The result goes to `src/` of the `meshterm.net` checkout beside this one |
| `reels.py` | Makes the videos for Instagram from the demo mesh: one vertical video for each feature, with subtitles in the picture and no sound, a cover, and a caption for the post. The result goes to `output/reels/` |
| `picocalc-lyra/` | Setup of the Calculinux device: console font, palette, Wi-Fi. `xiao-radio/` is the kit for the XIAO radio (firmware build, flashing, UART setup) |
| `uconsole/` | The uConsole's always-on SPI bridge service. MeshTerm can also control that radio directly, with no script (refer to `docs/devices/uconsole.md`) |
## basemap-doctor.py
The map is the only part of MeshTerm that uses the network. MeshTerm logs each fetch
failure on this path at DEBUG, and `log_level` is WARNING by default. Thus a user whose
tiles do not arrive sees a blank ground and no explanation. This script prints the
explanation and the correction.
To use it, tell the user to run this **on the machine that has the problem**:
```bash
curl -fsSL https://raw.githubusercontent.com/jpmartineau/MeshTerm/main/scripts/basemap-doctor.py -o /tmp/basemap-doctor.py
python3 /tmp/basemap-doctor.py
```
Any `python3` is correct. If that `python3` does not have MeshTerm, the script reads the
interpreter from the installed `meshterm` command's shebang, and it runs again with
that interpreter. Thus the answer always comes from **the app's own Python**. A Mac
often has three Pythons, and only one of them has the trust store that is important. Save
the script to a file, as in the example. Do not pipe it into `python3 -`. When there is no
file on the disk, the script cannot run again with the other interpreter.
Ask the user to paste all the output back to you. The output names the interpreter, the
certificate store, the tile source, the number of cached tiles, and `COLORTERM`. Then it
gives one verdict:
- **curl reached it, Python did not.** The Python's certificate store is empty. A
python.org install on macOS has an empty store until the user runs
`Install Certificates.command`.
- **neither reached it.** The problem is in the network path: a firewall, a proxy, a DNS
filter, or an outage. There is nothing to correct in MeshTerm.
- **both reached it.** The tiles are correct. The problem is colour. When `COLORTERM` is not
set, the terminal uses 256 colours, and the greens and blues of the basemap are too
similar. Terminal.app cannot do 24-bit colour.
The exit status is 0 when the tiles arrive and 1 when they do not. Thus a script can use it.
## screenshots.py
The website shows the same four screens for three platforms: the terminal, the Cardputer
Zero, and the PicoCalc. This script makes all twelve images from the demo mesh. Each run
gives the same pixels: the demo writes the same history, the clock of each run is set to
11:42 on Thursday 15 October 2026 in Montréal, and nothing moves on the screen when the
script saves it.
```bash
pip install -e .[dev] # Pillow, fontTools, and time-machine
meshterm emulate --fetch-fonts # the Terminus font of the handheld sets, one time
python scripts/screenshots.py # all three sets, into docs/screenshots/<set>/
python scripts/screenshots.py --only terminal
```
No window opens. MeshTerm runs in the process, in the session of the emulator, and the
script types the keys. The terminal set uses Cascadia Mono, Segoe UI Symbol, and Segoe UI
Emoji, which Windows has. On another system, change `TEXT_FONTS` and `EMOJI_FONT` at the
top of the script. The first run downloads the tiles of the map. The later runs use the
tile cache in the temporary directory.
The script also draws each wordmark of the startup splash (`meshterm/assets/splash/*.ans`)
as `docs/screenshots/splash/logo.<width>.png`, one image pixel for each pixel of the font,
in the Campbell colours. The website takes its splash from there: the wide mark on a wide
screen, and the narrow mark on a phone. `--only splash` draws only these two images.
After a change to a screen or to the art, run the script again, then rebuild the website
(refer to the README of the `meshterm.net` repository).
## video.py
The website plays a video of MeshTerm under its buttons. This script makes it from the
demo mesh, in the terminal set of `screenshots.py`: the same 80×24 terminal, the same
clock, and the same painter. It types the keys of a tour of less than two minutes: the
chat, the paths of a message, a question that mentions a node and its answer, a trace,
the map, Repeater admin, and the live feed. A camera copies the screen 30 times each second.
```bash
python scripts/video.py # into ../meshterm.net/src/
python scripts/video.py --out some/folder
python scripts/video.py --recording tour.pickle # keep the recording
python scripts/video.py --readme # the README's copy, after a check
```
It needs ffmpeg with libx264 on the `PATH`, and the needs of `screenshots.py`. A run takes
approximately four minutes. The tour runs on the real clock, then the script paints each
different screen in parallel and encodes the video. With `--recording`, the script keeps
the recording in that file. When the file exists, a later run paints and encodes it again,
and does not run MeshTerm.
The script writes three files: `demo.mp4`, `demo-poster.png` (the paths of a message,
which the website shows before the video plays), and `demo-play.png` (the poster with a
play mark and the length of the video). The camera stops while the tour waits for
something slow: the tiles of the map, and most of the read of the repeater's settings.
Thus the video jumps over the wait.
With `--readme`, the script makes no video. It uploads `demo.mp4` to GitHub as an
attachment of the repository, because GitHub plays a video in a README only when it is one
of its own attachments. Then it puts the new URL on the attachment line of `README.md`. It
uses an endpoint that GitHub does not document, with the token of the GitHub CLI. Each
upload stays on GitHub, so use it only on a video that you examined.
Each run gives the same video to the eye, but not the same file, because the camera copies
the screen on the real clock. Each release makes the video again, after the screenshots,
and pushes it to the website repository before the tag. After a change to the screens
between two releases, run the two scripts, then rebuild the website (refer to the README of
the `meshterm.net` repository).
## reels.py
This script makes the videos for Instagram. Each video shows one feature of MeshTerm, in
the demo mesh. It is a Reel: a vertical video of 1080×1920 pixels, at 30 video frames each
second. The terminal has 72 columns, so that its text is as large as the width of a phone
lets it be. Above the terminal is the name of the series (`MeshTerm · Chat`), and under it
are the subtitles. The video has no sound, because many people watch Instagram with the
sound off. It ends on a card with the wordmark and the address of the website.
```bash
python scripts/reels.py chat # into output/reels/
python scripts/reels.py chat --out some/folder
python scripts/reels.py chat --recording chat.pickle # keep the recording
```
`chat` is the only video now: the list of the conversations, a message that arrives, the
paths of a message, a mention and its answer, and a link as a QR code. To add a video, write
its tour and add it to `REELS`. A tour types the keys, as in `video.py`, and also writes the
subtitles (`Director.subtitle`).
The script writes three files: `<name>.mp4` (the video, with a silent audio track),
`<name>-cover.png` (the cover of the Reel), and `<name>.txt` (a caption for the post). It
needs the same things as `video.py`, but not the website checkout. A run takes
approximately two minutes.