NDI (Network Device Interface) send/receive addon for TrussC.
NDI is a low-latency video-over-IP protocol from Vizrt (formerly NewTek), widely used in broadcast, AV installations, and live streaming.
- Send — broadcast a TrussC app's pixels onto the NDI network
- Receive — pull frames from any NDI source on the network into a
tc::Pixels - Find — discover NDI sources currently advertising on the network
The NDI SDK is not redistributable, so you must install it yourself. Download from https://ndi.video/sdk/ (free, registration required).
Install the .pkg from the SDK download. Headers and library land at:
/Library/NDI SDK for Apple/include/
/Library/NDI SDK for Apple/lib/macOS/
Run the SDK installer. Default install location:
C:\Program Files\NDI\NDI 6 SDK\Include\
C:\Program Files\NDI\NDI 6 SDK\Lib\x64\
(The exact NDI 6 SDK part follows the SDK version you downloaded.)
On NDI SDK 6 the runtime DLL is not shipped under the SDK's Bin\x64\ — it comes from a separate NDI Runtime installer (also bundled with NDI Tools) and lands at:
C:\Program Files\NDI\NDI 6 Runtime\v6\Processing.NDI.Lib.x64.dll
If your SDK install's Bin\x64\ is missing Processing.NDI.Lib.x64.dll, download NDI Tools from https://ndi.video/tools/ (or the standalone NDI Runtime) and install it.
tcxNdi probes both the SDK tree and the NDI Runtime tree and copies the DLL next to your built .exe, so you should not need to copy Processing.NDI.Lib.x64.dll by hand. If both live in non-default locations, set NDI_SDK_ROOT to a path that contains either layout.
NDI on Linux relies on the avahi-daemon (mDNS service) for network discovery — without it other machines cannot find your sender. Pick the subsection that matches your distro.
Download the SDK installer from https://ndi.video/sdk/ (fill the form, a download link arrives by email). Extract and run it:
tar xf Install_NDI_SDK_v6_Linux.tar.gz
./Install_NDI_SDK_v6_Linux.sh # press Y to accept the EULA
The installer unpacks into ~/NDI SDK for Linux/. Copy headers and libraries to system-wide locations so the addon's CMake probe finds them:
# x86_64 (Ubuntu on a PC)
sudo cp -r "$HOME/NDI SDK for Linux/include/"* /usr/include/
sudo cp -r "$HOME/NDI SDK for Linux/lib/x86_64-linux-gnu/"* /usr/lib/x86_64-linux-gnu/
sudo ldconfig
# aarch64 (Raspberry Pi 4 / 5, 64-bit Raspbian)
sudo cp -r "$HOME/NDI SDK for Linux/include/"* /usr/include/
sudo cp -r "$HOME/NDI SDK for Linux/lib/aarch64-linux-gnu/"* /usr/lib/aarch64-linux-gnu/
sudo ldconfig
Then install avahi:
sudo apt install avahi-daemon libnss-mdns
sudo systemctl enable --now avahi-daemon
Raspberry Pi note: NDI SDK 6 is arm64-only. Raspbian must be the 64-bit build (uname -m should print aarch64). Pi Zero and Pi 1–3 running 32-bit OS are not supported.
Install the SDK from the AUR, then avahi:
yay -S ndi-sdk
sudo pacman -S avahi nss-mdns
sudo systemctl enable --now avahi-daemon
If receivers on other machines can't find the sender or see the name but never get frames, see Troubleshooting.
Add the addon to your project's addons.make:
tcxNdi
#include "tcxNdi.h"
tcx::NdiSender sender;
void tcApp::setup() {
sender.setup("My TrussC App"); // name visible to NDI receivers
}
void tcApp::draw() {
// ... draw your scene ...
sender.send(getPixels()); // ship the frame to the NDI network
}#include "tcxNdi.h"
tcx::NdiFinder finder;
tcx::NdiReceiver receiver;
void tcApp::setup() {
finder.refresh();
auto sources = finder.getSources();
if (!sources.empty()) {
receiver.connect(sources[0]);
}
}
void tcApp::update() {
if (receiver.update()) {
// new frame arrived; receiver.getPixels() now valid
}
}
void tcApp::draw() {
if (receiver.hasFrame()) {
receiver.getPixels().draw(0, 0);
}
}See example-ndi-sender/ and example-ndi-receiver/ for runnable samples.
Discovery is fine but the TCP video stream is being blocked or advertised on the wrong interface.
1. Open NDI's ports in firewalld. EndeavourOS ships it enabled by default; skip if systemctl is-active firewalld says inactive.
sudo firewall-cmd --zone=public --add-port=5353/udp --permanent
sudo firewall-cmd --zone=public --add-port=5960-5990/tcp --permanent
sudo firewall-cmd --zone=public --add-port=5960-5990/udp --permanent
sudo firewall-cmd --reload
2. Multi-NIC machines (Tailscale, Docker, VPNs) — pin NDI to the LAN IP in ~/.ndi/ndi-config.v1.json. Restart the sender after editing; the NDI runtime reads this config at init.
{
"ndi": {
"adapters": { "allowed": ["192.168.x.x"] },
"multicast": { "send": { "enable": false } }
}
}
Arch ships systemd-resolved bound to UDP 5353, the same port avahi needs for mDNS. When both run, avahi ends up publishing only on lo and other machines can't see the source. Hand 5353 to avahi:
sudo mkdir -p /etc/systemd/resolved.conf.d
sudo tee /etc/systemd/resolved.conf.d/no-mdns.conf > /dev/null <<'EOF'
[Resolve]
MulticastDNS=no
EOF
sudo systemctl restart systemd-resolved avahi-daemon
Confirm the source now advertises on your LAN NIC (not just lo):
avahi-browse _ndi._tcp -r -t
- Linux (EndeavourOS / Arch)
- Linux (Ubuntu / Debian)
- Linux (Raspbian)
- Windows (Windows 11 x64)
- macOS
API surface inspired by ofxNDI.
MIT License. See LICENSE.