Using node.js, python, multiple raspberry pi’s and usb lights to create an inexpensive wireless camera tally system that can arbitrate multiple sources simultaneously

Update: Version 1.2 is available now; read about it here:

At my church, we have two auditoriums, each with their own video switcher and cameras. All of the inputs and outputs of each switcher are on a common video router, so all of these sources can easily be shared across both rooms. However, even with all this, we have no camera tally system. Commercial tally systems can be expensive, and it’s just something we’ve never been able to afford.

It’s not normally an issue, but sometimes we want to pull up a shot of a camera in Auditorium 1 and show it in Auditorium 2. Because we have no tally system, the camera operator would not know their shot was being used. And, even if we did have a tally system, those systems generally only interface with one tally source/switcher, not multiple sources at the same time.

A few weeks ago, I was quarantined from work due to a co-worker testing positive for COVID-19. I set out to use this time to write a tally system for our church to use. Now that we’ve re-opened for church services, we will really need this, because we will have cameras capturing the service to stream online, but won’t necessarily have those cameras visible on the projector screens in the auditoriums during that time, where the operators would at least have a visual reference if their shot was in use.

And, because we have two video switchers, I needed to come up with a solution that would allow either video switcher to pull up a camera in either auditorium in Preview or Program, and make sure the operator still knew their shot was in use.

So here is Tally Arbiter. I called it this because the software aggregates tally data from multiple sources and “arbitrates” whether that device is in Preview, Program, or both across all sources and buses.

I played Halo a lot back in the day. A LOT.

The server software is written in Node.js and can run on a Raspberry Pi. It supports the TSL 3.1 network protocol like what our Ross Carbonite switchers use, but I’ve also written support for Blackmagic ATEM switchers, OBS Studio, StudioCoast VMix, and Roland SmartTally. I plan to one day add support for incoming webhooks, and GPIO inputs for switchers that don’t have network-based protocols.

The settings page of the Tally Arbiter server.

The software supports tally data coming from multiple sources, and each source can vary in protocol type. This could be useful, for example, if you had shared cameras for your production on-screen using an ATEM and also through your live stream using OBS or VMix, and you need the cameras to reflect the tally data of either system.

You can configure multiple devices in the software. These would be what generally receives tally data, whether it be cameras, CG stations, monitors, etc. Each device can support addressing from multiple sources. This is the “arbitration” portion of the software.

Once a device is determined to be in preview and/or program, device action(s) can be run. This can be sending out a TSL 3.1 protocol message (to a monitor/scope/multiviewer), an outgoing webhook (to tell another device to start playing a video (“roll clip”), for example), triggering a relay if you have CCUs that need contact closures to turn on the tally lights, or even local console output for logging and testing.

Some of our cameras have built-in tally lights, like the two Hitachi Z-HD5000 cameras we have. For those, I implemented a separate relay controller client that listens to the data on the Tally Arbiter server. It uses simple USB relays with the Node.js library I created a couple years ago that controls our auditorium window shade.

I bought a project box, put the relay in, ran some CAT5e cable I had laying around and connected it to the relay and the CCU’s with custom DB25 connectors. I had to modify the project box some because I wanted the relay to sit flat in the box, so I used a dremel to remove the bottom of the middle screwposts, which weren’t really needed anyway. Never be afraid to modify something to make it work!

The relay fits snugly inside this box. This particular unit has 8 relays, so I could add 2 more cameras with preview/program tally control to this unit.
The box and the Pi running the server fit nicely on top of one of the CCUs.
A clean rack is a happy rack!
Preview and Program lights!
This will make our camera operators happy.

But what about the cameras we use that don’t have tally lights? For these, I decided to use Raspberry Pi Zero W‘s that would run software listening over websockets to the Tally Arbiter server. These particular Pi models are inexpensive and simple to use. I knew that I could get the least expensive cost for physical tally lights out of these Pi’s if I went the GPIO route with some LED lights and custom circuitry, but I wanted to design something that people who may not be comfortable with these concepts could easily implement. And honestly, the thought of soldering something just sounded like something I’d have to possibly maintain down the road. So, I used the blink(1) USB lights by ThingM.

I first started experimenting with these USB lights about a year ago when I created a silent notification system for our band to use in case we had a tech issue during a service. The company that makes these has published very easy to use APIs, which makes it a great tool to use with custom software.

