On this page:
26.1 Render the frames
26.2 Encode an MP4
26.3 Keep file-writing commands separate
9.3

26 Save frames and make a video🔗ℹ

Use animation from the Quick Start. Until now, it has only been a value in memory. Rendering draws pictures. Encoding combines those pictures into a movie. These are two separate operations.

The documentation evaluator reconstructs the Quick Start Scene privately so the examples below remain executable without writing any output files:

Before writing files, you can still inspect the Scene directly:

> (scene-duration animation)

3/2

> (scene->pict animation 1)

image

26.1 Render the frames🔗ℹ

An output frame is one picture. The frame rate, or FPS, says how many of those pictures the movie shows each second.

The frame grid is pure data, so the manual can check it without creating PNG files. A 1.5-second Scene sampled at 30 FPS has 45 frames:

> (scene-frame-count animation #:fps 30)

45

The frame indices are therefore 0 through 44. Frame 44 is sampled at 22/15, or 22/15 seconds:

> (frame-index->time 44 #:fps 30)

22/15

The next grid time would be exactly 1.5 seconds, but there is no frame 45 in this Scene:

> (frame-index->time 45 #:fps 30)

3/2

To actually write those 45 numbered PNG files, use:

(eval:alts
 (render-frames! animation "out/circle-frames" #:fps 30)
 (void
  (lambda ()
    (render-frames! animation "out/circle-frames" #:fps 30))))

The manual displays the real call, but evaluates only the dormant lambda. Thus the binding is checked while the documentation build performs no file output. Use an unused output directory when you run the command yourself.

The exact mathematical endpoint, 1.5 seconds, is not another output frame. The final half-second hold is why the viewer has time to see the completed movement before the Scene ends.

26.2 Encode an MP4🔗ℹ

Encoding needs FFmpeg installed on the render machine. It is not needed just to sample a Scene, show a Pict, or compute the frame grid.

After rendering the PNG sequence, encode it with:

(eval:alts
 (encode-mp4! "out/circle-frames" "out/circle.mp4" #:fps 30)
 (void
  (lambda ()
    (encode-mp4! "out/circle-frames" "out/circle.mp4" #:fps 30))))

Again, the displayed expression is the command you run. During the manual build only the dormant lambda is created, so Scribble does not launch FFmpeg.

Use the same FPS for rendering and encoding. Otherwise, the same sequence of frames will be played at a different rate. Open "out/circle.mp4" in a video player after encoding it.

26.3 Keep file-writing commands separate🔗ℹ

The example file describes the animation; the commands above request files. Keeping them separate lets a preview, another module, or a test load the example without starting an encoder.

This separation is also why the Guide can execute the Scene and frame-grid examples while leaving the two external effects dormant. Later, Organize a source program shows how to organize longer source files. There is no need to learn that machinery for this movie.

Continue with Build a small scene for native Scene composition, or Make a slide and give it time for layout-based lessons.