First pass on the streamer-tools OBS camera plugin: a minimal but real CMake project matching the design doc's core-library/OBS-adapter split (docs/superpowers/specs/2026-09-06-obs-camera-plugin-design.md in the streamer-tools repo). No LiveKit FFI integration yet -- this proves the toolchain works. - core/: dependency-free C++17 library (no OBS dependency), unit tested via CTest with no external test framework. - obs-adapter/: adapted from obsproject/obs-plugintemplate (commit 3e7d7ac, 2025-12-09). Registers a real, stubbed OBS source type; builds as a genuine dynamically-linked OBS module against Ubuntu's system libobs-dev (confirmed via ldd/nm, not a fake stand-in). - Simpler hand-written top-level CMakeLists.txt in place of the template's full buildspec-driven bootstrap (which downloads full OBS source + prebuilt deps) -- find_package(libobs) alone is enough on Linux; falls back to core-library-only when libobs isn't found (expected on macOS/Windows CI for now). - .gitea/workflows/build.yml: 3-platform matrix (ubuntu-latest, macos-latest, windows-latest) matching the runners confirmed available to this repo under the CyberCoveLLC org. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE
160 lines
8.2 KiB
Markdown
160 lines
8.2 KiB
Markdown
# obs-streamer-tools-plugin
|
|
|
|
Native OBS Studio source plugin that will pull streamer-tools camera feeds
|
|
directly from LiveKit over WebRTC (via LiveKit's `livekit-ffi`), replacing
|
|
the current SRT/RTSP-via-VLC-or-Media-Source path for directors. Full
|
|
design: `docs/superpowers/specs/2026-09-06-obs-camera-plugin-design.md` in
|
|
the `streamer-tools` repo (as of this writing, that doc lives on the
|
|
`worktree-obs-plugin-server-api` branch there, not yet merged to `main`).
|
|
|
|
## Status: scaffolding only
|
|
|
|
**This repository does not talk to LiveKit or streamer-tools yet.** This
|
|
first pass exists to prove the CMake toolchain, the core-library/OBS-adapter
|
|
split, and the three-platform Gitea Actions CI pipeline all actually work,
|
|
so the next phase (real `livekit-ffi` integration) can be planned against
|
|
verified facts instead of assumptions. See the design doc's "Components"
|
|
and "CI / build pipeline" sections for the target architecture this scaffold
|
|
is standing up.
|
|
|
|
## Layout
|
|
|
|
```
|
|
core/ - core library (C++17, no OBS dependency, headless-testable)
|
|
include/stplugin/
|
|
core.h C++ API (ConnectionConfig, core_version())
|
|
core_c.h C ABI wrapper the OBS adapter calls into
|
|
src/core.cpp
|
|
tests/ dependency-free CTest unit tests
|
|
|
|
obs-adapter/ - thin OBS glue (C, adapted from obsproject/obs-plugintemplate)
|
|
src/plugin-main.c obs_module_load/unload + a stub source registration
|
|
src/plugin-support.{h,c.in}
|
|
data/locale/en-US.ini
|
|
|
|
.gitea/workflows/build.yml - 3-platform CI matrix (see below)
|
|
```
|
|
|
|
Everything in `core/` is real, working, unit-tested code -- it just doesn't
|
|
do anything useful yet (a version string, a config struct with non-empty
|
|
validation). Everything in `obs-adapter/` is real OBS module code -- it
|
|
registers an actual `obs_source_info` and builds as a real, dynamically
|
|
loadable OBS module (see "Verified" below) -- but the source is a stub:
|
|
`create`/`destroy` allocate/free a dummy blob, there is no properties UI,
|
|
and no frames are ever pushed. That's the boundary this task was scoped to.
|
|
|
|
## What's real vs. deliberately deferred
|
|
|
|
Deferred, per the task that produced this scaffold (out of scope for this
|
|
pass, in scope for the next one):
|
|
|
|
- No `livekit-ffi` linkage of any kind.
|
|
- No streamer-tools API client (auth, slot-listing, token minting).
|
|
- No properties UI (server URL / room slug / read key / camera dropdown).
|
|
- No frame output (`obs_source_output_video`/`_audio`).
|
|
- No packaging/release step (the design doc's "on a version tag" job).
|
|
|
|
## Toolchain notes (verified on this machine: Ubuntu 24.04 / Linux)
|
|
|
|
- **CMake 3.28.3**, **Ninja 1.11.1**, GCC 13.3.0 -- all installed via
|
|
`apt-get install cmake ninja-build`. Top-level `CMakeLists.txt` requires
|
|
CMake >= 3.16 (deliberately lower than the official
|
|
obsproject/obs-plugintemplate's `3.28...3.30` floor -- see below).
|
|
- **OBS plugin template used as reference**: obsproject/obs-plugintemplate,
|
|
commit `3e7d7ac3b5342cd7d9b88890b9c70b472d1520fc` (2025-12-09, "Fix typo
|
|
of Visual Studio in README"), fetched fresh from GitHub. `src/plugin-main.c`,
|
|
`src/plugin-support.{h,c.in}`, and the empty `data/locale/en-US.ini` in
|
|
`obs-adapter/` are adapted directly from it.
|
|
- **Deliberate deviation from the template's own build system**: the
|
|
official template's `CMakeLists.txt` chains into
|
|
`cmake/common/bootstrap.cmake`, which in turn reads `buildspec.json` and
|
|
*downloads full OBS source archives (pinned to OBS 31.1.1) plus prebuilt
|
|
dependency bundles* for macOS and Windows. That machinery is real,
|
|
actively maintained, and probably the right long-term answer for
|
|
cross-platform reproducible builds -- but it's heavy (multi-hundred-MB
|
|
downloads, a whole `cmake/{macos,windows,common}` support tree, Qt6,
|
|
code-signing hooks) and out of scope to stand up and debug in one pass.
|
|
This scaffold instead uses a much simpler hand-written top-level
|
|
`CMakeLists.txt` that calls `find_package(libobs)` directly.
|
|
- **On Linux, this actually works far better than expected**: Ubuntu ships
|
|
a real `libobs-dev` package (`30.0.2+dfsg-3build1` on 24.04, i.e. **not**
|
|
the 31.1.1 the template's buildspec.json pins -- worth reconciling before
|
|
the next phase if API surface matters) with genuine CMake package config
|
|
files (`/usr/lib/x86_64-linux-gnu/cmake/libobs/libobsConfig.cmake`,
|
|
`libobsTargets.cmake`) that export an `OBS::libobs` imported target --
|
|
the exact target name the official template expects. `find_package(libobs
|
|
QUIET)` finds it with zero extra plumbing. This means the OBS adapter in
|
|
this repo links against **real OBS headers and a real `libobs.so`**, not
|
|
a stub -- confirmed by `ldd` showing `libobs.so.0` and `nm -D` showing
|
|
real `obs_module_*` exports (see "Verified" below). Install via
|
|
`apt-get install libobs-dev` (pulls in Qt6 as a dependency chain, ~seconds
|
|
on a fast mirror).
|
|
- **macOS/Windows have no equivalent system package** (there's no Homebrew
|
|
formula or winget package that ships `libobsConfig.cmake` the way Ubuntu's
|
|
`libobs-dev` does). For those platforms the choices are: (a) adopt the
|
|
template's full buildspec-driven source/prebuilt-deps download, or (b)
|
|
find/produce a lighter prebuilt SDK bundle. **This is now a concrete,
|
|
scoped decision for the next phase**, not a guess -- the CI workflow in
|
|
this repo currently takes option (c) for this pass only: skip building
|
|
the OBS adapter on macOS/Windows and build+test just the core library,
|
|
via the same `find_package(libobs QUIET)` fallback the top-level
|
|
`CMakeLists.txt` already has for exactly this situation.
|
|
- **`ENABLE_QT`/`ENABLE_FRONTEND_API` template options were not carried
|
|
over** -- this scaffold's properties-UI-free stub doesn't need Qt yet;
|
|
the real adapter will need to revisit this once the properties UI
|
|
(server URL / room slug / read key / camera dropdown) is built.
|
|
|
|
## What actually builds, and how it was verified
|
|
|
|
```
|
|
$ cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
|
|
-- libobs found (/usr/lib/x86_64-linux-gnu/cmake/libobs) -- building OBS adapter module
|
|
-- Configuring done
|
|
-- Generating done
|
|
|
|
$ cmake --build build
|
|
[1/7] Building C object obs-adapter/CMakeFiles/streamer-tools-camera.dir/plugin-support.c.o
|
|
[2/7] Building C object obs-adapter/CMakeFiles/streamer-tools-camera.dir/src/plugin-main.c.o
|
|
[3/7] Building CXX object core/CMakeFiles/stplugin_core.dir/src/core.cpp.o
|
|
[4/7] Linking CXX static library core/libstplugin_core.a
|
|
[5/7] Building CXX object core/tests/CMakeFiles/stplugin_core_tests.dir/test_core.cpp.o
|
|
[6/7] Linking CXX shared module obs-adapter/streamer-tools-camera.so
|
|
[7/7] Linking CXX executable core/tests/stplugin_core_tests
|
|
|
|
$ ctest --test-dir build --output-on-failure
|
|
1/1 Test #1: stplugin_core_tests .............. Passed 0.00 sec
|
|
100% tests passed, 0 tests failed out of 1
|
|
|
|
$ ldd build/obs-adapter/streamer-tools-camera.so | grep obs
|
|
libobs.so.0 => /lib/x86_64-linux-gnu/libobs.so.0 (...)
|
|
|
|
$ nm -D build/obs-adapter/streamer-tools-camera.so | grep obs_module
|
|
0000000000001430 T obs_module_free_locale
|
|
0000000000001450 T obs_module_load
|
|
...
|
|
0000000000001490 T obs_module_unload
|
|
```
|
|
|
|
This is a genuine, dynamically-linked OBS module -- not the "standalone
|
|
shared library without linking OBS" fallback the scaffolding task's scope
|
|
explicitly allowed as an acceptable compromise. That fallback path is still
|
|
exercised (and needed) on macOS/Windows CI for now; see above.
|
|
|
|
## CI
|
|
|
|
`.gitea/workflows/build.yml` runs on every push/PR, matrixed across the
|
|
three runners confirmed available to this repo by living under the
|
|
`CyberCoveLLC` org (see the design doc's "CI / build pipeline" section):
|
|
|
|
| Job | `runs-on` | Runner |
|
|
|---|---|---|
|
|
| `linux` | `ubuntu-latest` | `gitea-runner.internal.cloud-hosting.io` (Global) or `localhost.localdomain` (org-scoped; **note:** now online with `ubuntu-latest`/`ubuntu-24.04`/`ubuntu-22.04` labels -- the design doc recorded it as offline, that's since changed) |
|
|
| `macos` | `macos-latest` | `home-mac` (Global) |
|
|
| `windows` | `windows-latest` | `winvm-builder` (org-scoped to `CyberCoveLLC`) |
|
|
|
|
The Linux job installs `libobs-dev` and builds the real OBS adapter module
|
|
plus the core library, then runs `ctest`. The macOS/Windows jobs build and
|
|
test only the core library for now (see toolchain notes above for why).
|
|
|
|
No packaging/release step yet -- out of scope for this pass.
|