I like this simple black case from Vilros. You can get the whole kit minus the SD card for about $30 on Amazon.
Here’s a blink(1). A pretty versatile device!

The listener client script is written in Python since that programming language runs so easily on the Raspberry Pi OS no matter what model Pi you have. And, since we are using the websocket libary, bi-directional real-time communication between the server and clients even though the programming languages vary is not an issue.

I used a USB extension cable to bring the light up by the camera, but the Pi is down on the floor of the platform.
Another view.

All together, each wireless tally light should cost between $55 and $60 depending on what Pi case you use, SD cards, etc. Tally Arbiter has no built-in limitation of the number of wireless clients that can be connected, so this makes it a very versatile and flexible system no matter what the size is of your production.

Lastly, I also created an option to view live Tally data in a browser, like on a tablet or phone. You can select the device from the list and the background of the page will be red, green, or black depending on that device’s tally state.

The web based tally option is nice if you need a quick portable tally option.

The web tally is controllable through the Settings page just like any other listening client, so you can reassign the tally remotely and even send a flash to that client to get their attention.

Here’s a walkthrough video of the whole system in action:

As usual with my projects, I’ve made this open-source and available for your use on Github: It is fully documented with a REST API if you want to automate use of it outside of the GUI that I have created. There are also step-by-step instructions on how to set up a Raspberry Pi Zero, with OS imaging and all of of the libraries and script installing needed to get it going.

My hope and passion is to see resources like this to be used to further the Gospel. I believe and have seen that God can use technology for His good, and when we can use it to further ministry, that is how we can see the Gospel spread.

