Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
206 commits
Select commit Hold shift + click to select a range
deb19ed
design: import the OpenScreen design system — assets, titlebar and br…
EtienneLescot Jun 27, 2026
f5e5bd4
feat(editor): bootstrap the v3 editor model and shell, and make it th…
EtienneLescot Jun 25, 2026
a57f152
fix(editor): 0-byte recordings, and a scrub thumb stuck at 0% on an e…
EtienneLescot Jun 30, 2026
7705935
feat(timeline): build the multi-clip timeline — clips, viewport, lane…
EtienneLescot Jul 1, 2026
78f5220
feat(agent): agent tool runtime, with inspector and export polish
EtienneLescot Jul 2, 2026
551b509
fix(electron): stop EPIPE/ECONNRESET from crashing the main process
EtienneLescot Jul 2, 2026
5879a7f
test(editor): Playwright and computer-use end-to-end coverage
EtienneLescot Jul 2, 2026
8b03c28
feat(llm): provider and reasoning parity, SSE streaming and context c…
EtienneLescot Jul 2, 2026
8a0011e
feat(preview): wire zoom, annotation and speed regions plus the curso…
EtienneLescot Jul 2, 2026
0901fb1
feat(llm): discover provider models and persist LLM state
EtienneLescot Jul 2, 2026
53f5bb0
feat(transcript): reshape the source transcript modal and wire per-as…
EtienneLescot Jul 3, 2026
5383a51
feat(agent): port axcut's deepagents runtime, with per-message rewind…
EtienneLescot Jul 3, 2026
a2ecbbc
feat(stt): thread the Whisper language through, and rename sessions i…
EtienneLescot Jul 3, 2026
dfbe9b9
fix(launch): drop the HUD bar's drop-shadow halo
EtienneLescot Jul 3, 2026
4c248b3
feat(transcript): an aggregated transcript pane, editable through a s…
EtienneLescot Jul 3, 2026
88b1af5
refactor(editor): extract PreviewCompositor and the playback clock, a…
EtienneLescot Jul 4, 2026
50d6f19
feat(stt): move captioning to a native engine — whisper.cpp with alig…
EtienneLescot Jul 5, 2026
f187fd2
fix(preview): fall back to VirtualPreview for the screen stage
EtienneLescot Jul 6, 2026
4d8ca11
feat(stt): settle on whisper.cpp with DTW word timestamps, and stabil…
EtienneLescot Jul 8, 2026
877ca8a
fix: clear leftover merge-conflict markers and regenerate the lockfile
EtienneLescot Jul 8, 2026
caed614
fix(llm): find MiniMax's model slugs, fix its empty responses and wir…
EtienneLescot Jul 8, 2026
057389b
feat(editor): refactor to OpenScreen Editor v4 (Media/Edit/Rec) and m…
EtienneLescot Jul 9, 2026
a1fdca8
feat(timeline): rebuild the timeline from the v4 design (V4Timeline)
EtienneLescot Jul 9, 2026
15fc514
design: import the OpenScreen Design System
EtienneLescot Jul 8, 2026
557ea19
fix(recording): sync the webcam to native capture and compensate its …
EtienneLescot Jul 9, 2026
2657fd6
feat(docs): scaffold the Docusaurus site with its GitHub Pages CI
EtienneLescot Jun 26, 2026
7d0b8ba
feat(docs): a design-system landing page and feature documentation gr…
EtienneLescot Jul 9, 2026
157dd2d
fix(preview): fit the video to its container, with inspector-aware pa…
EtienneLescot Jul 10, 2026
87a4f9a
feat(timeline): unify the trim/effect model, ventilate on reorder, an…
EtienneLescot Jul 10, 2026
7ba1204
feat(editor): per-clip crop export, HUD/RecStage redesign, real wavef…
EtienneLescot Jul 11, 2026
acfae63
feat(editor): export UX, .openscreen project files, exact crop ratios…
EtienneLescot Jul 12, 2026
63a4566
feat(export): size exports to the largest clip and the timeline aspec…
EtienneLescot Jul 15, 2026
b89eb7f
fix(recording): reconcile main's recording fixes into the v4 recordin…
EtienneLescot Jul 15, 2026
e54ef66
feat(editor): re-port gradients, the File menu, 100x speed and Full C…
EtienneLescot Jul 15, 2026
503cd1c
ci(whisper-stt): scope the build cache to the runner image version
EtienneLescot Jul 15, 2026
7eb2828
feat(export): the RenderPlan data model and audio-concat planner, thr…
EtienneLescot Jul 15, 2026
511ef84
feat(export): render multi-asset timelines through the v2 segment loop
EtienneLescot Jul 15, 2026
527ee67
feat(export): apply timeline speed per sub-segment, and route every e…
EtienneLescot Jul 15, 2026
6aa796c
perf(export): a StageTimings harness and hardware-first encode, with …
EtienneLescot Jul 16, 2026
7611be5
docs(export-v2): measure the upstream chain — IPC is the bottleneck, …
EtienneLescot Jul 16, 2026
e076870
feat(export): detect ffmpeg's capabilities — binary path, encoder pic…
EtienneLescot Jul 16, 2026
3829e38
docs(native-core): price the Rust/wgpu compositor against sandbox:fal…
EtienneLescot Jul 16, 2026
12568d3
feat(export): stream frames to a native ffmpeg encoder behind a main-…
EtienneLescot Jul 16, 2026
fc38863
feat(bench): a headless export bench — the measurements that exclude …
EtienneLescot Jul 16, 2026
502c456
perf(export): stop rebuilding per frame what never changes — the wall…
EtienneLescot Jul 17, 2026
54dbce1
docs(architecture): one export document, and the target rendering arc…
EtienneLescot Jul 17, 2026
875fb8d
feat(bench): gate G0 — fence the GPU before the encode timers, and ca…
EtienneLescot Jul 17, 2026
c676500
fix(project): stop concurrent saves from splicing project files together
EtienneLescot Jul 17, 2026
a715fbf
feat(bench): price the shadow and the gaussians apart from the plumbing
EtienneLescot Jul 17, 2026
f186bb7
feat(poc): a full-shader compositor POC, instrumented with honest GPU…
EtienneLescot Jul 17, 2026
dda97f0
perf(poc): bake the background and cull what cannot be seen — 85 fps
EtienneLescot Jul 17, 2026
513577e
feat(poc): motion blur, a real cursor and an analytic Gaussian shadow…
EtienneLescot Jul 17, 2026
a7c5a71
perf(poc): measure throughput, not the empty loop — and serialise the…
EtienneLescot Jul 17, 2026
2b16afe
feat(poc-native): the WGSL compositor on native wgpu — pipe-bound at …
EtienneLescot Jul 17, 2026
831c765
feat(poc-native): CPU decode measured every way — the wall is CPU↔GPU…
EtienneLescot Jul 17, 2026
caf6391
feat(poc-native): zero-copy Vulkan decode via gpu-video, blocked only…
EtienneLescot Jul 17, 2026
16fa015
docs(architecture): D3D11 delivers GPU residency driver-free, and the…
EtienneLescot Jul 17, 2026
25f4b7c
feat(poc-d3d): the native D3D11 compositor — the retained fast path
EtienneLescot Jul 17, 2026
a5698c5
feat(poc-d3d): an interactive preview and export GUI
EtienneLescot Jul 18, 2026
44ec967
feat(poc-d3d): embed the native view in the editor — library crate, n…
EtienneLescot Jul 18, 2026
5dd36d2
feat(poc-d3d): native export on the addon, non-blocking and wired to …
EtienneLescot Jul 18, 2026
4724e6e
feat(poc-d3d): typed inspector params, a param store, and sync on act…
EtienneLescot Jul 18, 2026
e37409a
feat(poc-d3d): time-addressable rendering, with the app transport dri…
EtienneLescot Jul 18, 2026
faf4b23
feat(poc-d3d): inspector effects on the native path, live recompose, …
EtienneLescot Jul 18, 2026
72fb34f
feat(poc-d3d): native multiclip export over the real timeline
EtienneLescot Jul 18, 2026
52ab3b2
feat(scene): the SceneDescription contract — app to native, with buil…
EtienneLescot Jul 18, 2026
6583f97
feat(poc-d3d): consume the scene in Rust — the layout preset drives t…
EtienneLescot Jul 18, 2026
dd24b86
feat(poc-d3d): real backgrounds and a native cursor, with corrected p…
EtienneLescot Jul 18, 2026
e0935cd
feat(poc-d3d): zoom regions, full camera, export badges and native si…
EtienneLescot Jul 19, 2026
c94c9a0
refactor(scene): make sceneDescription the single source of truth
EtienneLescot Jul 19, 2026
9cd3355
chore: ignore the cc-delegate worktrees and drop its salvage snapshots
EtienneLescot Jul 19, 2026
74fa851
feat(poc-d3d): speed regions and the native audio pipeline
EtienneLescot Jul 19, 2026
1f9a6aa
feat(preview): stream native frames to the canvas — offscreen render …
EtienneLescot Jul 19, 2026
31a2958
fix(preview): cursor overflow, the readback's COM interface, and odd …
EtienneLescot Jul 19, 2026
331cc73
refactor(preview): remove the CPU and web fallbacks — one native path
EtienneLescot Jul 19, 2026
fd34f7f
fix(preview): PiP duplication, doubled CSS shadows, the real camera a…
EtienneLescot Jul 20, 2026
33f455a
feat(export): report real native export progress to the UI
EtienneLescot Jul 20, 2026
4eec287
fix(poc-d3d): webcam hwaccel, decode cadence and clip auto-advance
EtienneLescot Jul 20, 2026
5431dea
fix(scene): tag regions with their clip, follow the chosen aspect, an…
EtienneLescot Jul 20, 2026
f93a83d
fix(preview): timeline ordering, roundness, stray 'ended' events, sta…
EtienneLescot Jul 20, 2026
74ed7eb
fix(compositor): resolve the PATH-dependent ffmpeg addon load and fin…
EtienneLescot Jul 20, 2026
92b1b60
fix(compositor): corner rounding, background cover, crop aspect and e…
EtienneLescot Jul 20, 2026
b940965
fix(export): prefetch the cursor track, and settle the Source and ups…
EtienneLescot Jul 21, 2026
a0c1ec7
fix(compositor): webcam PiP dragging, and a drop shadow that went ell…
EtienneLescot Jul 21, 2026
1c35af1
fix: video-effects slider desync, a slow background picker, and the H…
EtienneLescot Jul 21, 2026
5d9fe36
fix(document): scope speed regions per clip, keep other assets' trims…
EtienneLescot Jul 21, 2026
b13c2e1
perf(preview): multi-clip trim jumps, canvas buffers and a decoupled …
EtienneLescot Jul 21, 2026
6e0af1d
perf(timeline): optimistic drag, memoised components and direct-DOM s…
EtienneLescot Jul 21, 2026
ae3d072
fix(architecture): anchor modifiers to clip boundaries and reproject …
EtienneLescot Jul 22, 2026
ce2325d
fix(vite): dedupe react so the app runs from a git worktree
EtienneLescot Jul 23, 2026
e222515
fix(timeline): anchor modifiers to clips and merge regions by identity
EtienneLescot Jul 23, 2026
56fae51
fix(compositor): rasterise at the output geometry, and drop the stret…
EtienneLescot Jul 23, 2026
8ec3266
perf(compositor): deliver only the preview frames that changed, and r…
EtienneLescot Jul 23, 2026
234b3b2
fix(preview): keep a mid-transition pause, and resolve regions from t…
EtienneLescot Jul 23, 2026
e54dec7
fix(document): finish migrating v1.7 projects when the media duration…
EtienneLescot Jul 23, 2026
c84da97
feat(layout): weld screen and camera into one contain-fitted block, a…
EtienneLescot Jul 24, 2026
09d6360
fix: derive the dev ffmpeg dir from the cargo pin, and drop a region …
EtienneLescot Jul 24, 2026
57ab917
fix(layout): stop the block camera inheriting the picture-in-picture …
EtienneLescot Jul 24, 2026
7154b2a
feat(topbar): swap the placeholder tile for the transparent brand mark
EtienneLescot Jul 24, 2026
aea845c
fix(timeline): let Shift+wheel pan even when Ctrl is held
EtienneLescot Jul 24, 2026
7553d2d
docs(design): ship the brand mark and the token vocabulary the cards …
EtienneLescot Jul 24, 2026
1a531b9
fix(layout): fit the screen box to the crop, and resolve the layout p…
EtienneLescot Jul 24, 2026
e83782b
docs(poc-d3d): flag the dead VITE_NATIVE_COMPOSITOR opt-in as removed
EtienneLescot Jul 24, 2026
d9d1018
feat(brand): ship Geist, the typeface the design system always specified
EtienneLescot Jul 24, 2026
714a00f
refactor(scene): carry fractions across the native contract, never pi…
EtienneLescot Jul 24, 2026
f73534e
fix(dev): give each checkout its own vite dependency cache
EtienneLescot Jul 24, 2026
4ea8575
feat(timeline): resolve the output format and size from every clip's …
EtienneLescot Jul 24, 2026
1e865a1
fix(timeline): resize a clip when its source range is edited, and fix…
EtienneLescot Jul 25, 2026
c56500d
feat(agent): give the agent delete tools and camera-fullscreen, with …
EtienneLescot Jul 25, 2026
ac82b70
feat(editor): New-project starting points, i18n for the right rail, a…
EtienneLescot Jul 26, 2026
8602843
docs(engineering): audit main against feat/ai-edition and spec the re…
EtienneLescot Jul 25, 2026
3b358a2
fix(recording): the WGC frame mutex, even dimensions, a writer hang n…
EtienneLescot Jul 16, 2026
cd6346a
fix(annotations): start text annotations empty, with a placeholder
EtienneLescot Jul 25, 2026
c894fee
fix: the playhead jumping at a reordered junction, and the mic surviv…
EtienneLescot Jul 25, 2026
cc627a8
feat(editor): a free speed field beyond 3x, and zoom focus that can f…
EtienneLescot Jul 25, 2026
c95e15c
docs(engineering): record what the remediation branch delivered
EtienneLescot Jul 25, 2026
a934768
feat(zoom): a global auto-focus toggle, steady eases and honest previ…
EtienneLescot Jul 25, 2026
274e0f8
feat(zoom): expose the 3D rotation presets
EtienneLescot Jul 25, 2026
8b8f7f3
feat(annotations): render annotations in the native compositor — arro…
EtienneLescot Jul 25, 2026
61b0987
feat(annotations): create and edit annotations from the inspector
EtienneLescot Jul 25, 2026
ee2af31
fix(zoom): match the diagonal arrowheads, and make the 3D containment…
EtienneLescot Jul 25, 2026
be5a6a9
fix(annotations): one standard colour field, a reversible background …
EtienneLescot Jul 26, 2026
d6f4d34
fix(zoom): the tilt was a collapsing quadratic — round its shadow and…
EtienneLescot Jul 26, 2026
7ef8934
feat(captions): make captions an independent, transcript-derived layer
EtienneLescot Jul 26, 2026
241471d
fix(captions): group translated captions into phrases, over the share…
EtienneLescot Jul 26, 2026
fad4a9d
perf(hud): reserve the overlay's space instead of discovering it
EtienneLescot Jul 26, 2026
92fbe07
chore(integration): take only main's CI and packaging, not its code
EtienneLescot Jul 26, 2026
ba7b8bf
docs: rename docs/ to technical-documentation/ and stage the reorg sk…
EtienneLescot Jul 26, 2026
1054ef6
docs: scope check-docs.mjs to a slice with --only
EtienneLescot Jul 26, 2026
dc685d7
docs: add the doc index and the decision ledger, repoint every inboun…
EtienneLescot Jul 26, 2026
03737f0
docs(architecture): overview, document model and preview
EtienneLescot Jul 26, 2026
626f689
docs: the AI layer, providers, build/packaging, CI, release and test …
EtienneLescot Jul 26, 2026
01969f5
docs: let check-docs.mjs accept path:line source anchors
EtienneLescot Jul 26, 2026
8aa18a3
docs(architecture): the timeline coordinate model and the editor shell
EtienneLescot Jul 26, 2026
43272a5
docs(engineering): compress the rendering measurement record 924 -> 3…
EtienneLescot Jul 26, 2026
60454f5
docs(architecture): the native compositor, and the export pipeline as…
EtienneLescot Jul 26, 2026
06d6e49
docs(architecture): cross-platform recording, and the native bridge
EtienneLescot Jul 26, 2026
61ab01a
docs: the cursor pipeline and its diagnostics
EtienneLescot Jul 26, 2026
eeedab1
docs: add npm run docs:check, and complete the preview chain in the o…
EtienneLescot Jul 26, 2026
1cd0c29
docs(architecture): transcription through to rendered captions
EtienneLescot Jul 26, 2026
1c8feb5
docs(testing): one manual E2E checklist against the v4 shell
EtienneLescot Jul 26, 2026
4466e54
docs: drop the _harvest staging directory
EtienneLescot Jul 26, 2026
c190a39
ci: run CI on feat/ai-edition, and gate the docs tree
EtienneLescot Jul 26, 2026
1ef32ff
fix(test): make two platform-dependent tests pass off Windows, and cl…
EtienneLescot Jul 26, 2026
1f6f193
fix(inspector): stop the collapse button swallowing every pane's Help…
EtienneLescot Jul 26, 2026
3fcbdca
test(e2e): retarget the editor specs at the v4 shell
EtienneLescot Jul 26, 2026
9d6e7e1
refactor(exporter): delete the web MP4 pipeline the native path replaced
EtienneLescot Jul 26, 2026
f69a89a
chore: drop the two superseded POCs and their spike residue
EtienneLescot Jul 26, 2026
4e06815
docs: drop consumed one-shot plans and a stale tracked worktree handoff
EtienneLescot Jul 26, 2026
980d96b
chore(deps): drop seven unused dependencies and a ghost CI cache
EtienneLescot Jul 26, 2026
eef1b0f
fix(export): remove the hardcoded fixture path from the shipped addon
EtienneLescot Jul 26, 2026
6649646
docs: repoint the export and preview docs at what survives the deletion
EtienneLescot Jul 26, 2026
71c99a4
refactor(math): one clamp instead of sixteen
EtienneLescot Jul 26, 2026
3566798
refactor: crypto.randomUUID over the uuid dep, and one MSVC bootstrap
EtienneLescot Jul 26, 2026
fc13624
refactor(format): one timecode module instead of six copies
EtienneLescot Jul 26, 2026
dfa6d1e
refactor: reuse the gradient parser, and spread the settings patch
EtienneLescot Jul 26, 2026
7bf0731
fix: restore the two guards the dedup dropped, and keep gradients gra…
EtienneLescot Jul 26, 2026
51126bc
chore: tighten the dedup's loose ends
EtienneLescot Jul 26, 2026
8a3eaaf
refactor(schema): drop the four document fields nothing ever read
EtienneLescot Jul 26, 2026
97d1c53
refactor(llm): one provider stack, and a real Copilot token swap
EtienneLescot Jul 26, 2026
41caa27
refactor(store): drop seven timeline actions with no callers
EtienneLescot Jul 26, 2026
60acafe
fix(llm): finish the reroute — Codex account header, one model per run
EtienneLescot Jul 26, 2026
a2070a0
chore(schema): finish the four-field removal the fixtures missed
EtienneLescot Jul 26, 2026
36e3966
refactor(editor): drop the write-only showTrimWaveform setting
EtienneLescot Jul 26, 2026
aecc236
fix(compositor): resolve scene assets outside the asar, so themes and…
EtienneLescot Jul 26, 2026
67a51e1
fix(zoom): feather the tilted plane's edge at radius 0, so a 3D zoom …
EtienneLescot Jul 26, 2026
f7a020d
fix(background): accept a blank MIME type by extension, and say so wh…
EtienneLescot Jul 26, 2026
e0c06ce
fix(compositor): bypass Electron's asar-transparent fs when probing f…
EtienneLescot Jul 27, 2026
ec81c6d
fix(cursor): pivot custom cursors on their hotspot, and give the nati…
EtienneLescot Jul 27, 2026
21e4713
fix(cursor): put the cursor on the tilted plane instead of floating i…
EtienneLescot Jul 27, 2026
1dc867a
fix(stt): re-anchor whisper's word boundaries on the audio, so transc…
EtienneLescot Jul 27, 2026
eb8bd0b
fix(transport): remove non-functional loop and fullscreen buttons
EtienneLescot Jul 27, 2026
9db8bdc
fix(llm): drop the two providers that shipped borrowed vendor credent…
EtienneLescot Jul 27, 2026
b8e0d4f
fix(ipc): one document service, a protocol allowlist, and a loopback-…
EtienneLescot Jul 27, 2026
ff683c7
ci(release): run CI on release branches, and stage the STT binaries i…
EtienneLescot Jul 27, 2026
18a9696
ci: make the test typecheck a ratchet instead of a permanent red X
EtienneLescot Jul 27, 2026
51754cc
fix(topbar): hide left side panel toggle in Media and Rec modes
EtienneLescot Jul 27, 2026
c28981b
feat(titlebar): seamless window titlebar on Windows, macOS and Linux
EtienneLescot Jul 27, 2026
5b48a33
build(win): fail the pack on a stale compositor addon, and split poc-…
EtienneLescot Jul 27, 2026
4bae44e
docs(website): rewrite the feature docs against the v4 shell
EtienneLescot Jul 27, 2026
f6ad8a7
docs(roadmap): reconcile the roadmap with what actually shipped
EtienneLescot Jul 27, 2026
6d989f2
docs(architecture): repoint the LLM provider doc at the transport tha…
EtienneLescot Jul 27, 2026
96766b8
chore(i18n): drop two dead string blocks and the phantom Add Blur sho…
EtienneLescot Jul 27, 2026
7596cd8
docs(perf): lead with the D3D11 result instead of burying it under th…
EtienneLescot Jul 27, 2026
264251f
docs(perf): record an admissible C0..C8 run, and the cursor fixture's…
EtienneLescot Jul 27, 2026
23de945
fix(i18n): translate the captions pane in the 11 locales that fell ba…
EtienneLescot Jul 27, 2026
8f009c4
feat(chat): add welcome view when no LM provider is connected
EtienneLescot Jul 27, 2026
2cf98a0
fix(chat): show welcome when active provider is selected but disconne…
EtienneLescot Jul 27, 2026
25297d9
fix(chat): keep the welcome view honest about loading, history and de…
EtienneLescot Jul 27, 2026
a183712
fix(timeline): let the chat confirm Auto-enhance, instead of the time…
EtienneLescot Jul 27, 2026
4ef7abc
refactor(chat): trim the welcome card to what it actually needs
EtienneLescot Jul 27, 2026
1d28c72
feat(export): pick the video encoder from the host's hardware, with a…
EtienneLescot Jul 27, 2026
1b9f66a
fix(export): make the encoder choice forceable, and the fallback MP4 …
EtienneLescot Jul 27, 2026
f1523d5
ci(release): restrict the 1.8.0 build to Windows
EtienneLescot Jul 27, 2026
f6e90b3
chore(release): bump to 1.8.0-rc.1 [skip ci]
github-actions[bot] Jul 27, 2026
bce2477
fix(build): vendor the ffmpeg SDK so CI can build the compositor addon
EtienneLescot Jul 27, 2026
46e0cb8
chore(release): bump to 1.8.0-rc.2 [skip ci]
EtienneLescot Jul 27, 2026
60f53c3
chore(release): bump to 1.8.0-rc.3 [skip ci]
github-actions[bot] Jul 27, 2026
9e586bd
fix(stt): stop linking OpenSSL, and load-check the staged binary
EtienneLescot Jul 27, 2026
9bba0f5
feat(compositor): fail legibly when D3D11 init fails, instead of fall…
EtienneLescot Jul 27, 2026
c305e35
docs(compositor): correct the WGC rationale -- capture is not mandatory
EtienneLescot Jul 27, 2026
d4db3a0
feat(compositor): add a CPU backend -- WARP render + software decode,…
EtienneLescot Jul 27, 2026
8a0b119
feat(compositor): select the CPU backend automatically, and tell the …
EtienneLescot Jul 27, 2026
2535d3e
chore(release): bump to 1.8.0-rc.4 [skip ci]
github-actions[bot] Jul 27, 2026
13e1a31
feat(compositor): let the CPU backend reach the export encoder
EtienneLescot Jul 27, 2026
81e68ee
Merge branch 'release/v1.8.0' into feat/d3d-warp-fallback
EtienneLescot Jul 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
31 changes: 31 additions & 0 deletions .claude/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"version": "0.0.1",
"configurations": [
{
"name": "vite-dev",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev", "--", "--port", "5199", "--strictPort"],
"port": 5199,
"env": { "NO_ELECTRON": "1" }
},
{
"name": "desktop-dev",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev", "--", "--port", "5201", "--strictPort"],
"port": 5201,
"env": { "NO_ELECTRON": "1" }
},
{
"name": "v4preview",
"runtimeExecutable": "node",
"runtimeArgs": ["node_modules/vite/bin/vite.js", "--config", "vite.v4preview.config.ts"],
"port": 5207
},
{
"name": "docs",
"runtimeExecutable": "npm",
"runtimeArgs": ["--prefix", "website", "run", "serve", "--", "--port", "3111"],
"port": 3111
}
]
}
202 changes: 202 additions & 0 deletions .github/workflows/build-whisper-stt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
name: Build whisper-stt binaries

