i'm trying to write a node video app that generates frames using the canvas api (via node-canvas, the project's only npm dependancy right now), and writes it to ffmpeg via a stream to generate a video:
const { createCanvas } = require('canvas');
const { spawn } = require('child_process');
const fs = require('fs');
const canvas = createCanvas(1280, 720);
const ffmpeg = spawn('ffmpeg', [
'-y',
'-f', 'rawVideo',
'-vcodec', 'rawVideo',
'-pix_fmt', 'rgb24',
'-s', `${ canvas.width }x${ canvas.height }`,
'-r', '40',
'-i', '-', '-f', 'mp4',
'-q:v', '5',
'-an', '-vcodec', 'mpeg4', 'output.mp4',
]);
const ctx = canvas.getContext('2d');
ctx.font = '30px Prime';
ctx.fillStyle = 'blue';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('Hello Canvas', canvas.width / 2, canvas.height / 2);
for (let i = 0; i < 250; ++i)
{
console.log(i);
ffmpeg.stdin.write(Buffer.from(ctx.getImageData(0, 0, canvas.width, canvas.height).data));
}
ffmpeg.stdin.end();
unfortunately, when i run it, the program throws this after writing the frames:
node:events:368
throw er; // Unhandled 'error' event
^
Error: write EPIPE
at WriteWrap.onWriteComplete [as oncomplete] (node:internal/stream_base_commons:98:16)
Emitted 'error' event on Socket instance at:
at emitErrorNT (node:internal/streams/destroy:164:8)
at emitErrorCloseNT (node:internal/streams/destroy:129:3)
at processTicksAndRejections (node:internal/process/task_queues:83:21) {
errno: -32,
code: 'EPIPE',
syscall: 'write'
}
Node.js v17.1.0
what am i doing wrong?
so, with the responses i got pointing me in the right direction, i was able to correct the syntax errors in my ffmpeg spawn, and then made it so the canvas data would be reencoded to 24-bit rgb (since mp4 doesn't support an alpha channel); these fixed my initial problems. and then i properly set the write procedure to drain:
so at last, i have a robust base that generates a playable video