Nodes/ComfyUI PenPlotter/SVG to MP4 Animation
ComfyUI Node

SVG to MP4 Animation

SVG to MP4 Animation

By wouterverweirder·Created about a year ago·Updated 4 months ago· 0
SVG to MP4 Animation
    • video
    svg
    speed_px_per_sec400
    max_duration_seconds30.0
    fps30
    out_width1280
    out_height720
    bg_color#fafafa
    freeze_final_seconds1.0
    stroke_width1.0

    Everyone loves watching a plotter draw - the lines appearing in order is pure ASMR. SVG to MP4 Animation makes that video without a plotter: it takes an SVG string and renders a line-drawing animation where each stroke is drawn in sequence, then returns it as a ComfyUI VIDEO. You can preview it in the graph, save it, or feed it to Video to Submission File and upload it to the plotter service. The output is a great proof-of-work to pair with a real plot.

    The clever - and fiddly - part is how it renders. There's no server-side encoder here. The Python node sends the SVG plus your settings to the browser, where JavaScript renders each frame using WebCodecs' VideoEncoder and muxes the result into an MP4 with the mp4-muxer library. The browser then POSTs the finished file back to a route the pack registers on ComfyUI's server, and only then does the node unblock and return. It's rendering on your GPU-accelerated browser tab instead of the Python process, which is why it's fast - and also why it has a hard dependency on a live tab.

    How it works

    The node figures out the drawing order and speed from your settings. speed_px_per_sec (default 400) is how fast the "pen" travels along the lines, and the code will silently raise it if the animation would exceed max_duration_seconds (default 30) - that's the cap you set to stop a huge drawing from producing a marathon video. fps (default 30), out_width/out_height (default 1280×720), bg_color (default #fafafa), stroke_width (default 1) and freeze_final_seconds (default 1, a pause at the end so the finished drawing is readable) round out the controls.

    The render itself is dash-offset trickery: each path gets a stroke-dash offset that animates as its time slice arrives, so lines grow along their length in plot order. The node blocks on a threading event until the browser reports the MP4 back, with a generous timeout (animation length + freeze + two minutes of slack).

    The two things that catch people:

    • The ComfyUI tab must stay open. "Timed out waiting for browser to render MP4. Is the ComfyUI tab open?" is the actual error message. Background tabs usually survive, but closing the tab kills the job.
    • svg expects a forceInput string - wire it from Optimize SVG with vpype or anywhere you have SVG markup, not from a text-file path.

    Install

    It's in the ComfyUI PenPlotter pack. ComfyUI Manager → search "ComfyUI PenPlotter", or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/wouterverweirder/comfyui-penplotter
    

    Restart ComfyUI. The browser-side pieces (mp4-muxer.mjs, the render scripts) are bundled in the pack's web/ directory. Python-side you get the usual requirements - numpy>=2.3.4, opencv-python, numba, vpype, websockets, requests, qrcode[pil], AxiDraw API - with websockets doing the heavy lifting for the browser round-trip.

    Common issues

    • "Timed out waiting for browser to render MP4" - the tab was closed, backgrounded too aggressively, or the browser blocked the encoder. Keep the tab focused and rerun.
    • "SVG parse error" - your SVG is malformed for the browser's parser. Run it through Optimize SVG with vpype first; it normalizes a lot of sloppy markup.
    • Rendering looks wrong (lines popping in out of order) - that's usually an SVG with groups/transforms the simple parser mishandles. Flatten transforms before animating.
    • Cancel hangs - the pack's interrupt hook wakes waiting MP4 jobs, so Cancel should return promptly. If it doesn't, close the browser tab; the Python side has a timeout.

    This is the pack's most ambitious node - encoding video in the browser from inside ComfyUI is genuinely novel - and the price of that cleverness is that it needs your browser to cooperate. When it works, it's the most shareable thing the pack produces.

    CategoryPen Plotter

    Inputs (9)

    NameTypeDefaultDescription
    svgSTRING
    speed_px_per_secoptINT4001–10000
    max_duration_secondsoptFLOAT30.01–600
    fpsoptINT301–120
    out_widthoptINT128016–7680
    out_heightoptINT72016–4320
    bg_coloroptSTRING#fafafa
    freeze_final_secondsoptFLOAT1.00–60
    stroke_widthoptFLOAT1.00–100

    Outputs (1)

    NameTypeDescription
    videoVIDEO