Skip to content

benoitlahoz/node-syphon

Repository files navigation

node-syphon

Superficial bindings between Syphon-Framework and node.js, that supports both Intel and Silicon architectures.

node-syphon provides Javascript functions to handle publishing and subcribing to Syphon textures in OpenGL and Metal as:

  • Pixel buffers/arrays (Uint8Array).
  • IOSurface handles in Electron (publish only, subscribing is ready and tested but waiting for the approval of this Electron PR).

Donate / Sponsor

If you find this package useful, contribute to the author's open source work by donating here! Thank you!

paypal

Table of Contents

Install

yarn add node-syphon

Examples

Usage

Client

import {
  SyphonOpenGLClient,
  SyphonServerDirectory,
  SyphonServerDirectoryListenerChannel,
} from 'node-syphon';

const directory = new SyphonServerDirectory();

directory.on(
  SyphonServerDirectoryListenerChannel.SyphonServerAnnounceNotification,
  (server: any) => {
    console.log('Server announce', server);

    if (directory.servers.length > 0 && !client) {
      console.log('Create');

      client = new SyphonOpenGLClient(directory.servers[directory.servers.length - 1]);

      client.on('frame', (frame: FrameDataDefinition) => {
        console.log('Frame received', frame);

        const buffer: Buffer = frame.buffer;
        const width: number = frame.width;
        const height: number = frame.height;

        // ...
      });
    }
  }
);

directory.on(SyphonServerDirectoryListenerChannel.SyphonServerRetireNotification, (server: any) => {
  console.log('Server retire', server);
  console.log(directory.servers);
});

directory.listen();

Server

OpenGL
import { SyphonOpenGLServer } from 'node-syphon';

// Create a server.
const server = new SyphonOpenGLServer('My awesome server');

const size = 50 * 50 * 4;
const clamp = 255;

let data: any = new Uint8ClampedArray(size);

// Generate random pixels.
for (let i = 0; i < size; i = i + 4) {
  data[i] = Math.floor(Math.random() * Math.min(255, clamp));
  data[i + 1] = Math.floor(Math.random() * Math.min(255, clamp));
  data[i + 2] = Math.floor(Math.random() * Math.min(255, clamp));
  data[i + 3] = 255;
}

// Send frames.
const interval = setInterval(() => {
  server.publishImageData(
    data,

    // Region.

    { x: 0, y: 0, width: 50, height: 50 },

    // Texture dimensions.

    { width: 50, height: 50 },

    // Flipped.

    false,

    // Texture target (defaults to 'GL_RECTANGLE_EXT').

    'GL_TEXTURE_2D'
  );
}, 1000 / 60);
Metal
import { SyphonMetalServer } from 'node-syphon';

// Create a server.
const server = new SyphonMetalServer('My awesome server');

const size = 50 * 50 * 4;
const clamp = 255;

let data: any = new Uint8ClampedArray(size);

// Generate random pixels.
for (let i = 0; i < size; i = i + 4) {
  data[i] = Math.floor(Math.random() * Math.min(255, clamp));
  data[i + 1] = Math.floor(Math.random() * Math.min(255, clamp));
  data[i + 2] = Math.floor(Math.random() * Math.min(255, clamp));
  data[i + 3] = 255;
}

// Send frames.
const interval = setInterval(() => {
  server.publishImageData(
    data,

    // Region.

    { x: 0, y: 0, width: 50, height: 50 },

    // Texture dimensions.

    { width: 50, height: 50 },

    // Flipped.

    false
  );
}, 1000 / 60);

Contribute

See CONTRIBUTING.md

Performances

As of v0.6.1, the electron client example getting a 1920x1080 image from VDMX has a latency of 8 milliseconds on a MacPro 2013.

TODO

  • Test the server description NSImage->Napi::Buffer.
  • Experiment WebGPU Native to and from Browser.

About

Experimental and superficial wrapper of Syphon-Framework for node.js.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •