Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/build-whisper-stt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,10 @@ jobs:
name: whisper-stt-${{ matrix.tag }}
path: whisper-stt-${{ matrix.tag }}.tar.gz
if-no-files-found: error
retention-days: 30
# build.yml now stages these into the installers
# (scripts/stage-whisper-stt.sh), so an expired artifact fails a
# release build. 90 days instead of 30 to make that rarer.
retention-days: 90

- name: Workflow summary
if: always()
Expand Down
36 changes: 27 additions & 9 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,16 @@ jobs:
- name: Setup Node.js
uses: ./.github/actions/setup

# ponytail: STT is handled by the bundled whisper-stt-server (whisper.cpp
# with native DTW token timestamps). No separate VAD model is fetched
# here. See technical-documentation/architecture/transcription-and-captions.md for the full architecture.
# STT is the bundled whisper-stt-server (whisper.cpp with native DTW token
# timestamps); no VAD model is fetched here. The binary is built by
# build-whisper-stt.yml and staged below — without that step the installer
# ships without speech-to-text. See
# technical-documentation/architecture/transcription-and-captions.md.
- name: Stage whisper-stt binaries
shell: bash
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: bash scripts/stage-whisper-stt.sh win32-x64

- name: Build Windows app
run: npm run build:win -- --publish never
Expand All @@ -63,9 +70,11 @@ jobs:
- name: Setup Node.js
uses: ./.github/actions/setup

# ponytail: STT is handled by the bundled whisper-stt-server (whisper.cpp
# with native DTW token timestamps). No separate VAD model is fetched
# here. See technical-documentation/architecture/transcription-and-captions.md for the full architecture.
- name: Stage whisper-stt binaries
shell: bash
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: bash scripts/stage-whisper-stt.sh win32-x64

- name: Build Windows Store package
run: npm run build:win:store -- --publish never
Expand Down Expand Up @@ -102,8 +111,12 @@ jobs:
env:
npm_config_build_from_source: "false"

# ponytail: STT is handled by the bundled whisper-stt-server (see the
# build-windows comment); no VAD model is fetched here.
- name: Stage whisper-stt binaries
shell: bash
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: bash scripts/stage-whisper-stt.sh darwin-${{ matrix.arch }}

- name: Resolve macOS signing
id: signing
env:
Expand Down Expand Up @@ -261,7 +274,12 @@ jobs:
- name: Install pacman build dependencies
run: sudo apt-get update && sudo apt-get install -y libarchive-tools

# ponytail: no VAD fetch here either (see build-windows comment).
- name: Stage whisper-stt binaries
shell: bash
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: bash scripts/stage-whisper-stt.sh linux-x64

- name: Build Linux app
run: npm run build:linux -- --publish never

Expand Down
204 changes: 123 additions & 81 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,81 +1,123 @@
name: CI

# feat/ai-edition is a long-lived integration branch that PRs land on for
# months at a time. Without it listed here, every one of those PRs merged with
# no lint, no typecheck, no tests and no PR-title check.
on:
pull_request:
branches: [main, feat/ai-edition]
push:
branches: [main, feat/ai-edition]

jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: npm run lint

typecheck:
name: Type Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: npx tsc --noEmit

docs:
name: Docs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# No ./.github/actions/setup: check-docs.mjs imports only node builtins,
# so npm ci would be a minute of install for nothing. Node 22 is here for
# import.meta.dirname (needs >= 20.11).
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm run docs:check

test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: npm run test
- run: npm run test:browser:install
- run: npm run test:browser

build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: npx vite build

semantic-pr:
name: Validate PR title (semantic)
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
types: |
feat
fix
chore
refactor
perf
docs
test
build
ci
style
revert
requireScope: false
name: CI

# feat/ai-edition is a long-lived integration branch that PRs land on for
# months at a time. Without it listed here, every one of those PRs merged with
# no lint, no typecheck, no tests and no PR-title check.
#
# release/** is here for the same reason and it cost more: PRs #167, #168 and
# #169 — 30k+ lines of deletion and refactor — merged into release/1.8.0 with
# every one of those jobs skipped, because a release branch matched neither
# pattern. A release branch is the LAST place to run a build unguarded.
on:
pull_request:
branches: [main, feat/ai-edition, "release/**"]
push:
branches: [main, feat/ai-edition, "release/**"]

jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: npm run lint

typecheck:
name: Type Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: npx tsc --noEmit

