Files
obs-streamer-tools-plugin/.gitea/scripts/publish-release.sh
T
shadowdaoandClaude Sonnet 5 14fa00af3f
Build / macOS (macos-latest) (push) Successful in 28s
Build / Linux (ubuntu-24.04) (push) Successful in 59s
Build / Windows (windows-latest) (push) Successful in 10m45s
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
2026-09-07 07:45:36 -07:00

162 lines
6.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# Creates a (draft) Gitea Release for the tag that triggered
# .gitea/workflows/release.yml, and uploads every archive in $DIST_DIR as a
# release asset.
#
# RELEASE GATE: see the README's `## Status` section and
# third_party/livekit/README.md. The WebRTC/OpenH264 attribution question
# ("C1") is unresolved -- this script does not decide that question, it just
# makes sure the generated release notes put the reminder where whoever
# publishes the draft will actually read it. Pushing a version tag is the
# human decision this whole workflow hangs off of; this script does not add
# or remove any judgment about whether that decision was the right one.
#
# Required env: GITEA_TOKEN, SERVER, OWNER, REPO, TAG, SHA, DIST_DIR
# Optional env: MACOS_BUNDLE_FOUND ("true"/"false", default "false")
set -euo pipefail
: "${GITEA_TOKEN:?}"
: "${SERVER:?}"
: "${OWNER:?}"
: "${REPO:?}"
: "${TAG:?}"
: "${SHA:?}"
: "${DIST_DIR:?}"
MACOS_BUNDLE_FOUND="${MACOS_BUNDLE_FOUND:-false}"
if [ "${MACOS_BUNDLE_FOUND}" = "true" ]; then
MACOS_NOTE="This archive contains a \`.plugin\` bundle."
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."
fi
NOTES_FILE="$(mktemp)"
cat > "${NOTES_FILE}" <<EOF
> **This build has not been cleared for redistribution.** The plugin
> statically/dynamically pulls in Google WebRTC and OpenH264 code through the
> LiveKit SDK, and whether that can be redistributed as a public download --
> the "C1" attribution/patent question -- has not been resolved. Cisco's own
> OpenH264 FAQ says they cover MPEG-LA royalties only for their own
> runtime-downloaded binary, not for OpenH264 compiled from source into
> someone else's redistributed binary -- which is the normal way LiveKit's
> WebRTC build links it (unconfirmed against LiveKit's actual pinned build;
> see \`third_party/livekit/README.md\`'s 2026-09-07 section for exactly
> what is and isn't verified). See the \`## Status\` section of
> \`README.md\` for the rest. By publishing this release, you are personally
> taking on that open question -- if C1 hasn't been signed off on, don't
> publish it.
>
> (The separate GPLv2/Apache-2.0 license-compatibility question, "C2", is
> resolved: this project's own first-party code is Apache-2.0, matching the
> vendored LiveKit binaries.)
>
> This release was created as a **draft**. It stays invisible to anyone
> without write access to this repo until someone with write access opens it
> here and clicks Publish -- a second, deliberate step past pushing the tag.
# streamer-tools Camera Plugin -- ${TAG}
Built from commit \`${SHA}\`.
**Nobody has yet run this plugin in the OBS GUI, on any platform.** See "What
is verified, and how" in \`README.md\` for exactly what has and has not been
checked, including which claims are 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; the WinHTTP backend has never been exercised against a real streamer-tools server, only a loopback test server -- see README's Windows CI section |
| macOS | \`streamer-tools-camera-${TAG}-macos.zip\` | Built and tested by this workflow's macOS job. ${MACOS_NOTE} See the "macOS packaging gap" in README |
## Installing
### Linux
\`\`\`
mkdir -p ~/.config/obs-studio/plugins/streamer-tools-camera
unzip streamer-tools-camera-${TAG}-linux-x64.zip -d /tmp/stplugin-camera
cp -r /tmp/stplugin-camera/bin /tmp/stplugin-camera/data \\
~/.config/obs-studio/plugins/streamer-tools-camera/
\`\`\`
Start OBS, then Sources -> \`+\` -> "streamer-tools Camera" -> fill in the
server URL, room slug and read key from the room's settings page ->
"Refresh camera list" -> pick a camera. This is the same drop-in layout
README's "Testing this by hand" documents for a source build, adapted for a
downloaded zip -- known-good on Linux.
### Windows (installation path not yet verified in real OBS)
Per \`AddExtraModulePaths()\` in obs-studio's \`UI/window-basic-main.cpp\`, OBS
on Windows searches a plugins directory for \`bin\\64bit\\<name>.dll\` plus a
sibling \`data\\\`. Unzip the archive and copy its \`bin\\\` and \`data\\\` into
your OBS plugins directory (typically
\`%APPDATA%\\obs-studio\\plugins\\streamer-tools-camera\\\`), matching the
Linux layout above. This has not been confirmed against a real OBS install on
Windows -- report back if you try it.
### macOS (installation path not yet verified in real OBS; packaging gap)
OBS on macOS loads plugins as \`<name>.plugin\` bundles under
\`~/Library/Application Support/obs-studio/plugins/\`. As of this release,
this project's \`build/package/\` output on macOS is **not yet that bundle
shape** -- see the "macOS packaging gap" section of \`README.md\`. Treat the
macOS archive here as a build-verification artifact, not a working
drop-in, until that gap is closed.
## What this is
Native OBS Studio source plugin that pulls streamer-tools camera feeds
directly from LiveKit over WebRTC. See \`README.md\` in the repository for
the full design, what is and is not verified, and current CI status.
EOF
echo "----- release notes -----"
cat "${NOTES_FILE}"
echo "--------------------------"
BODY_JSON="$(python3 - "$TAG" "$NOTES_FILE" <<'PYEOF'
import json, sys
tag, notes_file = sys.argv[1], sys.argv[2]
with open(notes_file) as f:
notes = f.read()
print(json.dumps({
"tag_name": tag,
"name": tag,
"body": notes,
"draft": True,
"prerelease": False,
}))
PYEOF
)"
echo "Creating release for tag ${TAG} ..."
RESP="$(curl -sS -f -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
-d "${BODY_JSON}" \
"${SERVER}/api/v1/repos/${OWNER}/${REPO}/releases")"
RELEASE_ID="$(python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])' <<<"${RESP}")"
echo "Created release id ${RELEASE_ID} (draft)."
shopt -s nullglob
ASSETS=("${DIST_DIR}"/*)
if [ "${#ASSETS[@]}" -eq 0 ]; then
echo "::error::no archives found in ${DIST_DIR} -- nothing to upload."
exit 1
fi
for f in "${ASSETS[@]}"; do
name="$(basename "${f}")"
echo "Uploading ${name} ..."
curl -sS -f -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-F "attachment=@${f}" \
"${SERVER}/api/v1/repos/${OWNER}/${REPO}/releases/${RELEASE_ID}/assets?name=${name}" \
> /dev/null
done
echo "Done. Draft release: ${SERVER}/${OWNER}/${REPO}/releases/${RELEASE_ID}"