A 40-second film printed in four riso inks: the TGV leaves Part-Dieu, runs down the Rhône valley and through Provence, and stops above the sea at L'Estaque. A camera sits on the tray the whole way. When the train stops, it takes the picture. No footage, no samples, no timeline editor: every frame and every sound is computed from the time.

It started with Window Seat, an open-source riso film by sevenevesai: a night train seen through one fixed window, the same glass of water on the sill, the world changing behind it. Canvas 2D, Web Audio, every frame a pure function of time. It is a beautiful piece, and the point was not to copy it.
So I kept the three ideas that make it work (a fixed frame, one object that never leaves, the world passing behind) and swapped everything else: the line between the two cities my photographs keep coming back to, Lyon and Marseille, and a camera on the tray instead of a glass of water. A photographer's trip ends on a picture, so the film does too.
There is no colour anywhere in the drawing code. Each scene is drawn four times, once per ink, into grayscale coverage canvases: yellow, fluorescent pink, medium blue and teal, the way a risograph master is cut for each drum. Orange is yellow under pink. The Mediterranean is teal over blue. Lavender is pink over blue.
Two rules carry the whole look. A near object clears itself out of every plate before it prints its own inks, so it owns its colour instead of mixing with the sky behind it. Light, haze and glints only ever add ink. A single WebGL2 pass then screens each plate into round dots at its own angle, knocks it a pixel or two out of register, starves a few dots, and multiplies it onto cream paper.
// Clear, then print:
// the shape owns its colour.
function solid(pl, cov, path) {
knock(pl, path); // paper on every plate
glaze(pl, cov, path); // then its own inks
}
// A cypress: teal over blue,
// never mixed with the sky.
solid(plates, { teal: 0.72, blue: 0.5 }, cypress);
// Sun on the sea: light only adds ink.
glaze(plates, { yellow: 0.8, pink: 0.3 }, glints); The journey is a speed profile of nine keys: standing at the platform, 1 500 px/s across the valley, braking to a stop at 34.4 seconds. Because every segment is a smoothstep, the distance travelled has an exact closed form, so any frame knows where the train is without replaying the ones before it. Every layer then moves at its own share of that distance: the Ventoux at a hundredth, the lavender rows faster the nearer they are, the catenary masts at full speed.
The world changes only when nobody can see it change. Lyon becomes the valley inside a tunnel, the valley becomes Provence behind a TGV passing the other way, and Provence becomes Marseille in a second tunnel. A test checks that each switch happens while the window is fully covered.



The soundtrack is synthesized sample by sample from the same clock as the picture. A rail joint clacks each time the distance travelled crosses one, twice per bogie, so the rhythm slows with the train and stops with it. The rumble follows the speed and closes in inside the tunnels. The other TGV tears past, panned from right to left on the frames where it crosses the window. The sea comes in once the train reaches Marseille.
Under all of it, a soft felt piano plays a lilting 6/8 in F major, each note a handful of partials that fade faster the higher they are. Its last chord lands on the shutter. Written naively it took 3.6 seconds to synthesize; with rotating phasors instead of a sine per sample it takes about one, while the first frame is on screen, so pressing play starts at once.


Marseille is composed for the moment the train stops: Notre-Dame de la Garde on her hill, the Frioul on the horizon, the sun's road on the sea, an umbrella pine keeping the right of the frame the way I would keep it. At 35.2 seconds the camera takes the picture. The button sinks, its screen goes black for a frame, a breath of paper-white crosses the glass.
Then nothing moves any more. Only ink leaves: the carriage fades off the paper, the window's rounded hole opens into a print's rectangle, and a caption is printed underneath. Drag the slider to compare the view from the seat with the print it became.
The first full pass had the right structure and a broken ending. Stills taken along the whole film showed that Marseille, the payoff, was the weakest scene. Notre-Dame de la Garde was off screen, because landmarks drifted with the tens of thousands of pixels the train had covered. The hill covered the whole sea. The pines read as lily pads floating on the water. The sun's road never printed, because its glints were thinner than the halftone screen. A catenary mast stood in the middle of the final print.
Each place is now framed at its own reference moment, so Marseille is exactly composed when the train stops. The glints are thick enough to print, the sun is a coral disc clear of the islands, and the masts are phased so the nearest one stands just outside the print. What is still rough: the lavender and the houses are naive, some clouds look like bubbles, and the mix of piano and rails deserves a real listen.

Because every frame is a pure function of time, exporting is just asking for them one by one. A headless Chrome opens the page, seeks each of the 1 200 frames at 30 fps, and pipes them to ffmpeg next to the soundtrack from the same synthesis. It takes 74 seconds. No frame is dropped, and the picture never drifts from the sound, because neither of them was ever played in real time.
After Window Seat by sevenevesai (MIT licence). Journey, drawing and sound written from scratch for this piece.