LED Receiver supports flexible configuration through JSON files, allowing you to define display and content settings independently.
# Use LED screen configuration
python3 ndi_receiver.py --config config.led_screen.json
# Use adaptive configuration
python3 ndi_receiver.py --config config.adaptive.json
# Create custom config
cp config.example.json my_config.json
# Edit my_config.json
python3 ndi_receiver.py --config my_config.jsonThe configuration distinguishes between:
- Display: The physical screen (e.g., 800x800 LED panel or 1920x1080 monitor)
- Content: The NDI video stream (e.g., 320x320 video)
This separation allows you to:
- Handle LED screens with different physical/effective resolutions
- Position content anywhere on the display
- Scale content independently
- Rotate content without affecting display
"ndi": {
"source_suffix": "_led", // Auto-detect sources ending with this
"scan_timeout": 2, // Seconds to wait for discovery
"color_format": "bgra" // Format: bgra (fastest), uyvy, rgba
}"display": {
"resolution": "800x800", // Physical display resolution
// null = auto-detect
"fullscreen": true, // Run fullscreen
"video_driver": "auto", // SDL driver: auto, kmsdrm, x11, directfb
"show_fps": false // Show FPS counter
}Display Resolution Options:
"800x800"- Specific resolutionnull- Auto-detect (recommended for adaptive setups)
"content": {
"resolution": "320x320", // Force content to this size
// null = use source resolution
"position": "0,0", // Position in pixels (x,y)
// or: "center", "top-left", etc.
// null = center
"rotation": 180, // Rotation in degrees (0, 90, 180, 270)
// null = 0
"scaling": "none" // Scaling mode (see below)
}Position Options:
"0,0"- Top-left corner (x,y in pixels)"100,50"- Specific pixel position"center"- Center of display"top-left","top-right","bottom-left","bottom-right"- Named positionsnull- Auto-center
Scaling Modes:
"none"- No scaling, use content resolution as-is"fit"- Scale to fit display, maintain aspect ratio (default)"fill"- Scale to fill display, may crop"stretch"- Stretch to fill display exactly
Rotation:
- Rotates the content before positioning
- For 90° or 270°, width and height are swapped
"bridge": {
"enabled": false, // Enable bridge client mode
"url": null, // Bridge server URL (e.g., ws://bridge-server:8081)
"component_id": null, // Unique ID for bridge mode
// null = auto-generated from hostname
"component_name": "LED Wall" // Human-readable name for bridge display
// null = uses "name" field
}Bridge Mode: When connecting to a TD_NDI_NamedRouter bridge server, this Raspberry Pi receiver will appear in the unified web interface alongside TouchDesigner instances and other RPi receivers.
Fields:
enabled: Set totrueto enable bridge mode (can be overridden with--bridge-urlCLI arg)url: WebSocket URL of the bridge server component port (default: 8081)component_id: Unique identifier for this componentcomponent_name: Human-readable display name
Configuration Priority:
- CLI arguments (
--bridge-url,--component-id,--component-name) - Config file (
bridgesection) - Auto-generated defaults
Default Values:
component_id: Auto-generated as"RaspberryPi_<hostname>"component_name: Uses the"name"field from config
Example (Multi-RPi Setup with Bridge):
{
"name": "LED Screen",
"bridge": {
"enabled": true,
"url": "ws://192.168.1.100:8081",
"component_id": "LED_Wall_Main",
"component_name": "LED Wall - Stage Left"
}
}This connects to the bridge at 192.168.1.100:8081 and appears in the interface as "LED Wall - Stage Left" with ID "LED_Wall_Main".
Modes:
- Standalone:
--web-server(local web interface only) - Bridge only:
--bridge-url ws://server:8081 --bridge-only(no local web server) - Hybrid:
--web-server --bridge-url ws://server:8081(both local and bridge)
{
"description": "LED screen with specific content area",
"display": {
"resolution": "800x800",
"fullscreen": true
},
"content": {
"resolution": "320x320",
"position": "0,0",
"rotation": 180,
"scaling": "none"
}
}Use case: LED panel that reports 800x800 but only has 320x320 active pixels in the corner, upside down.
{
"description": "Auto-detect everything",
"display": {
"resolution": null,
"fullscreen": true
},
"content": {
"resolution": null,
"position": null,
"rotation": 0,
"scaling": "fit"
}
}Use case: Works on any display, scales NDI content to fit perfectly.
{
"description": "Test on 1366x768 LCD",
"display": {
"resolution": "1366x768",
"fullscreen": false
},
"content": {
"resolution": null,
"position": "center",
"rotation": 0,
"scaling": "fit"
}
}Use case: Testing on a laptop/monitor, scale content to fit.
{
"description": "Multiple small windows",
"display": {
"resolution": "1920x1080",
"fullscreen": true
},
"content": {
"resolution": "320x320",
"position": "100,100",
"rotation": 0,
"scaling": "none"
}
}Use case: Display content at specific position (for multi-window setups in future).
{
"description": "Portrait orientation",
"display": {
"resolution": "1080x1920",
"fullscreen": true
},
"content": {
"resolution": null,
"position": "center",
"rotation": 90,
"scaling": "fit"
}
}Use case: Portrait display with rotated content.
Configuration sources in order of priority (highest to lowest):
- Command line arguments
- Configuration file
- Default values
Example:
# Config file says rotation: 180, but CLI overrides to 0
python3 ndi_receiver.py --config config.json --rotation 0Problem: LED panel shows as 800x800, but only 320x320 area is active at top-left, upside down.
Solution:
{
"display": {"resolution": "800x800", "fullscreen": true},
"content": {
"resolution": "320x320",
"position": "0,0",
"rotation": 180,
"scaling": "none"
}
}What it does:
- Opens 800x800 display
- Receives NDI at native resolution
- Forces to 320x320 if different
- Positions at 0,0 (top-left)
- Rotates 180° to fix upside-down
- No scaling (pixel-perfect)
Problem: Want to test on any display without manual configuration.
Solution:
{
"display": {"resolution": null, "fullscreen": true},
"content": {
"resolution": null,
"position": null,
"rotation": 0,
"scaling": "fit"
}
}What it does:
- Auto-detects display size
- Uses NDI source resolution
- Centers content
- Scales to fit while maintaining aspect ratio
Studio (config.studio.json):
{"content": {"rotation": 180}}Home (config.home.json):
{"content": {"rotation": 0}}Run:
# At studio
python3 ndi_receiver.py --config config.studio.json
# At home
python3 ndi_receiver.py --config config.home.jsonThe application validates configurations:
- Display resolution must be
"WxH"format ornull - Content resolution must be
"WxH"format ornull - Position must be
"X,Y"pixels or named position - Rotation must be 0, 90, 180, or 270
- Scaling must be "none", "fit", "fill", or "stretch"
Invalid configurations will show an error and exit.
Enable debug logging to see configuration details:
python3 ndi_receiver.py --config config.json --debugLook for log lines like:
Configuration: display=(800, 800), content_res=(320, 320), position=(0, 0), rotation=180°, scaling=none
- Start with adaptive config - Use
config.adaptive.jsonfirst to verify everything works - Test incrementally - Add one setting at a time to isolate issues
- Use profiles - Create different config files for different scenarios
- Log everything - Use
--debugwhen troubleshooting - Pixel-perfect - Use
scaling: "none"when you want exact sizing
Recommended organization:
led_test/
├── config.adaptive.json # Auto-detect everything
├── config.led_screen.json # Your LED screen
├── config.studio.json # Studio-specific
├── config.home.json # Home-specific
└── config.example.json # Template
Select with --config:
python3 ndi_receiver.py --config config.led_screen.jsonSee Also:
- CLI_GUIDE.md - Command line options
- STUDIO_SETUP.md - Studio setup guide