- The OBS-NDI plugin relies on timecode for syncing NDI sources. That timecode can either come from the video source (eg. camera), called “Source Timing” or from the encoder itself, called “Network Timing”. Network Timing on BirdDog encoders is essentially broken because the encoders don’t have network time sync (NTP). There’s a patch available for OBS-NDI which works around this.
- BirdDog NDI audio in OBS sometimes glitches, not sure why.
- BirdDog encoders in AUTO signal detection mode, when run without a valid input signal, cause OBS to crash (vMix seems to do the same, implying an issue in the NDI library). If the signal is set explicitly no crashes occur.
- BirdDog headsets must be charged by USB before use.
- BirdDog Comms require two groups to be created in the NDI Access Manager (detailed below).
- BirdDog 4K Flex Encoders output enough power via the DC Out jack to power a Panasonic FZ2500 but not a Sony PMW-Z150 ENG Camera, nor a Sony HXR-NX5.
My first multicam shoot was around 12 years ago – and I was a camera operator (as opposed to an equipment supplier, mixer operator or technician). We used a Panasonic mixer, I think it had 4 video channels, lots of different wipes/transitions and it took composite video feeds. It wasn’t great.
Fast forward another 6 years and Blackmagic Design had introduced affordable SDI-based mixers. Fortunately our cameras were all SDI capable and so the switch to SDI was swift and hugely enjoyable. Suddenly we had beautiful, uncompressed full HD, no hum bars, no sadness.
Then, about two years ago, I came across the SlingStudio system, which was FANTASTIC, but had a whole bunch of limitations. I wrote about this previously, but in a nutshell the SlingStudio system is awesome provided your project fits within a very narrow set of criteria.
Things have moved on though and as I write this I am now trying to make the jump into the wonderful world of IP-based video switching, oh man, what a thrill.
My company was doing live streaming stuff on occasion before the Corona Virus hit. In fact for years before the Corona Virus pandemic I *begged* multiple clients to allow me to stream their productions. Some embraced the technology as a means of marketing themselves as tech-savvy, others rejected the proposal outright and some saw the technology as a way of connecting with clients and investors. Unfortunately the latter was the minority.
Of course Wuhan happened and now _everything_ is live streamed. Enter NDI and specifically BirdDog, an Australian company (mmm de ja vu/Blackmagic Design) that produces very affordable IP video encoders. Seriously, on paper these things RAWK. They’re affordable, they take POE (Power over Ethernet), they’re IP based, they accept any video signal up to 4K, they support PTZ cameras and most excitingly they can output 12V DC @ roughly 15W. This is better than what I was looking for.
BirdDog NDI encoders are in very short supply currently, but by scrounging around on the web I was able to acquire encoders necessary to perform an upcoming shoot. I landed up buying a combination of new and used encoders from 4 different vendors from all over the world.
The BirdDog Flex 4K encoders are really small and fit beautifully on top of my go-to live streaming cameras, namely the Panasonic FZ2500. I suspected that the encoder’s DC output would be good enough to power the camera, and I was right. One ethernet cable with POE (52V) is sufficient to drive both the encoder, camera and comms… so cool.
A ton of testing was undertaken and things were looking really good. Pictured above is a 24-port Mikrotik Router+Switch, with auto passive and active POE on every ethernet port. Attached are some cameras. An OBS instance, off-screen, is ingesting the feeds and compositing them into a single frame, which is then being output to a BirdDog Mini in decoder mode and being displayed on the monitor.
Things were stable and it seemed like a good time to try out the system on a simple upcoming job, which consisted of a camera feed and a laptop feed.
The shoot went really well, the quality was excellent. A small five-port POE switch provided power and data to devices and the OBS NDI output functionality (via obs-ndi) worked well for previews and duplicating presentation machine feeds to comfort monitors.
It was time to try something more ambitious: an offline, shoot for live, using 5 cameras with 3 camera operators, comms and a comfort monitor. Unfortunately I don’t have any photos of this for various reasons.
The structure of this shoot was as follows:
- A 24-port Mikrotik router and switch was positioned in the main venue. 6 NDI devices connected to this switch, namely 5 cameras (wide, mid and two close shots, as well as one camera purely for audio). An additional BirdDog Mini was used as a decoder for the comfort monitor.
- A 10 Gigabit fibre link from the 24-port switch to a smaller 5-port 10GbE Mikrotik switch.
- Three Windows (meh, not Linux) laptops, were connected to this switch. One OBS instance handled the comfort monitor and video playback. It output pre-recorded video content via NDI to both the comfort monitor and an OBS instance running on the second laptop.
- The second laptop switch between the NDI camera sources as well as the video playback laptop and recorded the result to a file. This was a “deferred” live stream, which was transmitted the following day.
- One laptop had a Caldigit 10GbE Thunderbolt 3-based NIC, the other had a 5GbE USB3 Kensington ethernet NIC. Pricing for 10G, 5G and 2.5G is near exponential in nature and for HD streams a 2.5G adapter is more than adequate.
- Finally, a third Windows laptop was running BirdDog’s Comms Lite application. This application requires that two send groups be configured in the NDI Access Manager. A requirement which isn’t obvious and is documented in a difficult-to-find section of Birddog’s Knowledgebase. Regardless, BirdDog’s Jon was quick to respond when I asked them for help. Also, if you bought the BirdDog headsets while they were still for sale, you must charge them using the micro-USB port before use. If you don’t the microphone won’t work (this really screwed me a bit, also not documented anywhere).
So we were sorted; multiple high-performance laptops, 10 and 5 GbE ethernet interfaces, 10GbE backbone, etc. The encoders were all configured for 120 mbit/sec. All camera feeds were ingested by both OBS machines and proxies were ingested by BirdDog Comms Lite (which shows previews).
- The first issue was stuttering. Our cameras were configured for 1080p @ 30fps, which on the wire is actually 29.97 fps. We were using 2x Panasonic FZ2500s (awesome cameras), 1x Sony FZ150 ENG-style camera and a Sony A7s MkII.
- If you set the BirdDog NDI encoders to “Auto” and they don’t have a signal on the HDMI port, OBS will crash! If you set the encoders to a specific framerate and resolution you won’t have this problem.
- When set to AUTO, the encoders detected the incoming framerate at 59.94, which I don’t believe it was but this reduced the stuttering. The next thing that further reduced the stutter was configuring OBS for a canvas framerate of 29.97 fps and setting the sync source to “Source Timing” vs “Network Timing” per source in OBS.
- At this point stutter had pretty much been eliminated, yay.
- The audio and video being rendered on the comfort monitor via the BirdDog Mini decoder (playing the feed from one of the OBS instances) was out of sync by around 400ms. I don’t know why.
- During the production, two of the camera feeds went severely out of sync, by as much as 2 seconds. Restarting the sources in question (by changing one of their properties) temporarily fixed the sync.
- The audio occasionally stuttered (momentary glitch every 4-10 minutes).
- The audio was severely distorted and amplified compared to what the camera’s VU meters were indicating.
Unfortunately, one could describe the above as a mild f*ck up. Luckily we weren’t live and had backup recordings of everything.
Before we head into the sync side of things it’s useful to have a broad overview of how OBS works. In short, OBS uses frame timestamps to determine when to render a frame. Timestamps are therefore extremely important for syncing. A new frame is requested in OBS (on a timer, a tick) and OBS goes, per source, “is the source’s current frame newer than the last frame we rendered AND has the frame’s time elapsed relative to the system time, if so, render the frame, otherwise keep the last good frame”.
The NDI SDK, which is a fantastic document, details two sync modes, namely source and encoder sync. OBS-NDI maps source sync to “Source Timing” and encoder sync to “Network Timing”. If your cameras emit timecode and they’re synced, “Source Timing” should work well… but my cameras are cheap, so I don’t have this option.
The next option is Network Timing/encoder sync. In this case the encoder uses it’s internal clock (aka wall clock) to timestamp the outgoing frames. This timing data is accurate to 100ns in terms of resolution. This sync method is only useful if the clocks on your encoders are synced. BirdDog does not include any kind of synchronisation method on their encoders – so this doesn’t work. In fact this is super annoying because further analysis demonstrates that they’re using an off-the-shelf distribution of Linux which can easily include an NTP client. More on this in the teardown post.
So, there’s really only one other option then, and that’s for OBS to timestamp frames as it receives them. What a hack. Fortunately someone has already done this and I’ve been able to test it to confirm it practically fixed the sync issues.
I started by acquiring a super cheap Chinese HDMI splitter.
In concert with another splitter I was able to duplicate one HDMI signal to 5 BirdDog encoders, which consisted of 4x HDMI Flex 4K Ins and 1x BirdDog Mini.
On an oldish Linux laptop (Ubuntu), I ran an ffmpeg/ffplay combo command which outputs a test video pattern as well as burnt in timecode, down to the frame. I also included a “beep” file, which outputs an auditory beep every 5 seconds (5 seconds on, 5 seconds off). Below is the command:
ffmpeg -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 -filter_complex "amovie=intermittenbeep.mp3:loop=0,volume=0.8,asetpts=N/SR/TB[bg];[bg]amix=duration=shortest" -f lavfi -i testsrc=duration=36000:size=1920x1080:rate=30 -vf drawtext="fontsize=15:fontfile=/Library/Fonts/DroidSansMono.ttf:\ timecode='00\:00\:00\:00':rate=25:text='TCR\:':fontsize=72:fontcolor='white':\ boxcolor=0x000000AA:box=1:x=860-text_w/2:y=960" -c:v prores -pix_fmt yuv422p10 -f mov -movflags frag_keyframe+empty_moov - | ffplay -fs -i -
The font file above isn’t important as ffmpeg will default to an available font if it can’t find the file specified.
As can be seen above, on a high speed network, even on gigabit ethernet, with synthesised timestamps OBS renders the feeds exactly in sync (for video at least). Audio is still distorted though, but only for specific frequencies. My solution to this, in the interim, is to try and use a Dante Audio Interface (Virtual ASIO sound card), but this solution is still pending testing.
NDI Sources must be configured to use Low Latency mode. Network/Source timing doesn’t matter as the above patch obliterates those timestamps in favour of OBS’s system timestamp (essentially, render the frame as soon as it arrives).
This change has not made its way into the current OBS-NDI plugin release, but is available here as a dev build.
If you’d like a slightly deeper dive into BirdDog Encoders, click here.