# Builds the whisper.cpp-based `whisper-stt-server` helper for each desktop
# platform and uploads the binary + ggml backend sidecars as GitHub artifacts
# so `build.yml` can bundle them into installers.
#
# Triggered:
# * manually via workflow_dispatch (release-blocking binary refresh)
# * automatically when the helper, build script, or this workflow changes
#
# ponytail: one binary per platform is enough because whisper.cpp selects the
# right backend at runtime (Metal on Apple Silicon, Vulkan on Windows/Linux,
# CPU fallback when no GPU/driver is available). A CUDA variant is supported
# by the build script but is not built by default; Vulkan already accelerates
# NVIDIA cards.

on:
workflow_dispatch:
inputs:
enable_cuda:
description: "Also build a CUDA variant when the host has an nvcc toolchain"
required: false
default: "false"
type: choice
options:
- "true"
- "false"
push:
paths:
- "scripts/build-whisper-stt.sh"
- "electron/native/whisper-stt/**"
- ".github/workflows/build-whisper-stt.yml"

permissions:
contents: read

jobs:
build:
name: ${{ matrix.label }}
strategy:
fail-fast: false
matrix:
include:
- os: macos-latest
arch: arm64
# Matches `os_arch_tag()` in scripts/build-whisper-stt.sh — this is
# the directory name the build script actually stages into
# (electron/native/bin/<tag>/), NOT `${{ matrix.os }}-${{ matrix.arch }}`.
tag: darwin-arm64
label: macOS arm64 (Metal)
vulkan: false
- os: macos-15-intel
arch: x64
tag: darwin-x64
label: macOS x64 (CPU)
vulkan: false
- os: ubuntu-latest
arch: x64
tag: linux-x64
label: Linux x64 (Vulkan + CPU fallback)
vulkan: true
- os: windows-latest
arch: x64
tag: win32-x64
label: Windows x64 (Vulkan + CPU fallback)
vulkan: true
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: ./.github/actions/setup

