Streampunk / grandiose

Node.JS native bindings to Newtek NDI(tm).
Apache License 2.0
189 stars 48 forks source link

converting image buffer to png #12

Open NijsJonas opened 4 years ago

NijsJonas commented 4 years ago

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 ?

jensstigaard commented 4 years ago

Hi @yyy898

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

Best regards

NijsJonas commented 4 years ago

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]

bpisano commented 2 years ago

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.

jensstigaard commented 2 years ago

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
}
bpisano commented 2 years ago

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);