docs: the macOS bundle was fine all along, and record the GUI verification #6
@@ -25,7 +25,7 @@ set -euo pipefail
|
||||
MACOS_BUNDLE_FOUND="${MACOS_BUNDLE_FOUND:-false}"
|
||||
|
||||
if [ "${MACOS_BUNDLE_FOUND}" = "true" ]; then
|
||||
MACOS_NOTE="This archive contains a \`.plugin\` bundle."
|
||||
MACOS_NOTE="This archive contains a \`.plugin\` bundle (verified on v0.1.0: MH_BUNDLE + Info.plist, libobs via \`@rpath\` + \`@executable_path/../Frameworks\`, LiveKit dylibs bundled, all three binaries code-signed). **arm64 only -- no Intel slice**, macOS 13+. Never yet loaded in OBS.app by a human."
|
||||
else
|
||||
MACOS_NOTE="This archive is packaged as a bare \`streamer-tools-camera.so\` (the layout \`build/package/\` currently produces on macOS), **not** an OBS.app-loadable \`.plugin\` bundle. It will not load in the OBS GUI as-is -- see the \"macOS packaging gap\" section of \`README.md\`."
|
||||
fi
|
||||
@@ -36,18 +36,22 @@ cat > "${NOTES_FILE}" <<EOF
|
||||
|
||||
Built from commit \`${SHA}\`.
|
||||
|
||||
**Read the per-platform notes below before relying on this.** The module has
|
||||
been loaded in the OBS GUI exactly once -- Windows, OBS 32.2.2 on Windows 11,
|
||||
2026-09-09 -- and only "it loads and registers its source type" is confirmed
|
||||
there. Whether video renders correctly, A/V sync, end-to-end latency and
|
||||
mid-show publisher restart are all still unverified on every platform. See
|
||||
"What is verified, and how" in \`README.md\` for exactly what is backed by
|
||||
automated tests versus a human watching OBS.
|
||||
**Confirmed working on Linux and Windows, including a live show.** The plugin
|
||||
carried a real broadcast on 2026-09-07. Video and audio both arrive and hold
|
||||
up across a session: Linux verified by the project owner, Windows by two
|
||||
directors independently.
|
||||
|
||||
Still unverified: **macOS in the OBS GUI** (nobody has opened it -- see the
|
||||
table), **measured** A/V sync and end-to-end latency against the existing
|
||||
egress path (no drift reported, but nothing measured), and whether a publisher
|
||||
restarting mid-show recovers cleanly on screen. See "What is verified, and
|
||||
how" in \`README.md\` for what is backed by automated tests versus a human
|
||||
watching OBS.
|
||||
|
||||
| Platform | Archive | Notes |
|
||||
|---|---|---|
|
||||
| Linux (x64) | \`streamer-tools-camera-${TAG}-linux-x64.zip\` | Functionally complete and verified end to end against a real LiveKit server and a real libobs (see README); OBS GUI itself still unverified |
|
||||
| Windows (x64) | \`streamer-tools-camera-${TAG}-windows-x64.zip\` | Built and tested by this workflow's Windows job. Confirmed to load in the OBS GUI (32.2.2 / Windows 11, 2026-09-09); nothing past module load is verified. The WinHTTP backend has never been exercised against a real streamer-tools server, only a loopback test server -- see README's Windows CI section |
|
||||
| Linux (x64) | \`streamer-tools-camera-${TAG}-linux-x64.zip\` | Functionally complete, verified end to end against a real LiveKit server and a real libobs (see README), and confirmed working in the OBS GUI |
|
||||
| Windows (x64) | \`streamer-tools-camera-${TAG}-windows-x64.zip\` | Built and tested by this workflow's Windows job, and confirmed working in the OBS GUI by two directors independently (first load: OBS 32.2.2 / Windows 11) -- which also exercises the WinHTTP backend against a real streamer-tools server |
|
||||
| macOS | \`streamer-tools-camera-${TAG}-macos.zip\` | Built and tested by this workflow's macOS job. ${MACOS_NOTE} |
|
||||
|
||||
## Installing
|
||||
|
||||
@@ -24,15 +24,21 @@ The plugin is **functionally complete on Linux and verified end to end there**
|
||||
real streamer-tools API shape, and pushes decoded frames into
|
||||
`obs_source_output_video`/`_audio`).
|
||||
|
||||
**First confirmed OBS GUI load: Windows, 2026-09-09** — the v0.1.0 release
|
||||
artifact loaded into OBS 32.2.2 on Windows 11 (build 26200) on a director's
|
||||
machine, from
|
||||
`C:\ProgramData\obs-studio\plugins\streamer-tools-camera\bin\64bit\`.
|
||||
That retires "the module will not even load in a real OBS" for Windows. It
|
||||
does **not** yet cover whether video renders correctly, colours, A/V sync or
|
||||
latency — see "Not verified anywhere" below for what is still open. Linux and
|
||||
macOS have still never been opened in the GUI; macOS builds the real module in
|
||||
CI but its artifact is not yet loadable (see the macOS packaging gap under CI).
|
||||
**Confirmed working in the OBS GUI on Linux and Windows, including a live
|
||||
show.** The plugin carried a real broadcast on 2026-09-07 and was reported to
|
||||
work well. Video and audio both arrive and hold up across a session: Linux
|
||||
verified by the project owner, Windows by two directors independently
|
||||
(2026-09-09/10; the first Windows load was OBS 32.2.2 on Windows 11 build
|
||||
26200, from
|
||||
`C:\ProgramData\obs-studio\plugins\streamer-tools-camera\bin\64bit\`).
|
||||
Because listing cameras requires an API call, that also retires "the WinHTTP
|
||||
backend has never run against a real streamer-tools server".
|
||||
|
||||
What that does **not** cover: measured A/V sync and end-to-end latency against
|
||||
the existing egress path (no drift reported over a session, but nothing was
|
||||
measured), mid-show publisher restart, and **macOS in the GUI — still never
|
||||
opened by anyone**, though its artifact is now known to be correctly packaged
|
||||
(see macOS packaging below). See "Not verified anywhere" for the current list.
|
||||
|
||||
⚠️ **The install directory is not the same on every platform, and getting it
|
||||
wrong fails silently.** On Windows it is
|
||||
@@ -169,15 +175,15 @@ plugins. This bit a director on 2026-09-09: a correctly-shaped install under
|
||||
`AppData\Roaming` produced a log with zero mention of the module.
|
||||
|
||||
The module resolves the LiveKit libraries from `$ORIGIN` (verified: `ldd` on the staged copy resolves both
|
||||
to `bin/64bit/`), not from the build tree. macOS is not this shape; see the
|
||||
macOS packaging gap under CI.
|
||||
to `bin/64bit/`), not from the build tree. macOS is not this shape — it ships
|
||||
a `.plugin` bundle; see macOS packaging under CI.
|
||||
|
||||
## Testing this by hand
|
||||
|
||||
**The module has been loaded in the OBS GUI on Windows once (2026-09-09, OBS
|
||||
32.2.2 / Windows 11 26200) — nothing beyond "it loads and registers its source"
|
||||
is confirmed there, and Linux and macOS have never been opened in the GUI at
|
||||
all.** To do it on Linux:
|
||||
**Linux and Windows are confirmed working in the GUI — video and audio over a
|
||||
real session, Linux by the project owner and Windows by two directors
|
||||
independently (2026-09-09/10). macOS has never been opened in the GUI by
|
||||
anyone.** To repeat the Linux run:
|
||||
|
||||
```
|
||||
mkdir -p ~/.config/obs-studio/plugins/streamer-tools-camera
|
||||
@@ -233,21 +239,17 @@ livekit-server 1.13.6 in dev mode):
|
||||
| Two sources in one OBS process | same harness with a second source added: both connect with distinct nonce identities, both receive frames, both tear down cleanly |
|
||||
|
||||
**Not verified anywhere:**
|
||||
- Anything past module load in the OBS GUI. Windows 2026-09-09 confirms the
|
||||
module loads and its source type appears; whether video actually renders
|
||||
(right way up, right colours), what the A/V sync and latency look like, and
|
||||
whether a publisher restarting mid-show recovers on screen are all still
|
||||
unanswered. Linux and macOS have not been opened in the GUI at all.
|
||||
- macOS beyond "CI builds and links the real module and the core tests pass".
|
||||
Its artifact is a bare `.so` with a relative libobs install name and will
|
||||
not load in OBS.app — see the macOS packaging gap under CI.
|
||||
- Windows beyond "the core library and the WinHTTP backend compile and their
|
||||
tests pass", from runs predating the current fixes. The WinHTTP backend has
|
||||
never run against a real streamer-tools server, only against the loopback
|
||||
test server in `test_api_client`.
|
||||
- A/V sync and end-to-end latency against the existing egress path.
|
||||
- Behaviour against the real production streamer-tools server (only against a
|
||||
stand-in serving the same shapes).
|
||||
- **macOS in the OBS GUI.** Nobody has opened it. Its artifact is now known to
|
||||
be a correctly-formed, correctly-linked, code-signed `.plugin` bundle
|
||||
(verified by inspecting the shipped v0.1.0 zip — see macOS packaging under
|
||||
CI), and it is arm64-only, so Intel Macs are out regardless. "The bundle is
|
||||
well formed" is not "OBS loaded it".
|
||||
- **Measured** A/V sync and end-to-end latency against the existing egress
|
||||
path. A live show and several sessions on Linux and Windows produced no
|
||||
reported drift, which is not the same as a measurement — and the timestamp
|
||||
caveat above is the reason to want real numbers.
|
||||
- Whether a publisher restarting mid-show recovers cleanly on screen.
|
||||
- Token expiry across a session longer than an hour (see below).
|
||||
- Token expiry after an hour. Expiry is handled *reactively*: a fatal
|
||||
disconnect makes the worker mint a fresh token and reconnect. The design
|
||||
doc's "proactively refreshed before expiry" is **not** implemented —
|
||||
@@ -261,8 +263,8 @@ runners available to this repo under the `CyberCoveLLC` org.
|
||||
| Job | `runs-on` | Runner | State |
|
||||
|---|---|---|---|
|
||||
| `linux` | `ubuntu-24.04` | `localhost.localdomain` | **Green.** Builds the real adapter against Ubuntu's libobs-dev 30.0.2, runs all six test suites, uploads `build/package` as an artifact |
|
||||
| `macos` | `macos-latest` | `home-mac` (Global) | **Green.** Builds libobs 30.0.2 from source, then the real adapter; 6/6 tests; artifact uploaded. But see the macOS packaging gap below |
|
||||
| `windows` | `windows-latest` | `winvm-builder` (org-scoped) | **Failing, fix pushed and awaiting a completed run.** Every completed run so far has failed; the latest got as far as building libobs and stopped on an OBS-side `OBS::w32-pthreads` target that its own modern CMake path never defines. A bootstrap patch for that gap has been pushed but not yet confirmed by a green run; see below |
|
||||
| `macos` | `macos-latest` | `home-mac` (Global) | **Green.** Builds libobs 30.0.2 from source, then the real adapter; 6/6 tests; artifact uploaded as a `.plugin` bundle. Never loaded in OBS.app, and arm64-only — see macOS packaging below |
|
||||
| `windows` | `windows-latest` | `winvm-builder` (org-scoped) | **Green.** Builds libobs 30.0.2 from source, then the real adapter; 6/6 tests; artifact staged. Was red twice more after the bootstrap was fixed, both times on `test_api_client`'s timeout probe — see "WinHTTP timeouts are not deadlines" below |
|
||||
|
||||
The Linux job is pinned to `ubuntu-24.04` rather than `ubuntu-latest`: this
|
||||
instance's two Linux runners answer `ubuntu-latest` with different releases,
|
||||
@@ -356,26 +358,36 @@ obs-studio, builds libobs from source, builds and links the real adapter,
|
||||
passes 6/6 tests, and uploads its artifact. `otool -L` on the result shows it
|
||||
linked against libobs and `@rpath/liblivekit.dylib`.
|
||||
|
||||
### macOS packaging gap (known, unfixed)
|
||||
### macOS packaging (was described here as broken; it is not)
|
||||
|
||||
**The macOS artifact will not load in OBS.app as it stands.** Two reasons,
|
||||
neither of which CI can catch, because CI only proves it compiles and links:
|
||||
**This section used to claim the macOS artifact was a bare
|
||||
`streamer-tools-camera.so` with a relative libobs install name that "will not
|
||||
load in OBS.app as it stands". That is wrong, and it contradicted the release
|
||||
notes for the same build.** Corrected 2026-09-10 by inspecting the shipped
|
||||
`streamer-tools-camera-v0.1.0-macos.zip` itself:
|
||||
|
||||
1. It is a bare `streamer-tools-camera.so`. OBS on macOS loads plugins as
|
||||
`<name>.plugin` bundles (`Contents/MacOS/<name>`, `Contents/Resources/`,
|
||||
an `Info.plist`), which is what obs-plugintemplate's
|
||||
`cmake/macos/helpers.cmake` builds and which this project deliberately did
|
||||
not vendor.
|
||||
2. `otool -L` shows the libobs dependency recorded as the relative path
|
||||
`libobs/libobs.framework/Versions/A/libobs`, inherited from the
|
||||
from-source libobs's own install name. A real plugin needs
|
||||
`@rpath/libobs.framework/Versions/A/libobs` plus an `LC_RPATH` pointing at
|
||||
`OBS.app/Contents/Frameworks`.
|
||||
- It is a proper bundle: `streamer-tools-camera.plugin/Contents/MacOS/streamer-tools-camera`
|
||||
(Mach-O **`MH_BUNDLE`**, which is what OBS loads), plus `Info.plist`
|
||||
(`CFBundlePackageType BNDL`, `CFBundleExecutable streamer-tools-camera`),
|
||||
`Contents/Resources/locale/en-US.ini`, and both LiveKit dylibs under
|
||||
`Contents/Frameworks/`.
|
||||
- The install names are right, which was the specific doubt. The module loads
|
||||
`@rpath/libobs.framework/Versions/A/libobs` and carries
|
||||
`LC_RPATH @executable_path/../Frameworks` — inside OBS.app that resolves to
|
||||
`OBS.app/Contents/Frameworks`, where libobs lives. `@rpath/liblivekit.dylib`
|
||||
resolves through `LC_RPATH @loader_path/../Frameworks` to the bundle's own
|
||||
copy, and `liblivekit.dylib` finds `liblivekit_ffi.dylib` through its own
|
||||
`LC_RPATH @loader_path`. Nothing points into a build tree.
|
||||
- All three binaries carry an `LC_CODE_SIGNATURE` (superblob `0xfade0cc0`),
|
||||
which is not optional: arm64 macOS refuses to load unsigned code at all.
|
||||
|
||||
Fixing this means either vendoring the template's macOS bundle helpers or
|
||||
adding an `install_name_tool` pass and a bundle layout — bounded work, but
|
||||
work that has to be done and checked on an actual Mac. It is deliberately not
|
||||
attempted here rather than guessed at.
|
||||
**The real macOS limitation is different: the bundle is arm64-only.** There is
|
||||
no x86_64 slice, so Intel Macs cannot load it, and `LSMinimumSystemVersion` is
|
||||
`13.0`. Shipping a universal binary would mean building both slices and
|
||||
`lipo`-ing them, on a Mac.
|
||||
|
||||
Everything above is static inspection of the artifact. **Nobody has yet opened
|
||||
it in OBS.app** — well-formed and signed is a strong prior, not a load.
|
||||
|
||||
### Where the Windows bootstrap got to
|
||||
|
||||
|
||||
Reference in New Issue
Block a user