abd4dc9aca58f49d76704ad65ddede648d3367ef
18
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
abd4dc9aca |
docs: record the first confirmed OBS GUI load (Windows)
Build / macOS (macos-latest) (pull_request) Successful in 26s
Build / Linux (ubuntu-24.04) (pull_request) Successful in 59s
Build / macOS (macos-latest) (push) Successful in 37s
Build / Linux (ubuntu-24.04) (push) Successful in 55s
Build / Windows (windows-latest) (pull_request) Successful in 3m45s
Build / Windows (windows-latest) (push) Successful in 3m48s
The v0.1.0 Windows artifact loaded into OBS 32.2.2 on Windows 11 (build 26200) on a director's machine on 2026-09-09, from C:\ProgramData\obs-studio\plugins\streamer-tools-camera\bin\64bit\. That retires "has not been run in the OBS GUI on any platform", which this README asserted in four places. Scoped deliberately to what was actually observed: the module loads and registers its source type. Whether video renders, the colours, A/V sync, latency, and mid-show publisher restart are all still unverified, and Linux and macOS have still never been opened in the GUI. The "Not verified anywhere" list now says so explicitly rather than being deleted. Also drops the release-draft rationale that pointed at the no-GUI-load state, and carries the ProgramData install-path warning up into the status section, since that is what stopped the first GUI load from happening sooner. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AzGnvQ6wfD7bw7PZN35ft9 |
||
|
|
1571d7ecea | Merge pull request 'docs: the Windows plugin dir is ProgramData, not the config dir' (#2) from docs/windows-plugin-path into main | ||
|
|
bfc38f45ca |
docs: the Windows plugin dir is ProgramData, not the config dir
Build / macOS (macos-latest) (push) Successful in 36s
Build / Linux (ubuntu-24.04) (push) Successful in 55s
Build / macOS (macos-latest) (pull_request) Successful in 33s
Build / Linux (ubuntu-24.04) (pull_request) Successful in 1m9s
Build / Windows (windows-latest) (push) Successful in 10m51s
Build / Windows (windows-latest) (pull_request) Successful in 10m27s
The packaging section claimed `<config>/obs-studio/plugins/<name>/bin/64bit` is "exactly the layout OBS searches on Linux and Windows". The layout is right; the base directory is not the same on both. obs-studio's `AddExtraModulePaths()` uses `GetAppConfigPath` on Linux/macOS but `GetProgramDataPath` (`CSIDL_COMMON_APPDATA`) on Windows, so Windows scans `C:\ProgramData\obs-studio\plugins\`, never `%APPDATA%\obs-studio\` (`CSIDL_APPDATA`) — which on Windows is where OBS keeps its config. This bit a director on 2026-09-09: a correctly-shaped install under `AppData\Roaming` produced an OBS log with zero mention of the module. Noted here because the failure is silent — OBS names any module it finds but cannot use, so an absence of any line means the file is not on a scanned path at all. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AzGnvQ6wfD7bw7PZN35ft9 |
||
|
|
104326d05a |
docs/release: drop the C1 licensing gate, simplify install instructions
Build / macOS (macos-latest) (push) Successful in 29s
Build / Linux (ubuntu-24.04) (push) Successful in 49s
Build / Windows (windows-latest) (push) Successful in 2m50s
Release / macOS (macos-latest) (push) Successful in 33s
Release / Linux (ubuntu-24.04) (push) Successful in 56s
Release / Windows (windows-latest) (push) Successful in 3m20s
Release / Create Gitea Release (draft) (push) Successful in 19s
The WebRTC/OpenH264 attribution question tracked as "C1" throughout README, third_party/livekit/README.md, the release-notes template, and both workflow header comments is the project owner's call, and it has been made -- own sign-off given and reaffirmed. Remove the gate language and the extended research writeup from release-facing docs; keep the actual LICENSE/NOTICE files themselves (Apache-2.0 requires shipping those regardless of any of this). Also simplify the release notes' install instructions per owner request: point at each platform's default OBS plugins folder rather than walking through verbose per-platform copy/extract instructions -- the archives already extract straight into place (prior commit), so a short pointer is all that's needed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
e050b81d6c |
ci: stop re-downloading CMake/Ninja on every Windows run
Build / macOS (macos-latest) (push) Successful in 32s
Build / Linux (ubuntu-24.04) (push) Successful in 56s
Build / Windows (windows-latest) (push) Successful in 2m52s
Release / macOS (macos-latest) (push) Successful in 43s
Release / Linux (ubuntu-24.04) (push) Successful in 56s
Release / Windows (windows-latest) (push) Successful in 3m23s
Release / Create Gitea Release (draft) (push) Successful in 19s
lukka/get-cmake@latest re-fetched and re-extracted CMake + Ninja on every single Windows CI run. Its own cache (routed through this act_runner's built-in cache server) reported "Cloud cache miss" on every run, even one immediately after a run that logged a successful save under the exact same key -- an incompatibility between its bundled cache client and this act_runner's cache-server implementation, not a config gap. Separately and more importantly: the archive extraction step alone measured ~7.5 minutes for a 45MB zip on this VM, consistent with Defender real-time scanning rather than raw disk I/O. Together this was the dominant cost of every Windows CI run. CMake 4.4.2 and Ninja 1.12.1 are now installed once, directly on the winvm-builder VM's system PATH (C:\BuildTools\cmake, C:\BuildTools\ ninja), sidestepping the third-party action's cache entirely rather than debugging its internals further. Both Windows jobs now just verify cmake/ninja are present and fail loudly if not, instead of silently falling back to a slow reinstall. Full detail, including how to redo this if the VM is ever rebuilt, is in README's new "Windows runner: persistent build tools" section -- this is VM state, not something git reproduces. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
14fa00af3f |
docs: OpenH264/MPEG-LA royalty finding sharpens C1 -- not resolved
Cisco's own OpenH264 FAQ (openh264.org/faq.html) is explicit: they cover MPEG-LA/AVC patent-pool royalties only for their own prebuilt binary, downloaded at install time. Anyone who compiles OpenH264 from source and redistributes it inside their own binary takes on "all applicable license fees" themselves -- Cisco "will not be liable for any licensing fees incurred by other parties" in that case. LiveKit's client-sdk-cpp links Google libwebrtc via the webrtc-sdk org's fork, whose documented build args (rtc_use_h264=true, ffmpeg_branding="Chrome") are the standard Chromium/WebRTC recipe -- which links a from-source, statically-compiled copy of OpenH264 (from Google's mirror, not Cisco's runtime binary) into libwebrtc. That is exactly the shape of case Cisco's FAQ says voids their coverage. Not independently confirmed against LiveKit's actual pinned v1.10.1 build (their release archives ship only compiled output, no build manifest) -- this is webrtc-sdk/libwebrtc's documented default, not a verified fact about this specific artifact. This sharpens C1 into a concrete mechanism instead of a general open question. It does not resolve C1 -- if anything it strengthens the case for treating it as unresolved -- and none of this is a substitute for an actual legal opinion. Recorded in third_party/livekit/README.md (the full writeup), README.md's Status section, and the release-notes template in publish-release.sh so it reaches whoever opens a draft release next, not just this one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
1f342b1971 |
docs: Windows CI is green, log-verified; scope the w32-pthreads fallback
Records the outcome of
|
||
|
|
f27b1c0b45 |
Fix Windows configure: point find_package at OBS's exported w32-pthreads
The libobs_DIR fix in
|
||
|
|
2b216d3d75 |
ci: add tag-triggered release packaging workflow
Adds .gitea/workflows/release.yml, triggered only on a pushed v* tag, which builds all three platforms (reusing the exact same configure/build/test commands as build.yml, now factored out into .gitea/scripts/ so the two workflows can't drift), zips each platform's build/package/ output, and creates a draft Gitea Release with the archives attached. This is packaging automation only -- it does not resolve or bypass the C1 WebRTC/OpenH264 release gate documented in README.md's Status section. Nothing publishes until a human deliberately pushes a version tag (which should not happen before owner sign-off) and then explicitly publishes the resulting draft. The generated release notes lead with a restatement of the open C1 question specifically so that second step can't be taken by accident. build.yml is refactored (not rewritten) to call the same shared scripts; its job/step behavior is otherwise unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
969b8db94a |
license: relicense first-party code from GPL-2.0-or-later to Apache-2.0
Owner sign-off: replace root LICENSE with Apache License 2.0, add a root NOTICE file, and swap the GPL-2.0 boilerplate header in every first-party core/ and obs-adapter/ source file for a short Apache-2.0 notice. This resolves review finding C2 (GPLv2 top-level LICENSE vs. the vendored Apache-2.0 LiveKit SDK is a license-compatibility violation): the whole repo is now Apache-2.0, matching LiveKit, so there's no GPL/Apache clash left. Updated the README Status gate and the CI workflow comment to reflect that C2 is resolved, while leaving the C1 WebRTC/OpenH264 patent/royalty gate untouched -- that question is still open and still blocks release. third_party/ stays under its own upstream licenses; only this project's own code changed hands. All 6 CTest suites still pass after the header swap. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
a3579d4fd5 |
docs: bash-on-Windows is proven broken (WSL as local system), with the log
The |
||
|
|
2bbd94775a |
ci: patch obs-studio's Windows CMake to define OBS::w32-pthreads
libobs/cmake/os-windows.cmake unconditionally links OBS::w32-pthreads, but
in the OBS_CMAKE_VERSION>=3.0.0 ("modern") top-level CMakeLists.txt branch
this bootstrap selects, nothing ever adds deps/w32-pthreads (confirmed at
every checked tag, 30.0.2 through 31.1.1) -- only the legacy branch's
add_subdirectory(deps) does, and libobs/CMakeLists.txt itself only adds
deps/libcaption and deps/uthash.
Upstream's own CI never hits this because it leaves ENABLE_UI on, and
UI/cmake/os-windows.cmake happens to add deps/w32-pthreads as a side effect
of building the Qt UI. Building obs-frontend-api instead of libobs (as
upstream's CI does) does not help: UI/obs-frontend-api/CMakeLists.txt only
links OBS::libobs, and UI/CMakeLists.txt returns before reaching the file
that adds w32-pthreads whenever ENABLE_UI is off -- which this bootstrap
deliberately keeps off to avoid a ~100 MB Qt6 download this plugin's plain
obs_properties_* UI does not need.
Add _patch_obs_studio_w32_pthreads() to buildspec_common.cmake: after the
obs-studio archive is extracted and before the OBS sub-configure runs, patch
its libobs/CMakeLists.txt to add deps/w32-pthreads itself, guarded by the
same if(NOT TARGET OBS::w32-pthreads) check UI/cmake/os-windows.cmake already
uses upstream. Idempotent (skips if already patched) and fails loudly if the
expected anchor text is missing, rather than silently no-opping against a
future OBS version with a different libobs/CMakeLists.txt shape.
Verified locally: the CMake string(FIND)/string(REPLACE) patch logic was run
against the real libobs/CMakeLists.txt fetched from the obs-studio 30.0.2
tag, confirmed to produce the intended block, and confirmed idempotent on a
second run. The actual Windows CMake configure/build this unblocks cannot be
verified from this Linux sandbox -- that's what the next CI run is for.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE
|
||
|
|
c5fedd176f |
docs: the -A x64 fix is confirmed; Windows now blocked on OBS's own CMake
Updates the Windows record written in |
||
|
|
551f782d8a |
docs: correct Windows CI record, add release-gating note (C1/C2, I6)
Build / macOS (macos-latest) (push) Successful in 34s
Build / Linux (ubuntu-24.04) (push) Successful in 49s
Build / macOS (macos-latest) (pull_request) Successful in 33s
Build / Linux (ubuntu-24.04) (pull_request) Successful in 1m1s
Build / Windows (windows-latest) (push) Failing after 9m37s
Build / Windows (windows-latest) (pull_request) Failing after 9m27s
- I6: README claimed Windows CI status as "Unconfirmed". The actual record as of this review is 6 consecutive Windows CI failures on this branch, all at commits predating the two fixes believed to address it (the -A x64 argument fix and the PowerShell rewrite of the Windows steps). No completed run yet exercises either fix -- the runner's serial queue means commits with the fixes were still waiting behind older failing commits at the time of writing. Corrected the Status section, the CI summary table, and rewrote "Where the Windows bootstrap got to" to state this plainly instead of overstating progress. - C1/C2 (not resolved here, gating language only): added a prominent note to the README's top-level Status section stating that release/distribution of built binaries is blocked pending explicit owner sign-off on the WebRTC/OpenH264 attribution question and the GPLv2 LICENSE vs. Apache-2.0-linked-code compatibility question, pointing at third_party/livekit/README.md where the details already live. Checked .gitea/workflows/build.yml: it has no release-triggered publish step today (only actions/upload-artifact, which is CI-internal, not public distribution), so nothing currently needs blocking -- added a comment at the top of the workflow noting the gate so any future release/publish step is written with it in mind. Also corrected a stale test-count in README (test_api_client: 121 -> 127 checks, reflecting the new tests added in the prior commit). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE |
||
|
|
6829dd545a |
Stage the plugin into the directory layout OBS actually searches
The staged package put the module in build/package/bin. OBS does not look
there. From AddExtraModulePaths() in obs-studio's UI/window-basic-main.cpp,
the per-user plugin layout on Linux and Windows is:
<config>/obs-studio/plugins/<name>/bin/64bit/<name>.{so,dll}
<config>/obs-studio/plugins/<name>/data/
so build/package/ now uses bin/64bit and is a straight drop-in. Re-verified in
the headless libobs harness from the new path: the module loads, both sources
connect, frames arrive, the camera switch round-trips, and `ldd` on the staged
copy resolves liblivekit and liblivekit_ffi from bin/64bit via $ORIGIN.
macOS deliberately keeps the flat bin/ -- there OBS looks for a
<name>.plugin/Contents/MacOS bundle, which this build does not produce. That
gap is documented in README.md rather than papered over with a directory name
that would only look right.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE
|
||
|
|
9a1a1474a9 |
docs: record what CI actually proved, and the macOS packaging gap it does not
The macOS bootstrap now works end to end: obs-deps and obs-studio download,
libobs 30.0.2 builds from source, the real adapter compiles and links against
it, 6/6 tests pass, and the artifact uploads. The README's CI section records
all six failures it took to get there, each with the log line behind it, so
the next person to touch that code knows which changes are load-bearing.
It also records the gap CI cannot see. **The macOS artifact will not load in
OBS.app**, for two reasons neither a compile nor a link can catch:
- it is a bare streamer-tools-camera.so, and OBS on macOS loads plugins as
<name>.plugin bundles;
- otool -L shows the libobs dependency as the relative path
"libobs/libobs.framework/Versions/A/libobs", inherited from the
from-source libobs's own install name, where a real plugin needs
@rpath/libobs.framework/Versions/A/libobs plus an LC_RPATH into
OBS.app/Contents/Frameworks.
Fixing that means vendoring obs-plugintemplate's macOS bundle helpers or
adding an install_name_tool pass, and checking the result on an actual Mac.
Deliberately not attempted here rather than guessed at.
Windows is recorded as unverified. One real bug was found and fixed there --
the "-A x64,version=<SDK>" corruption of obs-studio's own dependency
architecture -- but the runner serialises jobs and no Windows run has yet
completed with the fix in place.
Also documents STPLUGIN_BOOTSTRAP_OBS=OFF for Linux builds, and adds the two
behaviours verified in the headless libobs harness since the last README
update: switching the selected camera reconnects cleanly (fresh nonce
identity, video returns, no stale frame), and two sources in one OBS process
both connect and both receive frames.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE
|
||
|
|
a484abec61 |
Make the OBS adapter real: properties UI, connect, and frame output
The stub source becomes an actual streamer-tools camera. On create it reads
server URL / room slug / read key / camera identity from obs_data_t, mints a
subscribe-only token through ApiClient, connects LiveKitSession, and pushes
decoded frames into obs_source_output_video / obs_source_output_audio. The
source is now OBS_SOURCE_ASYNC_VIDEO | OBS_SOURCE_AUDIO |
OBS_SOURCE_DO_NOT_DUPLICATE with an OBS_ICON_TYPE_CAMERA icon.
The file is C++ rather than C now: the core library's API is C++ and the C ABI
shim existed only to avoid that. obs-module.h already declares the module
entry points extern "C", so nothing is lost.
Properties UI: server URL, room slug, a masked read-key field (it is a
credential and is masked everywhere else in streamer-tools), a camera dropdown,
a "Refresh camera list" button, and a status line.
- The dropdown is built from a cache the worker keeps warm on every connect,
so opening properties never blocks on the network. The button is the
explicit way to force a round trip, with a shortened 5s timeout -- for which
ApiClient's two calls gained a timeout_ms parameter.
- The currently-selected identity is always in the list, labelled "(not in
this room)" if absent, so OBS cannot silently clear a working setting just
because the room happens to be dark.
- The status line is the OBS_TEXT_INFO property's description (which is what
OBS actually renders) and switches to the warning info type on a real error.
Threading: OBS's UI and graphics threads are never blocked on the network.
Each source owns a worker thread that mints, connects, and reconnects with
exponential backoff (1s -> 30s), waking early on any settings change via a
generation counter. Frames are pushed from LiveKitSession's reader threads
directly; obs_source_output_video/_audio are thread-safe.
Two details that matter operationally:
- A null frame is pushed whenever the session leaves Connected, so a camera
that stopped publishing clears instead of leaving its last frame on screen.
Leaving stale media up is precisely the failure this plugin exists to avoid.
- The SDK's own logging is routed into OBS's log file via
livekit::setLogCallback, instead of stderr where a director would never
see it. The adapter also logs the first frame and every later geometry
change, so a log answers "did video ever arrive, and at what size".
Packaging: the build now stages a runnable layout into build/package/ --
the module (RPATH $ORIGIN / @loader_path, so it resolves the LiveKit
libraries from beside itself rather than from the build tree), liblivekit +
liblivekit_ffi, the locale data, and the licence files. third_party/livekit/
carries client-sdk-cpp's Apache-2.0 LICENSE and NOTICE from the pinned tag.
Its README records a correction to the design doc: the "bundled LICENSE.md
with ~28 third-party licence blocks" the doc expects DOES NOT EXIST at
v1.10.1 -- not in any of the five release archives (which contain only
include/, lib/, bin/ and build-info.json) and not in the repo at that tag,
which has only LICENSE and NOTICE. The aggregated third-party notice covering
the WebRTC/OpenH264 code inside liblivekit_ffi.so has not been located, and
that is flagged as an open licensing question rather than papered over.
Verified on Ubuntu 24.04 against real libobs 30.0.2, a real
livekit-server 1.13.6, and a stand-in API serving plugin.routes.ts's exact
shapes, using a headless libobs harness (obs_startup + obs_reset_audio +
obs_reset_video + obs_open_module + obs_source_create):
registered=1 output_flags=0x87
[streamer-tools-camera] connected to ws://127.0.0.1:7880 as
obs:main-room:qY85r9D0PaPt, watching cam-test
[streamer-tools-camera] video frame 640x360 I420
camera dropdown has 3 items:
[0] (no camera selected) =
[1] Test Camera = cam-test
[2] Dark Camera (offline) = other-cam
status: connected (info_type=0)
and with a deliberately wrong read key:
status: unknown room slug, or the read key is wrong or has been rotated
(info_type=1)
with retry-and-backoff and no crash. ctest: 6/6 passed.
Still unverified, and the README says so plainly: the OBS GUI on any platform,
macOS/Windows beyond compiling, A/V sync, and end-to-end latency.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RL8abRmgFXkVASHkkqiJbE
|
||
|
|
105f1041ab |
Scaffold core/OBS-adapter split, prove CMake toolchain, add 3-platform CI
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 |