crates/veilvoice-video/src/frames.rs
veilvoice-video · 686 lines · read the source here · or on GitHub
The video's pictures, and how many of them there really are.
What this finishes
crate::ffmpeg::command has always known how to turn a directory of pictures into a video file. Nothing filled the directory, so what a render produced was veiled audio over a black picture, and the roadmap row said so rather than letting somebody find out by playing the file.
This fills it, with crate::raster for the pixels and crate::font for the names.
A frame is written when the picture changes, not thirty times a second
An hour at thirty frames a second is 108,000 pictures. Written out at 1080p that is gigabytes of intermediate files to make one video, and almost all of them are identical to the one before.
So the frame rate decides when the picture is looked at, and a new file is written only when what it would contain has actually changed. Three things can change it, and Signature is exactly those three:
- the playhead, which moves one pixel at a time and not one frame at a time,
- the level bars, which move when the envelope column changes,
- who is lit, which changes at a turn boundary.
On a 1920-wide waveform over an hour the playhead moves a pixel about every two seconds, so runs of fifty-odd identical frames collapse into one file held for the length of the run. That is not a guess: plan reports how many pictures it actually produced against how many frames the video has, and a caller can show the ratio.
A short recording saves nothing, and should not. The playhead crosses the whole waveform however long the recording is, so under about forty seconds it moves more than a pixel per frame and every frame is genuinely a different picture. The saving arrives with length, which is exactly where it was needed.
This is why the ffmpeg command is a concat list rather than a numbered sequence. image2 gives every file the same duration; a held frame needs its own. See crate::ffmpeg::concat_command.
What the video cannot draw that the page can
Names outside printable ASCII. The page is markup and uses whatever face the reader's machine has; this has one face, written here, for the reasons crate::font gives. A name it cannot draw comes out as open boxes and is named in the notes, because a person who typed a name in Cyrillic should be told before they render an hour of video rather than after.
In plain words
This draws the pictures the video is made of.
It only draws a new one when something on screen has actually moved, which for a long recording is a tiny fraction of the frames the video has, so a render writes hundreds of pictures rather than hundreds of thousands.
WHAT THIS FILE CONTAINS
686 lines defining 7 functions (4 public), 5 types and 0 constants. Everything below is read out of the source, so it cannot disagree with the code.
The types it owns.
struct Signatureline 76 · What decides whether two moments look the same.struct Frameline 109 · One picture, and how long the video shows it for.struct Planline 118 · The pictures a render will write, worked out without drawing any of them.struct Notesline 187 · What a drawn frame carried with it.struct Writtenline 375 · What a written sequence produced.
What happens when it runs. These are the ways in: public, and nothing else in this file calls them, so they are what an outside caller reaches first.
Plan::savingline 133 · How many pictures were saved by holding the ones that did not change.writeline 394 · Draw and write the whole sequence into directory.
reachesdraw,plan,dim,draw_wave,at
WHAT CALLS WHAT
The functions this file defines, and the calls between them. An edge means the callee's name appears, called, inside the caller's body. This is a syntactic reading, not a type-resolved one.
The same graph as Mermaid source
%%{init: {"theme":"base","themeVariables":{"background":"#1a1b26","primaryColor":"#1f2335","primaryTextColor":"#c0caf5","primaryBorderColor":"#7aa2f7","secondaryColor":"#16161e","tertiaryColor":"#16161e","lineColor":"#737aa2","textColor":"#c0caf5","mainBkg":"#1f2335","nodeBorder":"#7aa2f7","clusterBkg":"#16161e","clusterBorder":"#2f3549","fontFamily":"ui-monospace, SFMono-Regular, Consolas, monospace","fontSize":"14px"}}}%%
flowchart TD
n_at["Signature::at<br/>line 86"]
n_saving(["Plan::saving<br/>line 133"])
n_plan["plan<br/>line 146"]
n_draw["draw<br/>line 200"]
n_dim["dim<br/>line 336"]
n_draw_wave["draw_wave<br/>line 349"]
n_write(["write<br/>line 394"])
n_draw --> n_dim
n_draw --> n_draw_wave
n_plan --> n_at
n_write --> n_draw
n_write --> n_plan
click n_at href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/frames.rs#L86" "open the source"
click n_saving href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/frames.rs#L133" "open the source"
click n_plan href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/frames.rs#L146" "open the source"
click n_draw href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/frames.rs#L200" "open the source"
click n_dim href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/frames.rs#L336" "open the source"
click n_draw_wave href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/frames.rs#L349" "open the source"
click n_write href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-video/src/frames.rs#L394" "open the source"
classDef entry fill:#1f2335,stroke:#7aa2f7,color:#c0caf5
class n_saving,n_write entry
classDef api fill:#1f2335,stroke:#7dcfff,color:#c0caf5
class n_plan,n_draw api
classDef helper fill:#1f2335,stroke:#bb9af7,color:#c0caf5
class n_at,n_dim,n_draw_wave helper
This site loads no third-party script, so it cannot run Mermaid; the diagram above is the same nodes and edges drawn by the generator instead. GitHub renders the source below directly.
ITEMS
| Item | Line | Documentation |
|---|---|---|
Signature struct | 76 | What decides whether two moments look the same. |
Signature::at fn | 86 | |
Frame pub struct | 109 | One picture, and how long the video shows it for. |
Plan pub struct | 118 | The pictures a render will write, worked out without drawing any of them. |
Plan::saving pub fn | 133 | How many pictures were saved by holding the ones that did not change. |
plan pub fn | 146 | Work out which moments need a picture. |
Notes pub struct | 187 | What a drawn frame carried with it. |
draw pub fn | 200 | Draw the picture at at_secs. |
dim fn | 336 | Mix colour towards background, keeping amount of it. |
draw_wave fn | 349 | The envelope as filled columns inside the waveform's box. |
Written pub struct | 375 | What a written sequence produced. |
write pub fn | 394 | Draw and write the whole sequence into directory. |