Need someone to lead product management at your software company? I create software for people that create software and I'm looking for my next opportunity. Check out my resume and get in touch.

This is the blog of Adam Kalsey. Unusual depth and complexity. Rich, full body with a hint of nutty earthiness.

Products and Tools

Video calls using a networked camera

I’ve long used OBS to manage things for my video calling. I started because my DSLR has a 4:3 aspect ratio that I wanted to crop to a widescreen view. Over time, I’ve added color correction, multiple cameras, and a nameplate overlay.

But when I switched between computers, my video call setup wasn’t easy to take with me. And some video calling platforms (Google Meet, especially) suck so many resources from the computer that running something heavy like OBS often leads to dropped frames, frozen video, and video turning off. When I join a call from my five-year-old Intel MacBook, the fans run so loud that people on the call can hear them.

I had an old Dell Windows laptop gathering dust, so I decided to build a setup with that as a dedicated video management machine that provides a virtual camera over the network to my other computers. This blog post describes how I set it up.

Running OBS and exporting the Virtual Camera

I installed OBS on the laptop and copied my config files from one of my Mac laptops. In practice, this copying didn’t work well. Windows had different device names and file paths, so the imported config didn’t work. Instead of troubleshooting, I manually rebuilt my OBS configuration. If I had a more complicated config, I might have spent the effort fixing names and paths instead.

When OBS starts or restarts, the Virtual Camera doesn’t start automatically. OBS supports Lua scripts, so I wrote a script called start-cam.lua that says

obs = obslua
function script_load(settings)
obs.obs_frontend_start_virtualcam()
end

In OBS, under Tools > Scripts I added the start-cam.lua script. Every time OBS starts, it runs this script and starts the virtual camera.

Then I installed the DistroAV OBS plugin to add NDI support. NDI is an audio/video over IP protocol used by professional broadcasters. DistroAV creates NDI streams from the OBS VirtualCam output and can receive NDI streams into OBS like they’re cameras.

Over on my Macs, I’ve installed the NDI Vitual Input application. This app lets you turn an NDI stream on your network into a virtual camera.

DistroAV broadcasts a stream over my network from the Windows laptop, NDI Virtual Input on my Mac detects it and turns it into a camera I can use in Zoom, Webex, Google Meet, etc.

Connectivity

Instead of sending the NDI stream over wifi, I set up a dedicated wired network between the Windows computer and Mac computers. I use a Thunderbolt dock at my desk, so the ethernet cable runs from the Dell to a small switch and then the dock. When I plug a laptop into the dock, it can access the Dell over this private network. I manually configured both computers with private network IPs in a different class than I use for my home network. My home wifi network uses 192.168.x.x IP addresses and this manual wired network uses 10.0.0.x addresses.

I then set up the Dell’s wifi connection to access the Internet (so it can get updates), but not the local network.

This way, I know that all NDI streams are running over a dedicated gigabit wired network.

Connecting A/V devices

I have all my cameras (but one) connected to the Dell laptop. My Yeti microphone also connects to the Dell. In OBS, I export the camera and the microphone to the NDI stream.

On the Mac, I configure my video call services to use the NDI Virtual Output as both the camera and the Microphone. The speaker is the locally connected speaker on my monitor.

My monitor has an OK camera and microphone built in. These remain attached to the Macbook. If something goes wrong with the Dell, the network, or the NDI stream, I can use the monitor camera and mic as a backup.

OBS configuration changes

My main camera is an old Nikon D5100 running a patched firmware to let it work as a webcam. It’s connected through an AVerMedia capture device the Dell. OBS doesn’t detect any video when I first turn the camera on. It’s like the device is sleeping and OBS doesn’t wake it. When I had this directly connected to the Mac, starting PhotoBooth would wake up the video so OBS could see it. But now that it’s not on the Mac at all, I needed a new way of waking it up.

In OBS, I’ve set the “unload when not visible” property on every camera. Now if OBS doesn’t detect the video I can hide and show the source a couple of times and it wakes up.

OBS unload when not visible

Controlling the Dell

I didn’t want the Dell cluttering my desk, but I still needed to control it. At first, I tried Synergy to share a mouse and keyboard across the Mac and Windows. This worked extremely well, and I’d recommend Synergy as an application. It’s a solid product. But using it this way still meant I needed a screen for the Dell laptop, so it had to be open somewhere nearby.

I eventually moved the Dell to a mount under my desk and now use Remote Desktop to access it from the MacBook. When I first set this up, each time I connected to Windows over RDP, all microphones connected to that Windows computer stopped working. I Device Manager, no devices were even shown, even after disconnecting RDP and using the laptop directly. Rebooting Windows brought the microphone back... until I used RDP again.

VNC won’t work with the laptop lid closed, so I needed to find a way to make RDP work. It turns out that the fix is found in the Mac RDP client. There’s an option for where to play sound and changing this to “remote PC” fixed the problem. That’s about as non-obvious a fix as I can imagine.

Remote desktop audio setting

But it created a new problem. Now the laptop played all mic input out through the speakers. When speaking I’d hear myself through the Dell speakers. Muting the speakers didn’t solve it. I’d still hear a faint echo of myself. But the Dell is connected to a dock with a speaker port that creates a “USB sound device” speaker. I made that my default Windows speaker and now it’s sending sounds to an empty 3.5mm speaker jack.

Controlling OBS

I use an Elgato Stream Deck to switch cameras in OBS, control meeting apps, and manage my lighting. The Stream Deck is connected to the Mac. Now that OBS isn’t on the Mac, I needed to find a solution to control it. I considered a second Streamdeck and other ideas. Then I found a Stream Deck plugin called Multi OBS Controller. OBS has a websocket API that can do almost anything the UI can do. Multi OBS uses that API to send commands to OBS and lets you configure up to two OBS targets to control.

Mutli OBS Controller Settings

I only have one OBS, so I configured it in the plugin settings. Now when I press a Stream Deck button to turn a camera off, it sends the command over the websocket to the Dell instead of sending it to a local OBS.

Stream Deck button

Sometimes, the Stream Deck loses the websocket and doesn’t reconnect. Quitting Stream Deck and restarting it solves that. Using Hammerspoon, I’ve scripted the Stream Deck app to quit when I disconnect the laptop from the dock and start back up when it’s reconnected. That way, I always have a fresh websocket connection.

Recently Written

A Framework for Scaling product teams
Oct 9: The people, processes, and systems that make up a product organization change radically as you go through the stages of a company. This framework will guide that scaling.
My Networked Webcam Setup
Sep 25: A writeup of my network-powered conference call camera setup.
Roadmap Outcomes, not Features
Sep 4: Drive success by roadmapping the outcomes you'll create instead of the features you'll deliver.
Different roadmaps for different folks
Sep 2: The key to effective roadmapping? Different views for different needs.
Micromanaging and competence
Jul 2: Providing feedback or instruction can be seen as micromanagement unless you provide context.
My productivity operating system
Jun 24: A framework for super-charging productivity on the things that matter.
Great product managers own the outcomes
May 14: Being a product manager means never having to say, "that's not my job."
Too Big To Fail
Apr 9: When a company piles resources on a new product idea, it doesn't have room to fail. But failing is an important part of innovation. If you can't let it fail, it can't succeed.

Older...

What I'm Reading