← All projects

Browser-Based ATEM Control

A real-time web interface for controlling Blackmagic ATEM video switchers from any browser — full switching, transitions, keying, macros, and aux routing without desktop software.

Jun 2025
Django WebSocket Python PyATEMMax Alpine.js

What It Is

A complete browser-based control panel for Blackmagic ATEM video switchers — built to match the native ATEM Software Control as closely as possible, but running entirely in a browser over WebSocket.

Originally built as part of AV Site — my internal broadcast operations platform — but the control system is self-contained and works with any ATEM on the network.

Why I Built It

Blackmagic’s ATEM Software Control handles one switcher at a time, requires installation on every workstation, and offers no remote access. In an environment with many switchers spread across international studio locations, that doesn’t scale. I wanted any authenticated operator to open a browser, pick a switcher, and have full control instantly — no setup, no installs.

What You Can Control

The interface covers nearly the full feature set of the native software:

  • Program and Preview switching with source buttons that scale from mobile to 4K
  • Transitions — Cut, Auto, and a functional T-bar for manual transition control with real-time position tracking. Mix, Dip, Wipe, DVE, and Stinger styles with full configuration (stinger source, clip duration, trigger point, mix rate, pre-roll)
  • Four Upstream Keyers — each with Luma, Chroma, Pattern, and DVE tabs. The chroma implementation goes beyond basic keying — sample-based chroma with adjustable cursor position and size, plus a full color correction pipeline (brightness, contrast, saturation, per-channel RGB, spill and flare suppression)
  • Flying Key / DVE — full position, size, and rotation control. Border styling with bevel types, lighting direction, and shadows. Keyframe storage (A, B, Full) with animated run-to and a 9-direction Run To Infinite grid
  • Downstream Keys, Fade to Black, Color Generators, Aux Outputs, and Macro execution
  • Settings Panel that slides in from the side with the complete palettes for every feature above

How It Works

The frontend is Alpine.js talking to a Django Channels backend over WebSocket. Every button press sends a command to the server, which translates it into a PyATEMMax call to the physical switcher over Blackmagic’s proprietary UDP protocol. No SDK or official software on the server — just raw protocol communication.

Fully bidirectional and multi-user. The connection manager maintains multiple concurrent ATEM connections simultaneously. Multiple operators can be on different switchers at the same time, all sharing a connection pool with reference counting. Everything syncs in real-time — if someone switches a camera from the web interface, it shows up on the native ATEM Software Control. If someone presses a button on the physical hardware, every browser updates. If a second operator makes a change from the desktop app, the web clients reflect it instantly. Every source of control stays in sync, no matter where the change originates. A 2-second grace period on disconnect prevents page refreshes from dropping the connection, and a 5-minute inactivity timeout cleans up idle sessions automatically.

Smart polling. The system uses four polling tiers that adjust based on activity: 30ms during active transitions, 80ms after recent user input, 200ms during normal monitoring, and 400ms when idle. State changes are only pushed to clients when something actually changes — not on every poll cycle.

Session tracking. Every connection is logged — user, equipment name, IP, session duration, and disconnect reason (user-requested, inactivity timeout, switched to another ATEM, WebSocket closed).

The interface is fully responsive. An operator can pull it up on their phone, walk onto a studio floor, and switch cameras from their pocket.

Tech Stack

  • Backend: Django, Django Channels (ASGI), WebSocket
  • ATEM Protocol: PyATEMMax (custom fork — extended chroma sample API, flying key keyframes, DVE controls, color correction setters)
  • Frontend: Alpine.js, Tailwind CSS, DaisyUI
  • Deployment: Docker, Nginx Proxy Manager, Cloudflare SSL

Screenshots and screen recordings coming soon.

Coming soon — reverse engineering the ATEM protocol, building adaptive polling, getting the T-bar to sync across clients.

← All projects