A complete openFrameworks digital art template with dual-mode video recording
FrameworkCanvas combines the power of openFrameworks with a streamlined make-based workflow, perfect for digital artists who want both interactive creativity and high-quality video output.
- Two Render Lanes: write sketches in p5.js (
sketch.js, headless Chromium) or openFrameworks C++ (sketch.cpp); same commands, same outputs - Dual-Mode Operation: Switch between interactive app and video/GIF recording modes (C++ lane)
- Zero-Config Media Generation: Frame-by-frame TGA export with automatic MP4/GIF creation
- Multiple Output Formats: Generate high-quality MP4 videos or web-friendly animated GIFs
- Artist-Friendly Workflow: Simple
make artcommands with preset formats - Neovim + Make Integration: No Xcode required - pure terminal workflow
- Customizable Output: Configure resolution, framerate, duration, and quality
- Self-Contained: Everything managed through a single, powerful Makefile
# Clone and setup
git clone <your-repo>
cd FrameworkCanvas
# Check/locate your openFrameworks install (run this once after cloning)
make setup
# Interactive mode - opens a live window that loops your sketch in real time
make run # default C++ sketch
make run SKETCH=web-demo # a web (p5.js) sketch
# Look at your work before rendering
make sheet # contact sheet of the whole animation -> out/demo/sheet.png
make frame T=2.5 # one full-size still
# Create a video - generates MP4 automatically (output lands in out/<sketch>/)
make video
# Create an animated GIF - perfect for web sharing
make gif
# Quick presets
make instagram # 1080x1080 Instagram feed post
make gif-web # 800x600 optimized GIF
make 4k # 3840x2160 for high quality
make square # 1080x1080 for general social mediaYour art lives in sketches/<name>/sketch.js (p5.js) or sketches/<name>/sketch.cpp
(openFrameworks). Start from sketches/_template-web or sketches/_template, or copy
an example from sketches/_examples/. The file name picks the render lane. For the web
lane run make setup-web once first. Select a sketch with SKETCH=<name>
(default demo). See CLAUDE.md for the full workflow, which is written to
work equally well for people and for coding agents.
make # Build interactive .app
make run # Build and run interactive app
make video # Create MP4 video (default settings)
make gif # Create animated GIF (smaller, web-friendly)
make art # Alias for 'make video'
make help # Show complete usage guideInstagram Optimized:
make instagram # 1080x1080 feed post (most common)
make instagram-story # 1080x1920 stories & reels
make instagram-reel # 1080x1920 reel format
make instagram-portrait # 1080x1350 portrait postVideo (MP4):
make hd # 1920x1080 @ 30fps
make 4k # 3840x2160 @ 30fps
make square # 1080x1080 @ 30fps
make portrait # 1080x1920 @ 30fpsGIF (Optimized for Web):
make gif-small # 400x400 @ 15fps - tiny file size
make gif-web # 800x600 @ 20fps - balanced quality/size
make gif-square # 500x500 @ 24fps - social media ready
make gif-instagram-feed # 1080x1080 @ 24fps - Instagram ready
make gif-instagram-story # 1080x1920 @ 24fps - Story format# Override any video setting on the fly
make video VIDEO_WIDTH=2560 VIDEO_HEIGHT=1440 VIDEO_FPS=60 VIDEO_DURATION=15
# Custom GIF with specific settings
make gif VIDEO_WIDTH=600 VIDEO_HEIGHT=400 VIDEO_FPS=12 GIF_FILENAME=my_art.gif
# Custom filenames
make video VIDEO_FILENAME=my_artwork.mp4
make gif GIF_FILENAME=demo_animation.gifEdit config.make to set your preferred defaults:
# Output mode: "app" for interactive, "video" for recording
OUTPUT_TYPE = video
# Video settings
VIDEO_WIDTH = 1920
VIDEO_HEIGHT = 1080
VIDEO_FPS = 30
VIDEO_DURATION = 10
# Optional. Default is <sketch>.mp4 / <sketch>.gif, written to out/<sketch>/
# VIDEO_FILENAME = my_video.mp4
# GIF_FILENAME = my_anim.gif
# FFmpeg path (if not in PATH)
FFMPEG = ffmpeg- openFrameworks 0.12.1+ - Download here
- Xcode Command Line Tools -
xcode-select --install - FFmpeg -
brew install ffmpeg(for video generation) - Node 20+ - only for the web (p5.js) lane; then run
make setup-web - C++17 compatible compiler
FrameworkCanvas/
βββ sketches/
β βββ demo/ # default C++ sketch (+ params.json)
β βββ web-demo/ # default web (p5.js) sketch
β βββ _template/ # C++ template
β βββ _template-web/ # web template
β βββ _examples/ # C++: particles, noise-field, shader, type; web: web-particles, web-noise
β βββ _bakeoff/ # the 10 sketches from the lane comparison
βββ src/
β βββ Sketch.h # the sketch contract (Ctx + Sketch)
β βββ harness/ # app, recorder, settings: not for sketch authors
βββ engines/web/ # web lane: puppeteer driver + p5 harness (not for sketch authors)
βββ docs/
β βββ OF_CHEATSHEET.md # openFrameworks 0.12.1 gotchas
β βββ P5_NOTES.md # p5.js under the harness
β βββ bakeoff.md # web vs C++ lane comparison and results
β βββ LLM_READINESS_PLAN.md
β βββ WEB_ENGINE_PLAN.md
βββ out/ # renders (git-ignored): out/<sketch>/...
βββ config.make # project configuration
βββ Makefile # build + media workflow
βββ CLAUDE.md # workflow guide for agents and people
Both lanes produce numbered frames, then share the same ffmpeg steps.
- Frame Generation: C++ lane: the app renders offscreen as fast as it can and saves each frame as uncompressed TGA. Web lane: headless Chromium steps the p5 sketch frame by frame and saves PNGs. Time comes from the frame index in both, so rendering speed never changes the result.
- H.264 Encoding: FFmpeg converts frames to high-quality MP4 with H.264 codec
- Cleanup: Temporary frames are automatically removed
- Output: Final video saved to
out/<sketch>/
- Frame Generation: Same frame sequence as video
- Palette Optimization: FFmpeg generates optimal color palette for better quality
- GIF Encoding: Two-pass process creates smooth, web-optimized animated GIF
- Cleanup: Temporary frames and palette files removed automatically
The demo animation features rotating colorful circles - perfect for testing or as a starting point for your own creations.
Which lane to use: web (p5.js) for most 2D work, C++ for custom shaders and heavy compute.
A 10-run comparison is in docs/bakeoff.md. Run make test-web to self-test
the web engine.
make run SKETCH=<name> previews any sketch live. Web sketches open a Chromium window that loops the clip at its real frame rate (the canvas is scaled to fit your screen). The extras below are C++ lane only.
- Real-time Preview: See your art as you create it
- Manual Recording: Press 'r' to start recording anytime
- Live Stats: FPS counter and frame information
- Responsive Controls: Full mouse and keyboard support
make clean-frames # Remove temporary frame files
make clean-video # Remove generated MP4s
make clean-gif # Remove generated GIF files
make clean-all # Clean everything (build + frames + videos + gifs)The app reads these environment variables (set by Makefile):
OUTPUT_TYPE- "app" or "video"VIDEO_WIDTH- Frame width in pixelsVIDEO_HEIGHT- Frame height in pixelsVIDEO_FPS- Frames per secondVIDEO_DURATION- Recording duration in secondsSEED,RENDER_START,RENDER_END,PARAMS_FILE,FRAMES_DIR- set by the Makefile; see CLAUDE.md
Web (p5.js) lane:
make setup-web # once
cp -r sketches/_template-web sketches/mything
make check SKETCH=mything # syntax check + render frame 0, prints OK or the error
make sheet SKETCH=mything # open out/mything/sheet.png
make video SKETCH=mything FORMAT=instagram-storyfunction setup() { createCanvas(ctx.w, ctx.h); }
function draw() {
background(10);
circle(width / 2, height / 2, min(width, height) * (0.3 + 0.05 * sin(ctx.progress * TWO_PI)));
}C++ (openFrameworks) lane:
cp -r sketches/_template sketches/mything
make check SKETCH=mything # compile only, prints OK or the errors
make sheet SKETCH=mything # open out/mything/sheet.png
make video SKETCH=mything FORMAT=instagram-storyA sketch is one class with a draw(const Ctx&) method. Animate from ctx.t (seconds) or
ctx.progress (0..1 over the clip, so sin(ctx.progress * TWO_PI * k) loops seamlessly),
and size things from ctx.w / ctx.h. Frame capture and timing are handled for you.
#include "Sketch.h"
class MySketch : public Sketch {
public:
void draw(const Ctx& ctx) override {
ofSetColor(255, 100, 200);
ofDrawCircle(ctx.w / 2.0f, ctx.h / 2.0f,
std::min(ctx.w, ctx.h) * (0.2f + 0.05f * std::sin(ctx.progress * TWO_PI)));
}
};
std::unique_ptr<Sketch> makeSketch() { return std::make_unique<MySketch>(); }Other useful make targets: make smoke (fail on blank output), make draft (fast low-res
MP4), make help. Per-sketch tunables go in sketches/<name>/params.json.
This is a template project designed to be forked and customized for your own digital art creations. Feel free to:
- Add new preset formats
- Extend the animation system
- Integrate additional openFrameworks addons
- Improve the build system
This project is open source and available under the MIT License.
Built with openFrameworks - A creative coding toolkit.
Video encoding powered by FFmpeg.