- name: Install Ninja (Linux)
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y ninja-build build-essential

- name: Install Ninja (macOS)
if: startsWith(matrix.os, 'macos')
run: brew install ninja

- name: Setup MSVC (Windows)
if: matrix.os == 'windows-latest'
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64

- name: Install Vulkan SDK
if: matrix.vulkan
# ponytail: humbletim/setup-vulkan-sdk builds Glslang from source via
# CMake ExternalProject, which fails ("ENABLE_OPT set but SPIR-V
# tools not found") because Glslang's build needs a sibling
# SPIRV-Tools checkout it doesn't fetch on its own — reproduced on
# both the Linux and Windows legs. jakoch/install-vulkan-sdk-action
# downloads LunarG's official prebuilt SDK (glslc included, no
# compilation), which is both more reliable and much faster.
uses: jakoch/install-vulkan-sdk-action@v1
with:
vulkan_version: 1.4.304.1
install_runtime: false
cache: true

- name: Put glslc on PATH
if: matrix.vulkan
shell: bash
# Belt-and-braces: the action exports VULKAN_SDK but its own PATH
# handling isn't documented in enough detail to rely on for a tool
# (glslc) the ggml Vulkan backend's CMake configure step needs to find.
run: |
set -euo pipefail
for cand in "${VULKAN_SDK}/Bin" "${VULKAN_SDK}/bin"; do
if [[ -d "${cand}" ]]; then
echo "${cand}" >> "$GITHUB_PATH"
fi
done

