Skip to content

IERoboticsAILab/ndi_router

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NDI Router

Lightweight FastAPI web service and UI to discover NDI sources on your network and route a selected stream to one or more output devices over SSH.

The app discovers NDI sources using cyndilib and, on request, connects to selected devices to launch yuri_simple with the chosen NDI stream.

Features

  • NDI discovery: Enumerates live NDI sources using cyndilib
  • Web UI: Simple page to pick a source and target devices
  • Multi-device routing: Sends the same stream to multiple hosts concurrently
  • Stateless config: Output devices are defined in a single JSON file
  • REST API: Endpoints for sources, devices, and routing actions

Requirements

  • Python 3.11+
  • Platform dependencies suitable for cyndilib (NDI runtime/SDK as required by your OS)
  • Passwordless SSH access (public key auth) from the router host to each output device
  • On each output device: an executable run_yuri.sh script available in the default login directory

Quick start

  1. Clone and install
git clone https://github.com/yourusername/ndi_router.git
cd ndi_router
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
  1. Configure SSH access to devices
  • Ensure the router host can SSH to each device without a password.
ssh-keygen -t ed25519 -C "ndi_router"
ssh-copy-id user@DEVICE_IP
ssh user@DEVICE_IP "echo ok"
  1. Define output devices in src/output_devices.json
[
  { "name": "Display-1", "host": "192.168.1.10", "user": "youruser" },
  { "name": "Display-2", "host": "192.168.1.11", "user": "youruser" }
]
  1. Prepare run_yuri.sh on each output device

Place an executable script named run_yuri.sh in the default login directory of the remote user (so that ./run_yuri.sh works). Example content:

#!/usr/bin/env bash
set -euo pipefail
STREAM_NAME="${1:?NDI stream name required}"
pkill -f 'yuri_simple' || true
nohup yuri_simple "ndi_input[stream=${STREAM_NAME}]" "glx_window[fullscreen=True]" \
  > /tmp/yuri_simple.log 2>&1 &
echo "launched yuri_simple for ${STREAM_NAME}"
chmod +x run_yuri.sh
  1. Run the web app
uvicorn src.main:app --reload

Open http://127.0.0.1:8000 and use the UI to route a stream.

Environment variables (optional):

  • HOST (default 127.0.0.1)
  • PORT (default 8000)

API

  • GET /api/ndi-sources

    • Response: { "sources": [{ "name": str, "host": str, "stream": str }] }
  • GET /api/output-devices

    • Response: { "devices": [{ "name": str, "host": str, "user": str }] }
  • POST /api/route

    • Form fields:
      • stream_name: string (exact NDI source name as displayed)
      • devices: repeated string values of host addresses (e.g., 192.168.1.10)
    • Response: { "status": "ok" } on success

How it works

  • Discovery is implemented in ndi_discovery.py using cyndilib.Finder and exposed via FastAPI in src/main.py.
  • The UI (src/templates/index.html) fetches sources/devices and posts the routing request.
  • For each selected device, the server SSHes in via paramiko and runs ./run_yuri.sh "<stream>".

Troubleshooting

  • No NDI sources appear: Ensure the NDI runtime is installed and your machine is on the same network segment. Check host firewall rules.
  • SSH errors / prompts for password: Confirm your public key is installed on each device and sshd allows public key auth. Test with ssh user@DEVICE_IP "echo ok".
  • run_yuri.sh not found: Place the script in the remote user's default directory and chmod +x run_yuri.sh. The server invokes ./run_yuri.sh.
  • Display doesn’t update: Confirm yuri_simple exists and runs on the target device. Inspect /tmp/yuri_simple.log on the device.

Development

Project layout:

  • src/main.py: FastAPI app, API endpoints, and simple HTML UI route
  • ndi_discovery.py: NDI discovery helpers backed by cyndilib
  • src/templates/index.html: Minimal UI for selecting sources and devices
  • src/output_devices.json: Device configuration consumed by the API/UI
  • ndi_test.py: Example extended discovery including resolution/framerate

Run the discovery helper directly:

python ndi_discovery.py

Security note

This service performs remote command execution over SSH with no built-in authentication or authorization. Run it only on a trusted network or place it behind an authenticated reverse proxy.

License

MIT License

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors