Node.js native bindings to NewTek NDI(tm). For more information on NDI(tm), see:
NDI(tm) is a realisation of a grand vision for what IP media streams should and can be, hence a steampunk themed name of gra-NDI-ose.
Grandiose only supports Windows x64 platforms at this time. Other platforms may be added in the future.
Install Node.js for your platform. This software has been developed against the long term stable (LTS) release.
On Windows, the NDI(tm) DLL requires that the Visual Studio 2013 C run-times are installed, available from:
Grandiose is designed to be
required to use from your own application to provide async processing. For example:
npm install --save grandiose
A list of all currently available NDI(tm) sources available on the current local area network (or VLAN) can be retrieved. For example, to print a list of sources to the console, try:
const grandiose = ;grandiose;
The result is an array, for example here are some local sources to machine :
name: 'GINGER (Intel(R) HD Graphics 520 1)'urlAddress: '169.254.82.1:5962'name: 'GINGER (Test Pattern)'urlAddress: '169.254.82.1:5961'name: 'GINGER (TOSHIBA Web Camera - HD)'urlAddress: '169.254.82.1:5963'
The find operation can be configured with an options object and a wait time in measured in milliseconds:
The options are as follows:
First of all, find a stream using the method above or create an object representing a source:
const grandiose = ;let source = name: "<source_name>" urlAddress: "<IP-address>:<port>" ;
async function, create a receiver as follows:
let receiver = await grandiose;
An example of the receiver object resolved by this promise is shown below:
embedded: Externalvideo: Function: videoaudio: Function: audiometadata: Function: metadatadata: Function: datasource:name: 'LEMARR (Test Pattern)'urlAddress: '169.254.82.1:5961'colorFormat: 100 // grandiose.COLOR_FORMAT_FASTESTbandwidth: 100 // grandiose.BANDWIDTH_HIGHESTallowVideoFields: true
embedded value is the native receiver returned by the NDI(tm) SDK. The
data functions return promises to retrieve data from the source. These promises are backed by calls that are thread safe.
allowVideoFields parameters are those used to set up the receiver. These can be configured as options when creating the receiver as follows:
let receiver = await grandiose;
Request video frames from the source as follows:
let timeout = 5000; // Optional timeout, default is 10000mstryfor let x = 0 ; x < 10 ; x++let videoFrame = await receiver;console;catch e console;
Here is the output associated with a video frame created by an NDI(tm) test pattern:
type: 'video'xres: 1920yres: 1080frameRateN: 30000frameRateD: 1001pictureAspectRatio: 17777777910232544 // 16:9timestamp: 1538569443 717845600 // PTP timestampframeFormatType: 1 // grandiose.FORMAT_TYPE_INTERLACEDtimecode: 0 0 // Measured in nanosecondslineStrideBytes: 3840data: <Buffer 80 10 80 10 80 10 80 10 ... >
NDI presents 8-bit integer data for video, meaning samples are byte-aligned.
Note that the returned promise may be rejected if the request times out or another error occurs.
receiver instance will disconnect on the next garbage collection, so make sure that you don't hold onto a reference.
Audio follows a similar pattern to video, except that a couple of options are available to control for format of audio returned into Javasript.
let timeout = 8000; // Optional timeout value in mslet audioFrame = await receiver;
An example of an audio frame resolved from this promise is:
type: 'audio'audioFormat: 2 // grandiose.AUDIO_FORMAT_INT_16_INTERLEAVEDreferenceLevel: 0 // 0dB above reference levelsampleRate: 48000 // Hzchannels: 4samples: 4800 // Number of samples in this framechannelStrideInBytes: 9600 // number of bytes per channel in buffertimestamp: 1538578787 132614500 // PTP timestamptimecode: 0 800000000 // timecode as PTP valuedata: <Buffer 00 00 00 00 00 00 00 00 89 10 89 10 89 10 89 ... >
Follows a similar pattern to video and audio, waiting for any metadata messages in the stream.
let metadataFrame = await receiver;
The result is an object with a
data property that is string containing the metadata, expected to be a short XML document.
Next available data
A means to receive the next available data payload in the stream, whether that is video, audio or metadata, allowing the application to filter the streams as required based on the
type parameter. The optional arguments used for audio can also be used here.
let dataFrame = await receiverdata;if dataFrametype == 'video' /* Process just the video */else if dataFrametype == 'metadata' console;
To find out the version of NDI(tm), use:
grandiose.version(); // e.g. 'NDI SDK WIN64 00:29:47 Jun 26 2018 18.104.22.168'
To check if the installed CPU is supported for NDI(tm), use:
grandiose.isSupportedCPU(); // e.g. true
Status, support and further development
Support for sending streams is in progress. Support for x86, Mac and Linux platforms is being considered.
Although the architecture of grandiose is such that it could be used at scale in production environments, development is not yet complete. In its current state, it is recommended that this software is used in development environments and for building prototypes. Future development will make this more appropriate for production use.
Contributions can be made via pull requests and will be considered by the author on their merits. Enhancement requests and bug reports should be raised as github issues. For support, please contact Streampunk Media.
Apart from the exceptions in the following section, this software is released under the Apache 2.0 license. Copyright 2018 Streampunk Media Ltd.
The software uses libraries provided under a royalty-free license from NewTek, Inc..
includefiles are licensed separately by a NewTek under the MIT license.
- The DLL and library are provided for convenience of installation and are covered by the NewTek license contained in the
NDI(tm) is a trademark of NewTek, Inc..