- name: Install SPIRV-Headers (Windows only)
if: matrix.os == 'windows-latest'
shell: bash
# ponytail: ggml-vulkan's CMakeLists does
# `find_package(SPIRV-Headers CONFIG REQUIRED)`. The Linux LunarG SDK
# tarball bundles that CMake config alongside the SDK, so the Linux
# leg resolves it for free; the Windows installer .exe (as fetched by
# jakoch/install-vulkan-sdk-action) does not ship it at all, so
# find_package fails with "Could not find a package configuration
# file". vcpkg (preinstalled on GitHub's windows-latest image) ships
# a spirv-headers port that provides the missing config; point
# CMAKE_PREFIX_PATH at its install dir so ggml's own
# `if (DEFINED ENV{VULKAN_SDK}) list(APPEND CMAKE_PREFIX_PATH ...)`
# logic has a second, working prefix to fall back to.
run: |
set -euo pipefail
VCPKG_ROOT_DIR="$(dirname "$(command -v vcpkg)")"
"${VCPKG_ROOT_DIR}/vcpkg" install spirv-headers:x64-windows
echo "CMAKE_PREFIX_PATH=${VCPKG_ROOT_DIR}/installed/x64-windows" >> "$GITHUB_ENV"

- name: Cache whisper.cpp build tree
uses: actions/cache@v4
with:
# Matches scripts/build-whisper-stt.sh's own BUILD_ROOT default for
# each OS (short `C:/wstbuild` on Windows to dodge the vulkan-shaders-gen
# MAX_PATH issue; `.cache/whisper-stt-build` elsewhere) — cache the
# FetchContent checkout + object files directly, no env override needed.
path: ${{ runner.os == 'Windows' && 'C:/wstbuild' || '.cache/whisper-stt-build' }}
# Keyed on the pinned WHISPER_REF/backend flags in CMakeLists.txt so a
# bump there invalidates the cache instead of silently reusing a stale
# FetchContent checkout; falls back to the newest cache for the same
# platform + runner image on a miss so incremental compilation still
# helps. The runner image version ($ImageOS/$ImageVersion) is part of
# the key AND the restore-keys prefix because CMake bakes absolute
# toolchain paths (e.g. the Xcode SDK's libz.tbd) into the cached build
# tree — when GitHub rolls the image's Xcode/SDK, those paths vanish and
# a restored tree fails with "No rule to make target …libz.tbd". Scoping
# the cache to the image version auto-busts it on every toolchain roll.
key: whisper-stt-build-${{ matrix.tag }}-${{ env.ImageOS }}-${{ env.ImageVersion }}-${{ hashFiles('electron/native/whisper-stt/CMakeLists.txt') }}
restore-keys: |
whisper-stt-build-${{ matrix.tag }}-${{ env.ImageOS }}-${{ env.ImageVersion }}-

