Make video projects, with a moving channel split as the first video effect

A project can now be a clip: Setup has a Video switch with a length, a
frame rate and presets that set the canvas too (Instagram story, reel and
feed video, TikTok / YouTube Short, Square loop, Full HD clip). The preview
renders the whole clip, shrunk to a memory budget, and loops it with
play/pause and a scale; Save As... renders it again at full size and pipes
the frames into ffmpeg as .mp4, .mov, .mkv, .webm or .gif, with a progress
window that can cancel. --duration, --fps and --video-preset do the same
from the command line.

Effects learn about time through FrameTime and Effect::renderFrame, which
falls back to render, so nothing that holds still changes. Channel split
now sways, shakes and rolls a tracking bar down the picture in a video; its
motion params are marked forVideo() and hidden in a still project, and a
still renders byte for byte as before. renderFrames starts every frame
from the same seed and renders the still stages ahead of the first moving
one only once. The version moves to 0.6.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Si
2026-09-26 11:22:01 +02:00
co-authored by Claude Opus 5.5
parent c069de3566
commit 385617781e
26 changed files with 1868 additions and 39 deletions
+5
View File
@@ -40,6 +40,11 @@ public:
// which is what an effect compositing the image needs.
static Image load(const std::string& path, std::vector<std::uint8_t>* alphaOut = nullptr);
// A copy shrunk so that its longer side is at most `maxSide`, each pixel
// the average of the ones it covers; an image already that small comes
// back as it is. For previews: nothing rendered goes through it.
Image scaledToFit(int maxSide) const;
// Encodes by file extension; png is used when the extension is unknown.
void save(const std::string& path) const;