- C 63.1%
- CMake 28.5%
- Shell 8.4%
OBS 32 marked obs_properties_add_button OBS_DEPRECATED, and the plugin builds with -Wdeprecated-declarations -Werror, so upgrading the system obs-studio package (now 32.2.0 here) breaks the Linux build outright. The headers come from the distro package, not from anything vendored, so this appeared without any change on our side. obs_properties_add_button2 has the same signature plus a void *priv and exists un-deprecated as far back as the OBS 31.1.1 that buildspec.json pins for the Windows and macOS dependency sets, so this is safe across all three targets. Passing src as priv rather than NULL: obs_property_button_clicked uses priv when set and otherwise falls back to context->data. Both callbacks want the slm_source_t, which is what context->data already was, so an explicit priv is behaviour-identical where src is non-NULL and falls back exactly as before in the get_properties(NULL) path -- and it does not depend on that fallback existing in a future OBS. Ref #35 |
||
|---|---|---|
| build-aux | ||
| cmake | ||
| data/locale | ||
| src | ||
| vendor | ||
| .clang-format | ||
| .gersemirc | ||
| .gitignore | ||
| build-plugin.sh | ||
| build.sh | ||
| buildspec.json | ||
| CMakeLists.txt | ||
| CMakePresets.json | ||
| LICENSE | ||
| publish.sh | ||
| README.md | ||
SLM Wire for OBS Studio
An OBS Studio plugin that receives live video and audio from a SLAY Media (SLM) sender and injects them into OBS as low-latency input sources.
What it does
The plugin registers two OBS source types:
- SLM Source (
slay_media_source) - receives video and audio - SLM Audio Source (
slay_media_audio_source) - audio only
Senders are discovered automatically via multicast (239.255.77.43:9878). Once a sender is found, the plugin connects and begins receiving frames. If the sender is on the same machine, it uses a shared memory ring buffer for zero-copy, sub-millisecond delivery. UDP is used otherwise.
Known senders
| Sender | Transport | Video codec |
|---|---|---|
| slay-cart - SLAY Media player | SHM (local) / UDP | Raw NV12, H.264, H.265 |
| slay-camera - Android camera app | UDP | H.265 (H.264 fallback) |
Protocol
SLM is a custom binary UDP protocol (magic SLM\x01, version 4). The handshake sequence:
- Sender broadcasts
ANNOUNCEon multicast - Plugin replies with
HELLO(unicast to sender'sctrl_port) - Sender sends
CAPS(resolution, FPS, pixel format, codec, audio params) - Sender streams video chunks and audio frames
Video frames are split into 1400-byte UDP chunks and reassembled. Audio fits in a single datagram. Optional LZ4 compression is supported for raw NV12 video.
Supported video codecs:
| Codec | Notes |
|---|---|
| Raw NV12 | Original SLM mode; optional LZ4 per-frame compression |
| H.264 (Annex B) | Software decoded via libavcodec |
| H.265 / HEVC (Annex B) | Software decoded via libavcodec |
H.264/H.265 frames arrive as complete Annex B access units, one per logical video frame (reassembled from chunks). The decoder is initialised on CAPS and replaced if the codec changes mid-stream. IDR frames carry inline SPS/PPS so the decoder can recover after packet loss.
Supported audio format: float32 PCM, mono or stereo, 48 kHz
Transport
| Transport | Platforms | Notes |
|---|---|---|
| Shared Memory | Linux, Windows | Zero-copy; used when sender and receiver are on the same machine |
| UDP | All | Used for remote senders; always the fallback if SHM becomes stale |
The plugin tries SHM first and monitors the sender's heartbeat. If the heartbeat goes stale (no update for 5 seconds), it falls back to UDP automatically.
On Linux, SHM uses POSIX shared memory (shm_open) and named semaphores. On Windows, it uses Named File Mappings (page-file-backed CreateFileMapping) and Win32 named semaphores - the shared data layout is identical on both platforms.
Source settings
| Setting | Default | Description |
|---|---|---|
| Sender name | (empty) | Filter by sender name. Empty accepts any sender. Dropdown auto-populates from discovery. |
| Port | 0 (auto) | UDP port to listen on. 0 lets the OS pick a free port. |
| Force UDP | off | Skip SHM and use UDP only. Enable this for remote senders on another machine. |
Building
Windows
Requires Visual Studio 2022 and CMake 3.30+.
cmake --preset windows-x64
cmake --build --preset windows-x64
Install target places the plugin at %ALLUSERSPROFILE%\obs-studio\plugins\slm-wire-for-obs\bin\64bit\slm-wire-for-obs.dll.
Linux (Ubuntu 24.04)
Requires CMake 3.28+, ninja-build, pkg-config, and build-essential.
cmake --preset ubuntu-x86_64
cmake --build --preset ubuntu-x86_64
Platform notes
- Windows uses Winsock2; Linux/macOS use POSIX sockets.
- SHM works on both Linux and Windows. The
Force UDPsetting disables SHM on all platforms. - Multicast requires sender and receiver to be on the same subnet (or multicast routing to be configured for remote senders).
Planned
- Tally signal (#21): OBS detects when a source enters or leaves the Program/Preview slots and unicasts
PKT_TALLYback to the sender so remote operators know they are live. - Operator messaging (#21): A text field in the source properties lets the studio operator send a short message to the connected sender (e.g. "zoom in"), displayed as an overlay on the remote device.
- Dynamic bitrate feedback (#10): Loss-rate reporting from receiver to sender to allow encoder step-down on degraded links.