← Files FountainARCHIVED FILE
skills/fountain-clip-producer/modules/preflight/MODULE.md
4.26 KB · Oct 10, 2026 · 12:04 UTC
---
name: preflight
description: Confirm that the machine can render what the request asks for, before the first render starts.
---
## Overview
A render that fails halfway wastes the whole render.
This module checks what the machine can do, and it gives the answer before any work starts.
It names the caption renderer to use.
It names the ffmpeg binary to burn with, and the ffmpeg binary to time words with.
It also names every tool that is absent.
It reports the environment, and it never looks at a rendered file.
## Input
- The kind of output that the request asks for, which decides how strict the check is.
- The font families of the resolved caption style, from module **fonts**.
- Optional: the landscape master, to probe it at the same time.
## Output
- A preflight report, which names the caption renderer, the binary to burn with, and the binary that
carries whisper.
- A list of the missing tools, and a pass or a fail.
## Requirements
- ffmpeg and ffprobe.
- Python 3.11 or later.
- OpenCV 4.8 or later, importable from that same Python.
- ImageMagick, for a captioned render.
- Skill **fountain-onboarding**, to install a missing tool.
## Process
1. Run the check before the first render:
```bash
scripts/render-preflight.py --media clip-landscape-master.mp4 \
--require-magick --require-visual-qa --require-words --fonts "Montserrat,Anton" --json
```
For an export with no captions, drop `--require-magick` and `--fonts`.
Keep `--require-visual-qa`, because module **framing** needs that interpreter on every export.
Keep `--require-words` for every tier above a rough cut.
The words of the clip come from whisper, and three modules read them.
Give the family name alone, because a weight in the name matches nothing and shows as a missing font.
2. Stop and run skill **fountain-onboarding** when the report names a missing tool, because this is a
fault of the machine and not of the clip.
3. Read the caption renderer from the report, and record it in the caption plan.
The order of preference is ASS, then drawtext, then a prepared transparent layer.
4. Burn the captions with the binary that the report names, and not always with the one on the PATH.
5. Confirm that each named font resolves to itself, and read module **fonts** when one falls back.
A family that the skill ships passes without a system install, because libass is given that directory.
6. Cache the report, and run this module again only when the machine or the kind of output changes.
## Additional notes
A stock ffmpeg is often built without libass, so it cannot burn a styled caption.
The report therefore looks for another build on the machine, wherever the platform keeps them.
When it finds one, the ASS renderer is still available, and the report names that binary.
When a build has no libass, use the other binary.
Never drop to a lesser renderer for that reason.
The same search finds the build that has whisper, and the two are usually the same binary.
Word timing has no lesser renderer.
Without whisper, the clip has no words at all.
The whisper filter transcribes nothing on its own.
It needs the path of a whisper.cpp model.
The dangerous case is a build that has the filter, on a machine that has no model.
Then ffmpeg loads its backend, prints no error, and never returns.
The render hangs, and does not fail.
So the report names the model as well as the binary, and `--require-words` fails when there is no model.
The model is not bundled, because it is 141 MB, and the face model is only 2.3 MB.
The report has the one line that installs the model.
Give that line to the user, and say that it is a one-time install of about 141 MB.
Never let the queue spend an attempt on a machine with no model.
A model named `for-tests` is ignored on purpose.
The Homebrew whisper package ships one.
That model transcribes nonsense, and does not fail.
So the machine looks as if it works, and every caption on it is wrong.
The report also names the Python interpreter that carries OpenCV, which module **framing** needs for its scripts.
An interpreter older than OpenCV 4.8 carries no `FaceDetectorYN`.
That is a missing tool, and not a warning.
A prepared transparent layer is the last choice, and it needs its own checks in module **qa**.
Reach for it only when no build on the machine can burn an ASS file.
SHA-256: 3220b32d2e814ba46776de3746233d232efb8cecf481e8d23f85c09f6ee5769f