# NodeJS with Fastify but want to make an canvas (p5js server-side)

**URL:** <https://discourse.processing.org/t/nodejs-with-fastify-but-want-to-make-an-canvas-p5js-server-side/24317>\
**Category:** Libraries\
**Created:** [October 3, 2020, 10:45pm UTC](https://discourse.processing.org/t/nodejs-with-fastify-but-want-to-make-an-canvas-p5js-server-side/24317 "2020-10-03T22:45:02Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![Bas950](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/bas950/32/10749_2.png) [@Bas950](https://discourse.processing.org/u/Bas950)\
**Post date:** [October 3, 2020, 10:45pm UTC](https://discourse.processing.org/t/nodejs-with-fastify-but-want-to-make-an-canvas-p5js-server-side/24317/1 "2020-10-03T22:45:02Z")

</div>

Hey so I am kinda new to this,  
But I am making an API using Fastify & NodeJS and want to add an overlay to a video, I have looked at multiple things and found that p5js would be the best for me, but I am failing to set it up. Could someone tell me how to set it up since there is no browser for me to do things on since its just an API, you request data and get data in return.

Thank you in advance!

FYI: I tried [https://www.npmjs.com/package/node-p5](https://www.npmjs.com/package/node-p5) too and its just super outdated…

---

<div class="post-metadata">

**Author:** ![tony](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/tony/32/949_2.png) [@tony](https://discourse.processing.org/u/tony)\
**Post date:** [October 6, 2020, 7:08am UTC](https://discourse.processing.org/t/nodejs-with-fastify-but-want-to-make-an-canvas-p5js-server-side/24317/2 "2020-10-06T07:08:44Z")

</div>

Really interesting, I never heard of p5 on the server side, as it was originally meant for client side graphics.

Judging by the NPM page, it sounds like you could, say, generate custom pngs in response to a quart but I don’t know how applicable that might be to a video overlay, in that the video itself would be streamed from the server.

The way most people make an overlay with p5 is to pipe it in as a stream, then, client side, draw over it, within the canvas

What exactly are you trying to do?

---

<div class="post-metadata">

**Author:** ![Bas950](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/bas950/32/10749_2.png) [@Bas950](https://discourse.processing.org/u/Bas950)\
**Post date:** [October 6, 2020, 1:20pm UTC](https://discourse.processing.org/t/nodejs-with-fastify-but-want-to-make-an-canvas-p5js-server-side/24317/3 "2020-10-06T13:20:46Z")

</div>

Thank you for your reply!  
Maybe I should’ve explained it a bit better xD  
But yea I want p5 on server side, I am creating an API that changes video to gif and more, but I would like the users to be able to add an “overlay” to their video, some pre-made and some custom. It will also include like animations if you have multiple vids etc. Thats why I found p5js to be the best for this case.

For the video stuff itself I found:

> **[examples | p5.js](https://p5js.org/examples/dom-video-canvas.html)**

  

> **[examples | p5.js](https://p5js.org/examples/dom-video.html)**

And for exporting it I would just basically get a picture of every frame.

So in the end I would need to get pictures of each frame of the video with animations/overlay.

I hope this explains it a bit better! 🙂

---

<div class="post-metadata">

**Author:** ![tony](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/tony/32/949_2.png) [@tony](https://discourse.processing.org/u/tony)\
**Post date:** [October 7, 2020, 3:33am UTC](https://discourse.processing.org/t/nodejs-with-fastify-but-want-to-make-an-canvas-p5js-server-side/24317/4 "2020-10-07T03:33:33Z")

</div>

Ah okay interesting. That old library seems like the place to start. Im not super familiar with Nodejs, especially what goes on under the hood, so I can’t give you great advice.

My initial thought was, create it client side, get the exporting working, then port over to node and cross your fingers haha.

---

<div class="post-metadata">

**Author:** ![Bas950](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/bas950/32/10749_2.png) [@Bas950](https://discourse.processing.org/u/Bas950)\
**Post date:** [October 17, 2020, 9:49pm UTC](https://discourse.processing.org/t/nodejs-with-fastify-but-want-to-make-an-canvas-p5js-server-side/24317/5 "2020-10-17T21:49:53Z")

</div>

So if I made my own node-p5 now, but with saving the canvas I get this error:

```auto
TypeError: get_URL(...).createObjectURL is not a function
    at new FileSaver (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:19390:44)
    at Object.saveAs (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:19406:26)
    at Object._main.default.downloadFile (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:70088:34)
    at https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:65134:39
    at D:\CodeEnSHiz\project\API\node_modules\jsdom\lib\jsdom\living\nodes\HTMLCanvasElement-impl.js:80:9

```

Is this a p5 issue? Or is this an issue I can fix?

---

<div class="post-metadata">

**Author:** ![tony](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/tony/32/949_2.png) [@tony](https://discourse.processing.org/u/tony)\
**Post date:** [October 18, 2020, 5:25pm UTC](https://discourse.processing.org/t/nodejs-with-fastify-but-want-to-make-an-canvas-p5js-server-side/24317/6 "2020-10-18T17:25:30Z")

</div>

`createObjecrURL()` is a client-side method, part of the web-api.

In the past, I’ve used it to immediately display a users new profile pic. Instead of waiting for the upload, processing, and download, I used `createObjectURL()` to create a local ref that an `href` could understand.

That seems to be what your code is trying to do. Maybe see if you can tweak a line somewhere to instead use the node-servers local filesystem?

---

<div class="post-metadata">

**Author:** ![Bas950](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/bas950/32/10749_2.png) [@Bas950](https://discourse.processing.org/u/Bas950)\
**Post date:** [October 18, 2020, 7:23pm UTC](https://discourse.processing.org/t/nodejs-with-fastify-but-want-to-make-an-canvas-p5js-server-side/24317/7 "2020-10-18T19:23:29Z")

</div>

If you can contact me on discord (Bas950#0950) I can show you what I am doing,  
right now all I have is setting up JSDOM

```auto
const dom = new JSDOM(
			`
			<head>
				<script src="https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js"></script>
				<script>${readFileSync("sketch.js")}</script>
			</head>
			<body>
				<div>foo</div>
			</body>`,
			{
				runScripts: "dangerously",
				resources: "usable",
				pretendToBeVisual: true
			}
		);

```

and then sketch.js:

```auto
console.log("abc");

function setup() {
	let c = createCanvas(100, 100);
	console.log("canvas created");
	console.log(c);
	background(255, 0, 0);
	console.log("background set");
	saveCanvas(c, "myCanvas", "png");
	console.log("saved");
}

```

everything is working correctly only saving is just not working…

---

<div class="post-metadata">

**Author:** ![tony](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/tony/32/949_2.png) [@tony](https://discourse.processing.org/u/tony)\
**Post date:** [October 19, 2020, 4:17pm UTC](https://discourse.processing.org/t/nodejs-with-fastify-but-want-to-make-an-canvas-p5js-server-side/24317/8 "2020-10-19T16:17:12Z")

</div>

Hm, one last thought; maybe you can try writing your own `save()` function?

If the canvas holds a canvas object, perhaps you can save it directly, like in this tutorial:

> **[How to create and save an image with Node.js and Canvas](https://flaviocopes.com/canvas-node-generate-image/)**
>
> A story of how I improved my Twitter cards

---

<div class="post-metadata">

**Author:** ![Bas950](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/bas950/32/10749_2.png) [@Bas950](https://discourse.processing.org/u/Bas950)\
**Post date:** [October 20, 2020, 5:57pm UTC](https://discourse.processing.org/t/nodejs-with-fastify-but-want-to-make-an-canvas-p5js-server-side/24317/9 "2020-10-20T17:57:30Z")

</div>

Well I would need to import fs into the sketch file then…  
but yea that doesnt work I keep getting errors on that and get linked to:

> **[examples | p5.js](https://p5js.org/examples/data-variable-scope.html)**

---

<div class="post-metadata">

**Author:** ![Bas950](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/bas950/32/10749_2.png) [@Bas950](https://discourse.processing.org/u/Bas950)\
**Post date:** [November 1, 2020, 12:53am UTC](https://discourse.processing.org/t/nodejs-with-fastify-but-want-to-make-an-canvas-p5js-server-side/24317/10 "2020-11-01T00:53:09Z")

</div>

FYI: Got it working 🙂

> [@Loading video from base64, putting it on the canvas and adding stuff to each frame, then get the base64 of the new video with canvas stuff](https://discourse.processing.org/t/loading-video-from-base64-putting-it-on-the-canvas-and-adding-stuff-to-each-frame-then-get-the-base64-of-the-new-video-with-canvas-stuff/25090):
>
> Could someone help me with this: Loading video from base64, putting it on the canvas and adding stuff to each frame, then get the base64 of the new video with canvas stuff at the end. Already stuck at loading the video from base64… confused To get the base64 of the canvas at the end can maybe use c.canvas.toDataURL("video/gif") or c.canvas.toDataURL("video/mp4") but not sure, can’t even load the vid in yet confused

---

<div class="post-metadata">

**Author:** ![tony](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/tony/32/949_2.png) [@tony](https://discourse.processing.org/u/tony)\
**Post date:** [November 15, 2020, 8:01pm UTC](https://discourse.processing.org/t/nodejs-with-fastify-but-want-to-make-an-canvas-p5js-server-side/24317/11 "2020-11-15T20:01:08Z")

</div>

Nice! What was the fix?

---

<div class="post-metadata">

**Author:** ![Bas950](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/bas950/32/10749_2.png) [@Bas950](https://discourse.processing.org/u/Bas950)\
**Post date:** [November 20, 2020, 11:35pm UTC](https://discourse.processing.org/t/nodejs-with-fastify-but-want-to-make-an-canvas-p5js-server-side/24317/12 "2020-11-20T23:35:49Z")

</div>

Loading in JSDOM:

```auto
const virtualConsole = new VirtualConsole(),
      dom = new JSDOM(
        `
          <head>
            <script src="https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js"></script>
            <script>${readFileSync("util/sketch.js")};</script>
          </head>
          <body>
            <div>foo</div>
          </body>`,
        {
          virtualConsole,
          runScripts: "dangerously",
          resources: "usable",
          pretendToBeVisual: true
        }
      );
    virtualConsole.sendTo(console);

```

Then just do the p5js stuff in the sketch file  
And to send the data back I send back each frame as png  
and sending it back via JSDOM virtual console.

```auto
console.info(c.canvas.toDataURL("image/png"))

```

---

<div class="post-metadata">

**Author:** ![Bas950](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/bas950/32/10749_2.png) [@Bas950](https://discourse.processing.org/u/Bas950)\
**Post date:** [November 21, 2020, 12:01am UTC](https://discourse.processing.org/t/nodejs-with-fastify-but-want-to-make-an-canvas-p5js-server-side/24317/13 "2020-11-21T00:01:07Z")

</div>

@tony the only thing is it wont let me load videos…  
So I think I will need to get each frame and then edit each frame…  
But it takes like 2 seconds to load each frame so do you maybe know a fix for this:

```auto
Error: Not implemented: HTMLMediaElement.prototype.load
    at module.exports (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\browser\not-implemented.js:9:17)
    at HTMLVideoElementImpl.load (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\living\nodes\HTMLMediaElement-impl.js:110:5)
    at HTMLVideoElement.load (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\living\generated\HTMLMediaElement.js:111:34)
    at _main.default.MediaElement.play (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:60539:24)
    at setup (about:blank:13:11)
    at _setup (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:48784:27)
    at p5._runIfPreloadsAreDone (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:48722:27)
    at p5._start (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:48707:25)
    at new p5 (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:49057:22)
    at _globalInit (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:48197:17)
    at processTicksAndRejections (internal/process/task_queues.js:93:5) undefined
Error: Not implemented: HTMLMediaElement.prototype.play
    at module.exports (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\browser\not-implemented.js:9:17)
    at HTMLVideoElementImpl.play (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\living\nodes\HTMLMediaElement-impl.js:116:5)
    at HTMLVideoElement.play (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\living\generated\HTMLMediaElement.js:145:60)
    at _main.default.MediaElement.play (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:60540:34)
    at setup (about:blank:13:11)
    at _setup (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:48784:27)
    at p5._runIfPreloadsAreDone (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:48722:27)
    at p5._start (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:48707:25)
    at new p5 (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:49057:22)
    at _globalInit (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:48197:17)
    at processTicksAndRejections (internal/process/task_queues.js:93:5) undefined
Error: Uncaught [TypeError: Cannot read property 'functionName' of undefined]
    at reportException (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\living\helpers\runtime-script-errors.js:62:24)
    at innerInvokeEventListeners (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:333:9)
    at invokeEventListeners (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:274:3)
    at EventTargetImpl._dispatch (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:221:9)
    at reportAnError (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\living\helpers\runtime-script-errors.js:31:12)
    at reportException (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\living\helpers\runtime-script-errors.js:58:19)
    at runAnimationFrameCallbacks (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\browser\Window.js:462:13)
    at Timeout.<anonymous> (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\browser\Window.js:438:11)
    at listOnTimeout (internal/timers.js:551:17)
    at processTimers (internal/timers.js:494:7) TypeError: Cannot read property 'functionName' of undefined
    at processStack (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:46279:72)
    at fesErrorMonitor (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:46395:35)
    at callTheUserObjectsOperation (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\living\generated\EventListener.js:26:30)
    at innerInvokeEventListeners (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:318:25)
    at invokeEventListeners (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:274:3)
    at EventTargetImpl._dispatch (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:221:9)
    at reportAnError (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\living\helpers\runtime-script-errors.js:31:12)
    at reportException (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\living\helpers\runtime-script-errors.js:58:19)
    at runAnimationFrameCallbacks (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\browser\Window.js:462:13)
    at Timeout.<anonymous> (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\browser\Window.js:438:11)
Error: Uncaught [TypeError: The first argument must be an object]
    at reportException (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\living\helpers\runtime-script-errors.js:62:24)
    at runAnimationFrameCallbacks (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\browser\Window.js:462:13)
    at Timeout.<anonymous> (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\browser\Window.js:438:11)
    at listOnTimeout (internal/timers.js:551:17)
    at processTimers (internal/timers.js:494:7) TypeError: The first argument must be an object
    at CanvasRenderingContext2D.ctx.<computed> [as drawImage] (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\living\nodes\HTMLCanvasElement-impl.js:124:17)
    at _main.default.Renderer2D.image (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:51051:35)
    at p5._main.default.image (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:66018:28)
    at draw (about:blank:23:5)
    at p5._main.default.redraw (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:56238:19)
    at _draw (https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js:48842:25)
    at runAnimationFrameCallbacks (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\browser\Window.js:460:13)
    at Timeout.<anonymous> (D:\CodeEnSHiz\HiddenProjectName\API\node_modules\jsdom\lib\jsdom\browser\Window.js:438:11)
    at listOnTimeout (internal/timers.js:551:17)
    at processTimers (internal/timers.js:494:7)

```

Code used:

```auto
let c
let outputFrames = [];
let video;
function preload() {
	video = createVideo(bla);
	video.hide();
}
function setup() {
	c = createCanvas(576, 1024);
	frameRate(30);
	video.play();
	video.volume(0);
	video.onended(() => {
		noLoop();
		console.log("done");
		sendData();
	});
}
function draw() {
	background(220);
	image(video, 0, 0);
	textSize(32);
	text(video.time(), 10, 30);
	outputFrames.push(c.canvas.toDataURL("image/png"));
}

```

NOTE: the inputted video is base64 data.

---

<div class="post-metadata">

**Author:** ![DCsan](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/dcsan/32/12710_2.png) [@DCsan](https://discourse.processing.org/u/DCsan)\
**Post date:** [April 5, 2021, 12:08am UTC](https://discourse.processing.org/t/nodejs-with-fastify-but-want-to-make-an-canvas-p5js-server-side/24317/14 "2021-04-05T00:08:04Z")

</div>

using JSDOM basically is mocking up the whole HTML/CSS rendering stack. In fact all we really need is the canvas for p5js to work (unless you’re using a webGL renderer of course). Have you looked at node-canvas? that would be much more lightweight I believe.

But I’m not sure how things like the render loop are used eg `draw()` getting called in the JS runtime after P5 loads it. It’s not just a canvas API it’s a bunch of engine calls. Similarly how P5 is often polluting the global JS namespace with it’s commands. Perhaps that’s what the `node-p5` package is handling?

I’m just looking for a simple example to render a P5 canvas to a file… 😃

---

<div class="post-metadata">

**Author:** ![Bas950](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/bas950/32/10749_2.png) [@Bas950](https://discourse.processing.org/u/Bas950)\
**Post date:** [April 5, 2021, 2:24pm UTC](https://discourse.processing.org/t/nodejs-with-fastify-but-want-to-make-an-canvas-p5js-server-side/24317/15 "2021-04-05T14:24:35Z")

</div>

I could post my new solution to NPM or something like that if you want,  
its basically just a class and you can .exec p5 commands etc.

---

<div class="post-metadata">

**Author:** ![DCsan](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/dcsan/32/12710_2.png) [@DCsan](https://discourse.processing.org/u/DCsan)\
**Post date:** [April 6, 2021, 6:56am UTC](https://discourse.processing.org/t/nodejs-with-fastify-but-want-to-make-an-canvas-p5js-server-side/24317/16 "2021-04-06T06:56:44Z")

</div>

yeah i’d love to compare? Or just open the repo and i’ll fork it? I’m @dcsan on github too.