If these projects are helpful to you and your church, let me know! I love hearing how you use technology to serve the church.


  1. Upon receiving cell signal when my plane landed, I saw that you’d posted a new article. I read the entire thing before setting foot on the jet way. It’s so good! You’re incredibly generous to offer this up for other churches to use. Happier volunteers, more coordinated direction, more comprehensive worship experience, more attention on God. Thanks for doing this!

    Liked by 2 people

  2. This is so awesome! I have been searching endlessly for a solution like this. I am no programmer but read through your detailed instructions and decided to give it a shot. Just ordered everything. Thanks for working on this, this will really help out our church

    Liked by 1 person

  3. This is a wonderful answer to prayer. Our 5 camera Television OB van is under construction, we have 7″ Lilliput 663 camera monitors with built in green / red tallys but have never come up with a method of getting the tally signal out of out ATEM switcher. the BMD “decoder” is very costly and is not even complete as it needs the relay board. We will build with capability for 4 cameras wired to monitor tallys plus one for a mobile camera that will have to be wireless. Many thanks, I will keep in touch.

    John Fickling
    Endtime TeleVision
    Havelock North,
    New Zealand

    Liked by 1 person

      1. You should take a look at the Automation and Integration Guide from Newtek for the Tricasters. There are several options, but the easiest would probably be to use their TCP socket and listen for tally events. They will come back as XML like this:

        I’d also like to say your blog is awesome. Lots of good ideas here. I am ordering some Pi’s this week and already have the tally server running with our ATEM switcher. Big thanks for sharing your hard work!

        Liked by 1 person

  4. Cant handshake with BMD Atem Switcher.
    Its connected to it: shows green label
    Mapped to listener with input: 1
    Output to Console
    After changing input nothing happen


    1. Well, green is good! Do you have a source assigned to the device? Click “Device Sources” next to the device you created. It should have the input number that corresponds to the address or input on the ATEM.


      1. I did.

        Log output:
        Device Source Added: CAM 1 – ATEM Switcher
        Listener Client Connected. Type: web Device: CAM 1
        and nothing happend on tally page


      2. Send me a message here through the blog and I’ll respond from my email address, or you can email me directly: jadams at I want you to send me your config.json file so I can take a look and then we can figure out what might be going on. Thanks!


  5. Cant handshake with BMD Atem Switcher.
    Its connected to it: shows green label
    Mapped to listener with input: 1
    Output to Console
    After changing input nothing happen


  6. Does terminal have to stay open the entire time when running from directly within NODE?
    I figured out a very basic apple script for a one double click option for the NODE route so I think this would work for us but my OCD doesn’t like seeing the terminal application running.
    I get a missing write access error when I try to set it up as a Service. Are you able to add to your walkthrough on GitHub to maybe best resolve this?
    How are you activating/running the code in your application at your church (Direct or Service)?

    Thanks for doing this!

    Liked by 1 person

    1. Hey Chad! If the post doesn’t make it clear, I’m running it on a Raspberry Pi. I designed it with that platform in mind, hence it runs as a terminal process. But, the beauty of Node.js, it can run on many operating systems! So, yes, the terminal window will need to stay open. If you’re getting a write access error, it’s possible you are not running the process with the necessary permissions. An easy fix would be to run it with administrative (root) privileges. But it’s possible you could also grant specific permissions also. When you say “as a Service”, I’m just asking for clarification, you’re trying to use pm2 with MacOS?


      1. Yes that’s correct pm2 with MacOS at home to try it out. Yes you did say Raspberry Pi now that I think about it but I was thinking about putting it on my mac and there were Pi Zeros at the camera so that probably confused me too. Essentially once the “terminal” Pi is running, it can stay on and active in kind of a set it and forget it?


      2. Yes in general once TA is running, you won’t need to look at the terminal process for anything. You can manage it all through the web browser Settings page. I haven’t run it on anything less than a Pi 3B+ for the server so I would say that’s probably the safest minimum until I get a report that someone is running it on less. is a great place to get started!


      3. Is there a recommended Raspberry Pi model minimum? Also, I’ve heard of Raspberry Pi in the past but never educated myself on it. Do you have a suggested site(s) that you’ve found helpful in my situation?


  7. Hello, I tried this today and it looks like I’m having the same result as Kostyantyn and dkosta10. I’m on an ATEM 4M/E and using an iMac. I’m able to get a green light pretty quickly to confirm the software can “see” the switcher. Just when I set up a camera and select it, nothing else changes.

    Liked by 1 person

    1. I confirmed they are the same person. Can you send me your config file also? Also I will have a TA 1.1 release this week for you to try that should help troubleshoot. It’s working fine with my ATEM here. Are you running TA on the same computer as your ATEM software?


  8. Sorry I read that earlier and thought putting both of them sounded funnier in my head than in type. I can try and get the config file to you hopefully tomorrow. Yes TA and ATEM on same computer. I’m working on getting Raspberry or something on an old NUC that was sitting around as a permanent solution.
    The config file is just copied from the TA folder?


      1. This helped me. But LIVE status not red on 2nd device when set in Atem Software control. Its Yellow color on listening page (/tally page)


  9. I successfully installed Raspian on a NUC from 2012 but I’m only able to get node v10.21.0 and npm v5.8.0 installed. Can you confirm this setup is inadequate for TallyArbiter?
    Thank you.


      1. I’m inexperienced with Raspberry and pretty much everything else. I’m able to query version numbers for NPM and Node so they should be installed? I copied your folder from Github to the raspberry desktop. Switched to the folder via command line and attempted to start a service. But that is where i get stuck. Are you able to help me with the next steps?


      2. I just tried it again and I was able to get it to load directly within Node. I wasn’t able to get to install as a service on Raspberry. I just sent a screenshot of what I’m getting.


  10. We recently got an iKan vx9w monitor which has an Rj45 port labeled tally. Would you expect we would have to construct one of the relays you describe in order to send tally to the monitor?


    1. You can actually see the tally pinout here on the back of the monitor:

      What I am not sure about is whether it is contact-closure based or voltage based. You could test for this by just taking a spare RJ45 cable and cutting/splitting one end and connecting the wires to see if it turns on the tally or not. This is what a relay would do. If not, then you’ll need to use the GPO client with Tally Arbiter.


  11. Great work! What I need to do is pass on the ATEM tally signal to Datavideo PTC-140 cameras (same Visca as PTC-150) by sending a hex packet by TCP to the IP of the camera (same network) port 5002. Packet is 00 0B 81 01 7E 01 0A 00 0r 0g FF where r/g = 2(on)/3(off). I don’t think I can use Tally Arbiter to do that; could you confirm I am not missing something: the logic is there to send the messages, but not the required message protocol? Thanks


      1. This is fantastic. I think I may be able to control the built-in Tally on JVC PTZ cameras with a properly formed TCP string.

        Chris Glanzer


      1. Hi thanks for your reply (and sorry for multiple comments, I messed it a bit!!). I get an ERR_CONNECTION_FAILED on my phone. Am I supposed to run the server on my phone too? how do I do it?


      2. Ok Joseph thanks a lot for your support, I didn’t get it right but now it works perfectly on both phone and tablet!
        Thanks again, you did a great job!


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s