#`@remotion/p5` Deprecated?

1 messages · Page 1 of 1 (latest)

flint lantern
flint lantern
#

P5.js integration with Remotion was simpler than expected.

While P5 has its own "game loop", we override it by using Remotion's currentFrame to update the scene instead of p5.frameCount. This creates two separate loops running simultaneously. Ideally, we'd directly control P5's loop from Remotion, allowing a single, synchronized loop. But have not figured out that (yet).

import { ReactP5Wrapper, Sketch, SketchProps } from '@p5-wrapper/react';
import { AbsoluteFill, useCurrentFrame, useVideoConfig } from 'remotion';
import { z } from 'zod';
import { TRemotionFC } from '@/types';

import { SP5Comp } from './schema';

type TSketchProps = SketchProps & {
    currentFrame: number;
    fps: number;
};

const sketch: Sketch<TSketchProps> = (p5) => {
    let currentFrame = 0;

    p5.setup = () => p5.createCanvas(600, 400, p5.WEBGL);

    p5.updateWithProps = (props) => {
        currentFrame = props.currentFrame;
        if (p5.frameRate() !== props.fps) {
            p5.frameRate(props.fps);
        }
    };

    p5.draw = () => {
        p5.background(250);
        p5.normalMaterial();
        p5.push();
        p5.rotateZ(currentFrame * 0.01);
        p5.rotateX(currentFrame * 0.01);
        p5.rotateY(currentFrame * 0.01);
        p5.plane(100);
        p5.pop();
    };
};

export const P5Comp: TRemotionFC<z.infer<typeof SP5Comp>> = (props) => {
    const { width, height, fps } = useVideoConfig();
    const currentFrame = useCurrentFrame();

    return (
        <AbsoluteFill className="bg-blue-500" style={{ width, height }}>
            <ReactP5Wrapper sketch={sketch} currentFrame={currentFrame} fps={fps} />
        </AbsoluteFill>
    );
};

P5Comp.schema = SP5Comp;
P5Comp.id = 'P5';
flint lantern
#

Update: It's also possible to make p5 controlled

export const sketch1: TRemotionSketch = (p5) => {
    let currentFrame = 0;
    let canvasWidth = 600;
    let canvasHeight = 400;

    p5.setup = () => {
        p5.createCanvas(canvasWidth, canvasHeight, p5.WEBGL);
        p5.noLoop(); // Disable automatic looping
    };

    p5.updateWithProps = ({ currentFrame: frame, canvas }) => {
        // Only redraw if the frame has changed
        if (currentFrame !== frame) {
            currentFrame = frame;
            p5.frameCount = currentFrame;
            p5.redraw();
        }

        if (canvasWidth !== canvas.width || canvasHeight !== canvas.height) {
            canvasWidth = canvas.width;
            canvasHeight = canvas.height;
            p5.resizeCanvas(canvasWidth, canvasHeight);
        }
    };

    p5.draw = () => {
        p5.background(250);
        p5.normalMaterial();
        p5.push();
        const rotation = p5.frameCount * 0.01;
        p5.rotateZ(rotation);
        p5.rotateX(rotation);
        p5.rotateY(rotation);
        p5.plane(100);
        p5.pop();
    };
};