Manual / Help
Troubleshooting
Most faults come down to the service, the logs, or the network – check them in that order. Run First-look diagnostics below to cover all three, then jump to your symptom.
If the web UI is reachable, start with Diagnostics in the Overview tab. The summary cards point at the sick subsystem, and the Download diagnostics bundle button packages everything for a report.
Start here
First-look diagnostics
Run these on the Pi over SSH (ssh openfollow@<pi-ip> – see Quick Start if you're not sure how). They check, watch, and restart the OpenFollow background service:
# Is the service healthy? Look for "active (running)" in green.
sudo systemctl status openfollow
# Watch the live log – useful while reproducing a problem. Press Ctrl-C to stop.
sudo journalctl -u openfollow -f
# Restart it (fixes most "stuck since boot" symptoms).
sudo systemctl restart openfollow
sudo runs the command with administrator rights and may ask for the Pi password. If status shows failed or activating instead of active (running), the live log is where the reason will be.
If you're working inside the OpenFollow source folder on the Pi, these shortcuts do the same three things:
task status
task logs
task restart
Startup & display
Black screen after flashing the image
A freshly flashed station runs one-time setup on its first boot before the Operator Screen appears. Give it a minute before deciding it's stuck.
- Wait through the first boot. The first boot expands the station's storage and waits for the network, so the display can stay dark for up to three minutes. Power-cycle once and let it sit.
- Try the other HDMI port and a different cable. On a Pi 5 the output nearest the power connector is the first one. Reseat the cable; a marginal cable, an adapter, or a display that won't accept 1080p60 can stay black.
- Use the official 27 W USB-C supply. An under-powered Pi 5 can leave the display dark.
- Did the OpenFollow splash logo appear? It tells you where to look next:
- Splash, then the Operator Screen with a black video area – the app is running, and this is a video-source problem. See No video / black image below.
- Nothing at all, no splash and no Operator Screen – the service isn't starting. SSH in and run First-look diagnostics: if
statusshowsfailedoractivatinginstead ofactive (running), the live log holds the reason.
- Can you reach the Web UI from a browser? If you can, the app is healthy and the fault is the display path itself – stay on the HDMI port, cable, and monitor.
- Attached a keyboard and the screen is a text prompt? If the black screen turns out to be a
(initramfs)rescue shell rather than graphics, the bootloader couldn't find the root filesystem – usually an older Pi 5 bootloader. Update the bootloader and reboot:- If you can reach a shell or SSH into the station, run
sudo rpi-eeprom-update -athensudo reboot. - If it won't boot at all, recover from another computer with Raspberry Pi Imager → Choose OS → Misc utility images → Bootloader / EEPROM recovery. Pick the Pi 5 boot device you use (SD card, or NVMe / USB), flash it to a spare SD card, and boot the station once from that card until the screen turns green. Then power off, remove the card, and boot the OpenFollow card again.
- If you can reach a shell or SSH into the station, run
No video / black image
The Operator Screen and overlays are up, but the video area is black. If the whole screen is black with no overlays, that's a boot problem instead – see Black screen after flashing the image.
- Confirm the source URL or device. Test with
ffplayorgst-launch-1.0on a workstation:
If the stream plays in VLC but not here, the camera almost certainly wants a login – see RTSP stream plays in VLC but not in OpenFollow.ffplay -fflags nobuffer rtsp://<cam-ip>:554/stream/main - Check connection status on the on-screen overlay (or Camera & Grid → Video Source), and read Signal in Overview → Live Statistics → Video. See Reading the Video statistics – the resolution and frame-rate readings keep showing figures while the feed is down.
- NDI® 1 2 source not visible? Run
gst-inspect-1.0 ndisrcon the Pi. If the plugin isn’t found, the GStreamer NDI® plugin isn’t installed – see Installing NDI®. - Pi camera not detected? Check
libcamera-hello --list-cameras; confirm the camera is enabled in/boot/firmware/config.txt.
RTSP stream plays in VLC but not in OpenFollow
The same URL that works in VLC can stay disconnected here, because the URL isn’t the whole story: VLC asks for a username and password when the camera demands one and remembers them for next time, while OpenFollow takes credentials only from the URL you type.
- Put the credentials in the RTSP URL. In Camera & Grid → Video Source, write the login into the address:
URL-encode special characters in the password –rtsp://operator:secret@192.168.178.58:554/stream1@becomes%40,:becomes%3A,/becomes%2F. Many cameras are still on their factory login; it’s in the camera manual or on its web page under user accounts. - Test that exact URL outside OpenFollow. On a workstation, with the credentials in it:
ffplay -fflags nobuffer rtsp://operator:secret@<cam-ip>:554/<path>ffplaynever prompts, so it tests what OpenFollow sees. If it fails, the URL or the login is wrong; fix that before looking at OpenFollow. If it plays, copy and paste the URL into the RTSP URL field rather than retyping it. - Check the stream profile. Older cameras publish several profiles, and the one you picked may be MJPEG or MPEG-4 rather than H.264. Point the URL at an H.264 profile – see Video Inputs → RTSP for the camera settings that work best.
- Read Signal, not the frame numbers. See Reading the Video statistics below – a resolution and a frame rate next to Disconnected are normal and don’t mean the feed arrived.
Reading the Video statistics
Overview → Live Statistics → Video shows six readings, and not all of them answer “is video arriving?”
| Reading | What it tells you |
|---|---|
| Source | Which input the station is reading – confirm it’s the one you edited. |
| Signal | The one to trust. Connected means frames are arriving; Disconnected means they aren’t. |
| Resolution | The last frame size the station saw. It holds that figure while the feed is down. |
| Frame Rate (measured) | How fast the station is drawing, not how fast frames arrive. It keeps running at 50–60 fps with no camera attached at all. |
| Frame Rate (source) | The rate the camera advertises. 0.0 fps means nothing is being received. |
| Pipeline | Where the connection attempt stands: CONNECTED, CONNECTING, RECONNECTING, or DISCONNECTED. RECONNECTING that never reaches CONNECTED points at the URL, the credentials, or the network path. |
So Signal: Disconnected alongside Resolution 1920x1080 and Frame Rate (measured) 55.0 fps is a station with no video, drawing its Operator Screen normally.
Network & Web UI
Web UI is unreachable
- Is the service running?
sudo systemctl status openfollow. If not, start it and check the journal for the failure. - Is the Pi on the right network?
ip a; verify the IP address you’re browsing to. - Local sanity check. From the Pi:
curl -I http://127.0.0.1/. A200means the server is up. - Firewall. If you’ve enabled
ufwor another host firewall, allow whichever Web UI port you’re hitting –80,8080, or2010.
Web UI is on :8080 / :2010, or diagnostics is partial
OpenFollow doesn't have permission to bind the web port, and the full diagnostics bundle (USB topology, mount points, throttling flags, complete interface info) needs elevated access too. A packaged install – the image or the .deb – sets both up automatically. If you see a fallback port or a partial bundle, the service isn't running from the package; reinstall OpenFollow (see Installation) so it runs with the privileges it needs.
Station reports 127.0.0.1, peers don't discover
OpenFollow started before the network had an address – typically a fresh boot where the network came up late – so it stayed on loopback (127.0.0.1). Restart it once networking is up: sudo systemctl restart openfollow. If it repeats on every boot, give the Pi a wired link or a faster-associating network so an address is ready before the service starts.
Tracking, calibration & input
Markers drift or jitter
- Drift over a single show: the camera was bumped, or the lens auto-focused / auto-zoomed mid-show. Lock the camera mount, disable auto-focus and auto-zoom on the camera, then re-run the calibration wizard. See When to recalibrate.
- Jitter that gets worse with height: a small calibration error grows the further a marker sits above the grid plane, so it reads as wobble overhead. Tighten the solve: re-pin the corners accurately in wizard step 6 and re-check the camera Pos Z, Pitch, and FOV, then verify on stage with a tape measure.
- Jitter from the gamepad: raise the stick deadzone in Input → Gamepad (Axis deadzone, default
0.15). - Jitter only on OSC-driven markers: the incoming position stream is noisy or losing packets. Smooth or rate-limit it at the sender and check the link for loss.
Calibration won’t solve
Wizard step 6 (Corner Pinning) shows red corners and refuses to compute. The wizard rejects corners that cross over or enclose too small an area. Work through these, then press Reset Corners and re-pin:
- Camera Position is too far off (step 4). A bad starting point stops the solve. Go back to step 4 and re-check Pos Z and Pitch – Pitch must be negative (camera looking down).
- The marked rectangle is the wrong size. Re-measure it on stage; width and depth must match the figures you typed in step 2.
- The marked rectangle isn’t square. Measure both diagonals – they must be equal. If they aren’t, re-tape the corners to true 90°.
- Corners pinned out of order. Drag each handle to its matching stage corner without crossing the shape over itself.
Full walkthrough: Camera & Grid Calibration → Corner Pinning.
Positions offset between systems
OpenFollow and the console, visualiser, or media server place the same 3D position at different coordinates. Walk a marker to the centre of the stage, then to each corner, with a tape measure. How the error changes across the stage tells you which fault it is:
- Same offset everywhere: the point of origin is wrong. OpenFollow’s Reference Point (0, 0, 0) must be the same physical spot, with the same axis directions and units, as the zero point in the other system. Correct whichever one is mismarked. See Core Concepts → The Reference Point.
- Offset grows toward the edges: the grid scaling is wrong – the width and depth entered in the wizard don’t match the rectangle taped on stage. Re-measure the calibration grid, including both diagonals, and re-run the calibration wizard with the measured figures. See Camera & Grid Calibration → Grid Setup.
- Right at the corners, wrong in the middle: the FOV is off. Adjust HFOV in the Camera form by ±2° at a time and re-check. See Verifying calibration on stage.
Following too far upstage or downstage
The spot lands up- or downstage of the performer, and operators end up fudging the marker's height to drag it back on. Height is the wrong lever. Check these in order:
- Confirm every system shares the same origin. OpenFollow's Reference Point (0, 0, 0) must be the same physical spot, axis directions, and units as the zero point in every console, visualiser, and media server that uses its data. If one system's origin sits up- or downstage of OpenFollow's, every position carries that offset. See Core Concepts → The Reference Point.
- Check the camera is in a sensible position. A low, shallow angle flattens depth along the sightline, so a small steering error reads as a big up/downstage miss – which is what tempts operators to compensate with height. Aim for a higher, steeper view of the stage.
- Plan the placement with the calculator. Use Positioning the Camera to find a spot whose field of view covers the whole stage at a workable angle, then move the camera to match.
- Check image quality. A soft, low-resolution, or laggy picture makes the performer's feet hard to place, and depth keys off the feet. Raise the camera resolution and bitrate, and cut latency.
- Ask the operators whether they can see the performer clearly. If the stage lighting (low light, haze, backlight, blackouts) is hiding people, no angle will help. Try a more light-sensitive camera, or a model with IR / night-vision for dark scenes.
Gamepad not detected or buttons are wrong
- Wrong input mode. The controller must be in XInput mode. A pad in DirectInput or a console profile shows up with no sticks, swapped buttons, or not at all. Check your controller's manual for the mode switch / button combo and set XInput, then replug.
- Buttons mislabelled. Once in XInput, run the button detection wizard to relearn the layout.
- Not seen at all. Use a USB-wired connection – wireless / Bluetooth isn't supported for show work.
- 8BitDo Pro 2 Wired for Xbox on macOS3. macOS attaches no driver to this pad, so no app on the Mac can read it. This is a macOS limit, not an OpenFollow one.
Output & show control
The stream is live but nothing moves
The console shows a connected tracking source with the right system and marker names, the packets keep arriving at full rate, and the coordinates never change. Nothing on the receiving end distinguishes this from a healthy stream.
- Check the Frame clock. Open Overview → Live Statistics → Device. Stalled means the loop that reads input and moves markers has stopped, while PSN, OTP, RTTrPM, and OSC carry on sending the last known position. Gamepad, keyboard, mouse, detection, and zone evaluation are frozen with it, so the on-screen marker won't move either.
- Restart the app. Restart application in the Diagnostics section of the Overview tab. If the reading goes back to Running and stays there, you're clear.
- If it recurs, send the bundle. Download diagnostics bundle and attach it to a report – see Filing a useful bug report.
- Frame clock Running, still nothing? Then the marker isn't moving rather than the station being stuck: check that the station controls the marker the console is reading (Markers & Zones → Marker Control & Visibility), and that the marker IDs match on both ends.
PSN not received by the console
Almost always a multicast issue.
- Same subnet? OpenFollow and the console must share a VLAN.
- Is OpenFollow sending? On the Pi:
sudo tcpdump -ni any host 236.10.10.10. You should see packets at 60 fps. - Does the console see them? On a Linux workstation on the same VLAN as the console:
sudo tcpdump -ni any host 236.10.10.10. If you see them on the Pi but not here, the switch is dropping multicast. - Managed switches. Enable IGMP snooping with a querier on the relevant VLAN. See Networking & Security.
- Multi-NIC host. If the Pi has more than one network interface (Wi-Fi + Ethernet), set PSN Network Interface to the correct IP in Output → PSN Output. Leaving it on
Autopins TX to the host's primary outbound IPv4, which is usually right but not always.
OSC output isn’t firing
Start with the transmitter's collapsed row: a transmitter that can never fire names every reason there – see OSC Transmitters → Why a transmitter can't fire. If the row is clean, the answers live on the transmitter's own Diagnostics tab – see OSC Transmitters → Diagnostics. Common skip reasons:
- Open the transmitter's Diagnostics tab. The ring buffer shows the last ~100 send / skip events with the rendered address, args, and (for skips) the reason.
- Skipped with "no default marker configured"? The message uses
[x]/[y]/[z]/[markerid](or any other default-marker placeholder) but the transmitter has no Default markers. The web editor highlights the offending label in red and gates the Enabled toggle until you either set a default or rewrite the placeholder using the explicit-marker form ([x:N]). - Skipped with "default marker N not registered"? The marker ID isn't in this station's controlled markers. Add it under Markers & Zones → Marker Control & Visibility.
- Skipped with an unresolved
[z.frac]? The fractional height placeholder ([z.frac]) needs the grid's Max Height to normalise into ±1. Set a sensible upper bound (truss height, e.g. 6 m) under Camera & Grid → Grid → Max Height. Until then, the transmitter skips with the actionable hint. - Sending but not received? Check destination IP / port. For TCP transmitters, confirm Framing (SLIP vs Length-prefix) matches the receiver.
- TCP transmitter stuck in
backoff? The receiver is refusing or actively closing the connection. The status panel shows the current backoff window (0.25 s → 0.5 s → 1 s → 2 s → 5 s, holding at 5 s). Check the receiver's port is open and reachable; a successful connect resets the backoff. - Stream output is silent. If Send only on change is on, the transmitter only fires when the transmitter's default marker has moved more than the per-axis min change threshold since the last send. The gate watches the default marker even if the message uses
[x:3]. Move the marker or switch to Send always. - Quoted args rejected at save? Unclosed quotes surface a 400 with one wording. Balance the quotes, then save again.
/cue/start "Cue 12" 1.0sends two args;/cue/start "Cue 12 1.0rejects. - Use Test send. Fires the transmitter once with current data, independent of the enable toggle and trigger.
OSC input isn’t accepted
- Allowlist. If Allowed sender IPs is set, your sender’s IP must be in it. If not, check the journal:
sudo journalctl -u openfollow -f | grep -i osc - Address format. Confirm
/marker/<id>with three floats, or/marker/<id>/x(or/y,/z) with one float. Anything else is silently ignored. - Port. Default is
8765– verify your sender is hitting it.
Performance
High CPU or frame drops
- Rule out throttling first. Heat or an under-powered supply throttles the Pi 5 and reads as frame drops and high CPU. Check System health in the diagnostics bundle for throttling, undervoltage, and thermal flags, or run
vcgencmd get_throttledon the Pi – any result other than0x0means it throttled. Fix the cause: fit the official 27 W USB-C supply and add active cooling. - High CPU: disable Person Detection Experimental if you’re not using it.
- Frame drops: camera bitrate is too high (especially H.265). Drop the camera to H.264 main profile, 4–8 Mbps CBR.
- Pipeline restarts every few minutes: the camera is dropping its connection. Check Wi-Fi signal, PoE budget, or the camera’s health page.
Getting help
Filing a useful bug report
The fast path: attach a diagnostics bundle. Open the Overview tab and click Download diagnostics bundle in the Diagnostics section. It’s a browser download: the file lands in the download folder of the computer you’re browsing from, not on the station’s SD card. The bundle already contains OpenFollow version, host info, runtime versions, redacted config, log tail, network interfaces, USB devices, and more. See Diagnostics.
If for some reason you can’t get a bundle, include manually:
- OpenFollow version (commit hash if running from git).
- Host: Pi model and Pi OS release.
- Video source type and a redacted URL or device name.
- Output protocols enabled, and which destination was failing.
- The relevant excerpt of
journalctl -u openfollowaround the failure.
Either way, if the bug is reproducible, also include the exact steps from a clean state.
Report bugs at github.com/openfollowapp/openfollow/issues. Every report should include a diagnostics bundle.
For questions or feedback, join the OpenFollow Discord.
1. NDI® is a registered trademark of Vizrt NDI AB.
2. OpenFollow does not contain any NDI® code by itself. NDI® requires closed source NDI® Tools / NDI® SDK on the host system that need to be installed separately.
3. There is no release version of OpenFollow for macOS. It is in development, and no support can be provided for it.