- name: Run whisper-stt build script
env:
ENABLE_CUDA: ${{ github.event.inputs.enable_cuda || 'false' }}
run: bash scripts/build-whisper-stt.sh

- name: Stage binaries for upload
shell: bash
run: |
set -euo pipefail
BAG="whisper-stt-${{ matrix.tag }}"
mkdir -p "$BAG"
# Copy the whole per-platform directory: the helper executable plus
# every ggml backend sidecar/library it needs at runtime.
cp -v "electron/native/bin/${{ matrix.tag }}"/* "$BAG/"
tar -czf "${BAG}.tar.gz" "$BAG"
echo "Staged ${BAG}.tar.gz"

- name: Upload binaries
uses: actions/upload-artifact@v4
with:
name: whisper-stt-${{ matrix.tag }}
path: whisper-stt-${{ matrix.tag }}.tar.gz
if-no-files-found: error
# 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()
# Explicit shell: the bash `{ ... } >> file` grouping syntax below is
# not valid PowerShell, which is the default `run:` shell on Windows
# runners — this step silently failed on Windows without this.
shell: bash
run: |
{
echo "## whisper-stt build"
echo ""
echo "- Matrix: \`${{ matrix.label }}\`"
echo "- Result: ${{ job.status }}"
} >> "$GITHUB_STEP_SUMMARY"
58 changes: 36 additions & 22 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,16 @@ jobs:
- name: Setup Node.js
uses: ./.github/actions/setup

- name: Cache caption assets
uses: actions/cache@v4
with:
path: caption-assets
key: caption-assets-${{ runner.os }}-${{ hashFiles('scripts/fetch-caption-model.mjs') }}
# 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 @@ -65,11 +70,11 @@ jobs:
- name: Setup Node.js
uses: ./.github/actions/setup

- name: Cache caption assets
uses: actions/cache@v4
with:
path: caption-assets
key: caption-assets-${{ runner.os }}-${{ hashFiles('scripts/fetch-caption-model.mjs') }}
- 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 All @@ -84,6 +89,9 @@ jobs:

build-macos:
name: macOS ${{ matrix.arch }} DMG
# RELEASE-BRANCH-ONLY: 1.8.0 ships Windows-only. Do NOT let this `if: false`
# reach main when promoting, or every later release becomes Windows-only too.
if: false
runs-on: macos-latest
strategy:
fail-fast: false
Expand All @@ -106,11 +114,11 @@ jobs:
env:
npm_config_build_from_source: "false"

- name: Cache caption assets
uses: actions/cache@v4
with:
path: caption-assets
key: caption-assets-${{ runner.os }}-${{ hashFiles('scripts/fetch-caption-model.mjs') }}
- 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
Expand Down Expand Up @@ -258,6 +266,8 @@ jobs:

build-linux:
name: Linux packages
# RELEASE-BRANCH-ONLY: see the note on build-macos above.
if: false
runs-on: ubuntu-latest
steps:
- name: Checkout code
Expand All @@ -269,11 +279,11 @@ jobs:
- name: Install pacman build dependencies
run: sudo apt-get update && sudo apt-get install -y libarchive-tools

- name: Cache caption assets
uses: actions/cache@v4
with:
path: caption-assets
key: caption-assets-${{ runner.os }}-${{ hashFiles('scripts/fetch-caption-model.mjs') }}
- 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 All @@ -293,10 +303,11 @@ jobs:
publish-release:
name: Publish GitHub release
runs-on: ubuntu-latest
# RELEASE-BRANCH-ONLY: build-macos / build-linux are disabled for this
# Windows-only release. A skipped job in `needs` skips this one too, so they
# must come out of the list, not just be gated. Restore all three on main.
needs:
- build-windows
- build-macos
- build-linux
if: ${{ (github.event_name == 'push' && github.ref_type == 'tag') || (github.event_name == 'workflow_dispatch' && github.event.inputs.release_tag != '') }}
steps:
- name: Checkout code
Expand Down Expand Up @@ -378,6 +389,9 @@ jobs:
path: artifacts/mac-x64

- name: Download Linux packages
# RELEASE-BRANCH-ONLY: tolerate the missing artifact from the disabled
# Linux job (the macOS downloads below already do). Drop with the rest.
continue-on-error: true
uses: actions/download-artifact@v4
with:
name: openscreen-linux
Expand Down
Loading
Loading