Streampunk/grandiose

converting image buffer to png

NijsJonas opened this issue · 5 comments

i can receive my ndi stream now and i can see the buffer from the image
image
how can i convert this buffer to a png or other image to view ?

Hi @yyy898

You can try using the following library 'Sharp': https://github.com/lovell/sharp

Best regards

when i try
sharp(videoFrame.data)
.resize(1920, 1080)
.toFile('output.png', (err, info) => {console.log(err)});
}
i get the error: [Error: Input buffer contains unsupported image format]

Did someone managed to get this working ? I tried to pass the raw data to sharp because the frame data doesn't seems to contains any sort of png or jpeg formatted data.

await sharp(image.data, {
  raw: {
    width: frame.xres,
    height: frame.yres,
    channels: 3,
  },
}).toFile("test.jpeg");

But this still isn't working. I get the following error:

[Error: VipsImage: memory area too small --- should be 6220800 bytes, you passed 4147200

My image should be a perfectly white blank image. This is what my frame looks like when I log it:

{
  type: 'video',
  xres: 1920,
  yres: 1080,
  frameRateN: 30000,
  frameRateD: 1200,
  pictureAspectRatio: 1.7777777910232544,
  timestamp: [ 1637271127, 56764100 ],
  frameFormatType: 1,
  timecode: [ -41, 117500000 ],
  lineStrideBytes: 3840,
  data: <Buffer 7f eb 80 eb 7f eb 80 eb 7f eb 80 eb 7f eb 80 eb 7f eb 80 eb 7f eb 80 eb 7f eb 80 eb 7f eb 80 eb 7f eb 80 eb 7f eb 80 eb 7f eb 80 eb 7f eb 80 eb 7f eb ... 4147150 more bytes>
}

The buffer seems to have a pattern that makes me think I'm on the right path. But I can't figure out how to get this working. Any help would be really appreciated.

What options are you using on the grandiose receiver?
As I see it, you should be using below settings for this use case (not exhaustive)

const receiverOptions = {
	// Ensure RGB frames are received
	colorFormat: grandiose.COLOR_FORMAT_RGBX_RGBA,
	// Ensure progressive frames are received
	allowVideoFields: false
}

Thank you for your help! I managed to get this working with your options. Here is my working code:

const { writeFileSync } = require("fs");
const sharp = require("sharp");
const bmp = require("bmp-js");
const grandiose = require("./index");
const buffer = require("buffer");

async function saveScreenshot(receiver, name) {
  const image = await receiver.video(10000);
  try {
    await sharp(image.data, {
      raw: {
        width: image.xres,
        height: image.yres,
        channels: 4,
      },
    }).toFile(name);
  } catch (error) {
    console.log(error);
  }
}

async function bootstrap() {
  const sources = await grandiose.find();
  const obsLink = sources[0];
  const receiver = await grandiose.receive({
    source: obsLink,
    colorFormat: grandiose.COLOR_FORMAT_RGBX_RGBA,
    allowVideoFields: false,
  });
  await receiver.data();
  saveScreenshot(receiver, "screenshot.jpeg");
}

bootstrap().catch(console.log);