typecheck-tests:
name: Typecheck (tests)
runs-on: ubuntu-latest
# A RATCHET, not a gate. tsconfig.json includes only src + electron and
# excludes **/*.test.ts, so no test file has ever been typechecked, and
# vitest transpiles without checking — fixture types have drifted from the
# schemas they claim to build for years. Failing on the whole backlog would
# put a red X on every PR that nobody can fix, and a check everyone ignores
# is worse than no check. So: fail only if the count GROWS. Lower BASELINE
# whenever you fix some; delete this job's baseline logic at zero.
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- name: Typecheck tests against a baseline
shell: bash
env:
BASELINE: 80
run: |
set -uo pipefail
COUNT=$(npx tsc -p tsconfig.test.json --noEmit 2>&1 | grep -c 'error TS' || true)
{
echo "## Test-file typecheck"
echo ""
echo "| | |"
echo "|---|---|"
echo "| Errors now | ${COUNT} |"
echo "| Baseline | ${BASELINE} |"
} >> "$GITHUB_STEP_SUMMARY"
if [ "${COUNT}" -gt "${BASELINE}" ]; then
echo "::error::Test-file type errors went ${BASELINE} -> ${COUNT}. Fix the new ones, or raise BASELINE in ci.yml with a reason."
npx tsc -p tsconfig.test.json --noEmit 2>&1 | grep 'error TS' || true
exit 1
fi
if [ "${COUNT}" -lt "${BASELINE}" ]; then
echo "::notice::Test-file type errors down to ${COUNT} (baseline ${BASELINE}). Lower BASELINE in ci.yml to lock the win in."
fi

docs:
name: Docs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# No ./.github/actions/setup: check-docs.mjs imports only node builtins,
# so npm ci would be a minute of install for nothing. Node 22 is here for
# import.meta.dirname (needs >= 20.11).
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm run docs:check

test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: npm run test
- run: npm run test:browser:install
- run: npm run test:browser

build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: npx vite build

semantic-pr:
name: Validate PR title (semantic)
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
types: |
feat
fix
chore
refactor
perf
docs
test
build
ci
style
revert
requireScope: false
61 changes: 61 additions & 0 deletions THIRD-PARTY-NOTICES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Third-party notices

OpenScreen is MIT licensed (see [LICENSE](LICENSE)). The installers additionally
bundle the pre-built native components below. This file ships inside the
application resources and satisfies the attribution and source-offer obligations
that come with them.

npm dependencies are not listed here: they are resolved from `package.json` and
distributed by their own registries, not redistributed inside our binaries.

---

## FFmpeg — shared libraries (Windows only)

- **Components**: `avcodec-*.dll`, `avformat-*.dll`, `avutil-*.dll`,
`swresample-*.dll`, `swscale-*.dll` and their siblings, under
`resources/electron/native/bin/win32-*/`.
- **Used by**: the native D3D11 compositor addon, which links against them at
load time.
- **License**: **GNU Lesser General Public License v2.1 or later**
(<https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html>). FFmpeg's own
licensing page: <https://ffmpeg.org/legal.html>.
- **This is an LGPL build, not a GPL one.** It is configured without
`--enable-gpl` and without `--enable-nonfree`, and links no GPL-only library
(x264, x265, xvid, vidstab, rubberband, frei0r, …). `scripts/fetch-ffmpeg.mjs`
verifies this before vendoring — it reads `ffmpeg -L`, `-buildconf` and
`-encoders` and refuses any binary that reports otherwise.
- **Upstream binaries**: BtbN/FFmpeg-Builds, release
`autobuild-2026-07-15-14-01`, the `*-lgpl-shared-8.1` assets. Pinned by
SHA-256 in `scripts/fetch-ffmpeg.mjs`; the digests there identify the exact
artifacts we ship.
<https://github.com/BtbN/FFmpeg-Builds/releases/tag/autobuild-2026-07-15-14-01>
- **Corresponding source**: FFmpeg n8.1.2, commit `94138f6973`, from
<https://github.com/FFmpeg/FFmpeg>. The build configuration and scripts that
produced these exact binaries are published at
<https://github.com/BtbN/FFmpeg-Builds>.
- **Relinking**: as required by the LGPL, these are dynamic libraries. You may
replace them with your own build of the same FFmpeg version by overwriting the
DLLs in `resources/electron/native/bin/win32-*/`.

## whisper.cpp and ggml

- **Components**: `whisper-stt-server` and its ggml backend sidecars, under
`resources/electron/native/bin/<platform>-<arch>/`.
- **License**: MIT — <https://github.com/ggml-org/whisper.cpp> and
<https://github.com/ggml-org/ggml>.
- Built from source by `scripts/build-whisper-stt.sh`; the pinned upstream
revision is in `electron/native/whisper-stt/CMakeLists.txt`.
- The speech model (`ggml-*.bin`) is **not** bundled — it is downloaded into the
user's data directory on first use by `electron/stt/modelManager.ts`.

## OpenScreen native helpers

`wgc-capture` (Windows Graphics Capture), the ScreenCaptureKit helper (macOS)
and the D3D11 compositor addon are part of this repository and are covered by
[LICENSE](LICENSE).

---

To report an omission or request source for anything bundled here, open an issue
at <https://github.com/getopenscreen/openscreen/issues>.
Loading
Loading