Repository navigation
Stream247 1.5.43
1.5.43 - 2026-09-02
Changed
-
The ticker runs. It used to be a dwell: one message held still, the next taking its place on a
timer, because the renderer redraws onSCENE_RENDER_INTERVAL_MS— 2000ms by default, floored at
1000ms — and a line drawn into the frame at that rate cannot crawl, it can only teleport 118px a
step. That reasoning was sound and it was about the wrong thing: the crawl was never the
rasteriser's job.ffmpeg moves it now, at the output frame rate, for nothing per frame. The line is rendered once
per programme as a transparent strip; a bed the size of the band's clear run does the clipping,
and as many copies of the strip as the bed needs are laid down a period apart, so the line tiles
the band continuously and enters at its right-hand edge. The period is held at the band's own
width, so a short notice sweeps across on its own rather than appearing four times side by side;
a line longer than the band already exceeds that and keeps its designed gap. Measured before any of it was written:
exactly 4px of travel per frame at 120px/s and 30fps, clipped to the band.All the messages join into one running line, so the automatic rotation is gone. The seconds
setting stops meaning how long a message stands and starts meaning how long one crossing of the
band takes, clamped into a legible 40-240px/s on the design grid and scaled with the frame. It is
now offered for a single notice as well as for several. The studio preview draws the line at
rest, because a still picture cannot show it moving.On air the band is drawn empty and belongs to the process rather than to the current text: a
ticker cleared mid-programme would otherwise take the band away and leave the line crawling over
bare video. A strip that fails to render leaves the renderer drawing the line at rest, so a
failure costs the motion and never the picture — and it now raises an incident, because the
fallback is quiet enough to hide: the band still draws and the line still appears, standing still
instead of running.The cost of rendering the strip once instead of feeding it is real and worth stating plainly: a
ticker edited mid-programme reaches the screen at the next block, where the dwell replaced it
within one render tick. The period the encoder moves the line by is derived from the ink's own
width, so a new text needs a new graph, and the graph is fixed for the life of the process. On a
channel playing assets that is a few minutes. On the standby slate or a live bridge, which run
until the selection changes, there may be no next block at all, and the only way to replace a
ticker is a playout restart — which interrupts the stream. The emergency banner is a separate
field still drawn on the two-second tick, so an actual emergency keeps its own way onto the
screen.
Fixed
-
The scene overlay filter was written out three times in
apps/worker/src/index.ts— for an
asset, for a live bridge and for the standby slate — and none of the three could be reached from
a test. They agreed with one another by luck. They now build one graph from one function, which
is also what let the ticker crawl reach all three instead of whichever was remembered. -
The crawl laid down exactly two copies of the strip, which tiles only a bed narrower than one
period. Measured on the ordinary case — "Welcome to the stream" at 1080p, 213px of ink in a
1722-wide band — the rightmost column ever painted was 665: a thousand pixels of permanently
black bar, and the next pass materialising a quarter of the way across the band every three
seconds instead of entering at its right edge, which is the teleport the crawl exists to remove.
The copy count now comes out of the ink:(K-1)*period + ink >= bandWidth. Found by review
before it shipped; the suite could not see it because its ffmpeg probe ran two seconds and one
wrap takes nearly seven. There is now a test that runs a whole period, and with the old two
copies it fails with 761px of dead band and a 593px jump. -
The strip's canvas was an estimate treated as a fact. A line of glyphs wider than 1.3 em — the
loaded face carries some at 2.02 — outgrew it and was silently CUT, so the crawl ran a period
that did not match its ink and the tail of the operator's text never reached air. The ink is now
measured against the canvas and the strip redrawn on a wider one when it has reached the edge. -
A ticker panel dragged in the studio during a programme moved the band and left the line crawling
where the band used to be, over bare video, until the next block: the ffmpeg graph is fixed when
the programme starts and the renderer was reading the placement live. In crawl mode the band is
now drawn at the placement the crawl was built against, so the two cannot part company. -
overlayends with its LONGEST input, not with the picture it is drawing onto. The crawl adds a
looped image and a colour source, both endless, so withoutshortest=1on the last overlay a
two-second programme produced thirteen minutes of output and was still running when the probe
killed it. The crawl now ends with the picture it draws onto, whenever that picture ends.Stated more carefully than it first was: this does not change when a playout process ends today.
On air the scene pipe never EOFs either, so the picture being drawn onto is itself endless and
the graph is bounded by nothing — exactly as it was before the crawl existed. What ends a
programme is the worker, through the duration bound or a stop. The first draft of this entry
claimed the channel would have hung at every boundary without it; that was measured against a
finite scene input and is not true of production.