Skip to content
Commit 30f224e3 authored by Stefy Lanza (nextime / spora )'s avatar Stefy Lanza (nextime / spora )
Browse files

fit the caption to the frame, install the font that draws it, and stop reading...


fit the caption to the frame, install the font that draws it, and stop reading an unset field as a free GPU (v0.5.6)

Four defects behind one report: vertical renders came back with caption lines
running off both edges, in the wrong typeface, and speech-to-text answered
500/503 while a text model held the card.

THE FONT WAS NEVER IN THE IMAGE. Dockerfile.oci and Dockerfile.update install
fonts-montserrat; Dockerfile.oci-venv -- the one build_oci_image.sh actually
builds -- installed no fonts at all, so no image built the normal way has ever
had the family the compose API documents and defaults to. libass does not fail
on a missing family, it substitutes: DejaVu is considerably wider, which is how
a missing package became a layout bug with nothing but a log line to say so.
All three Dockerfiles now install the fonts AND fontconfig (Dockerfile.oci had
the fonts but not fc-match, so it could not even tell whether a family
existed).

And because an image rebuild is a poor way to add a brand font, fonts can now
be supplied per installation: files dropped in <config>/fonts -- or wherever
CODERAI_FONT_DIR points -- are registered at startup by writing a fontconfig
snippet into the user config. The snippet matters more than it looks: captions
are burned by libass inside an ffmpeg CHILD process, which does its own
fontconfig lookup, so a font this process can find is not necessarily a font
the renderer can use. The config volume outlives both a restart and a new
image, which is the point.

CAPTION SIZE CAME FROM THE FRAME HEIGHT. On a vertical video the height is the
LONG side: at 1080x1920 the font was sized 0.052 * 1920 ~ 100px to be drawn
across a 1080px frame. It is now sized from the short side, which leaves 16:9
byte-identical (there the short side IS the height) and gives 9:16 the same
text-to-width ratio as 16:9. Line breaking upstream works on a word budget and
cannot know how wide the words are, and WrapStyle is 2 -- no automatic wrapping
-- so a line that still overflows was simply drawn past the edge. Each event's
widest line is now measured against the real font file, and one that does not
fit gets its own smaller size through an inline \fs override: the long line
shrinks, not the whole video. Measured with the actual face rather than
estimated per character, because the families involved differ in width by
exactly the margin that decides the question. Clients scaling font_scale down
by hand for 9:16 and 4:5 can stop.

AN UNSET FIELD READ AS A FREE GPU. used_vram_gb=0 was honoured as authoritative
-- yet zero is this estimator's own "could not determine" sentinel, and it is
what the admin UI stores for a field the operator never filled in. A 27B
Q4_K_P with used_vram_gb=0 and measured_vram_gb=18.0 therefore estimated 0.00
GB against 8852 MiB of free VRAM. Nothing was evicted, every layer was aimed at
the GPU, the load failed and retried down a ladder -- all, 52, 39, 26 layers,
re-reading the weights at each rung -- for 11m50s, and settled with 39 of 66
layers on the CPU. The request then generated for another 19 minutes, 31m04s in
all, holding GPU ownership the whole time: every other model queued behind it,
which is what made speech-to-text answer 500/503. The swap gate was working
correctly; it swapped the moment the owner finished.

A real measurement is better information than an unfilled field, so it now
wins. An operator who means "no weights on the GPU" has n_gpu_layers=0, which
is handled separately and still reserves nothing.

Worth recording for the next time this looks like a quantization problem: it
was not. Those weights are 4-bit on disk and the KV cache was already
q4_0/q4_0 with flash attention -- about 2.2 GB for n_ctx=32000. Both were at
their most aggressive setting while the model sat on the CPU.

Co-Authored-By: default avatarClaude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S8LAP3ueNzQJtwzhgVbq66
parent 66c3d7eb
Loading
Loading
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment