8000 Tags · kladak/openwhispr · GitHub
[go: up one dir, main page]

Skip to content

Tags

Tags

v1.10.3

Toggle v1.10.3's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
chore(release): prepare 1.10.3 (OpenWhispr#2597)

* chore(release): prepare 1.10.3

Bump the app version to 1.10.3 and move the Unreleased changelog entries into a dated 1.10.3 section covering everything merged since 1.10.2: agent connectors (email, Gmail, Slack, Linear, GitHub), note templates and actions with the docked note chat, tables in the note editor, idle resource release, friendly provider errors, Orukeet streaming for OpenWhispr Cloud, and transcription, meeting and platform fixes.

* ci(release): write the Gmail OAuth client into the packaged .env

The GMAIL_CLIENT_ID/GMAIL_CLIENT_SECRET repository secrets were never written to the release build's .env, so Gmail send fell back to the calendar's Google client. Write the pair next to the calendar credentials in the Linux, Windows and macOS jobs.

* docs(changelog): tighten the 1.10.3 summary and cover OpenWhispr#2598

windows-system-audio-helper-v1.2.0

Toggle windows-system-audio-helper-v1.2.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix(meetings): keep the Windows silent-capture check armed for the wh…

…ole call (OpenWhispr#2233)

* fix(meetings): keep the Windows silent-capture check armed for the whole call

Windows hides Microsoft Teams call audio from WASAPI process loopback: the
helper receives digital silence for it no matter which process it targets or
which format it asks for, while the same audio is plainly present on the render
endpoint. The capture_silent watchdog added in OpenWhispr#1935 is the way out of that, but
it disarmed permanently on the first audible sample from any application, so a
notification sound, a browser tab or Teams' own join chime left the rest of the
meeting recorded without the other participants and without a warning.

The helper now compares its own capture against the render endpoints once a
second for the whole session, resetting the confirmation count on any captured
audio, and main no longer refuses the handover once some audio has been heard.

Fixes OpenWhispr#1265

* fix(meetings): review follow-ups for the Windows silent-capture handover

- File the changelog entry under Meetings, and stop claiming the check
  survives audio that plays continuously alongside the meeting: the streak
  resets on any captured second, so only a gap of five seconds trips it.
- Drop the watchdog's restart hook when the renderer takes over, so it can
  never respawn the helper behind a session the renderer already owns.
- Surface a takeover failure to the user. The one-shot silence notice is
  suppressed once a call has been audible, so a late failure was silent.

* fix(meetings): ship the rebuilt helper, and report a failed takeover properly

- Bump the helper workflow's default version to 1.2.0. The push trigger
  publishes the default tag, and the download script picks the newest
  published release with the prefix, so a rebuild published as 1.0.0 would
  have lost to the existing 1.1.0 and the fix would never have shipped.
- Report a failed renderer takeover as a translated system-audio interruption
  instead of a raw English string, and tell auto-end the system channel is
  gone, so a quiet microphone cannot end the recording behind it.
- Detach the watchdog's restart hook before stopping the helper, not after.
- Trim the wiring pins the behavioral test now covers, and soften two doc
  claims: a generic "gone quiet" notice does arrive three minutes later, and
  the Teams finding is measured across configurations, not every machine.

* fix(review): iteration 1 — 4 issues (takeover-failure guards)

* fix(review): iteration 2 — 1 issue (takeover attach failure handling)

* fix(meetings): keep the Windows helper until renderer loopback proves it hears more

capture_silent can fire while the helper is capturing the call fine, for
example when a stream hidden from process loopback plays through a lull.
Stopping the helper then dropped a working capture for the rest of the
meeting, and renderer loopback only hears the default output device.

Renderer loopback now starts beside the helper and takes the system
channel only after hearing audio the helper misses for a second
(meetingSystemAudioHandover.js). Until then its chunks are dropped; after
it, the helper's are, and the helper is stopped.

A takeover whose capture graph fails to build now releases the loopback
stream and its AudioContext instead of holding them until the recording
stops. Also trims comments and updates the docs for the new log lines.

---------

Co-authored-by: boseq <307062491+boseq@users.noreply.github.com>
Co-authored-by: Chadpiha <chadpiha23@gmail.com>

v1.10.2

Toggle v1.10.2's commit message
1.10.2

v1.10.1

Toggle v1.10.1's commit message
1.10.1

v1.10.0

Toggle v1.10.0's commit message
1.10.0

windows-system-audio-helper-v1.1.0

Toggle windows-system-audio-helper-v1.1.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix(meetings): fall back to renderer loopback when WASAPI capture is …

…silent (OpenWhispr#1935)

* fix(meetings): fall back to renderer loopback when WASAPI capture is silent

The Windows helper's probe only proves the OS exposes VAD\Process_Loopback
and accepts our format; it never starts capture or reads a frame. On some
machines activation then succeeds and every delivered sample is zero, and
because strategy selection reads the probe verdict and start() resolves on
the helper's {"type":"start"} event, nothing downstream ever reconsiders it.
The silence filler keeps the timeline aligned with the wall clock, so a dead
capture emits a well-formed, correctly paced stream of nothing and the
Chromium fallback stays unreachable for the whole session.

Silence on its own is ambiguous — an idle machine looks identical — so the
helper now only calls its capture broken while a render endpoint is metering
real output, confirmed over five consecutive one-second checks and disarmed
for good the moment any real audio arrives. It reports that once as a
capture_silent warning on the existing stderr channel.

Main treats that warning as proof the native path cannot work, stops the
helper, and hands the live session to Chromium loopback; the renderer builds
the capture graph mid-call through the same code the initial start uses. The
45s silence toast stays armed as the backstop for when the fallback fails too.

Fixes OpenWhispr#1891

* docs(changelog): note the silent Windows system-audio fallback

v1.9.2

Toggle v1.9.2's commit message
OpenWhispr 1.9.2

v1.9.1

Toggle v1.9.1's commit message
OpenWhispr 1.9.1

v1.9.0

Toggle v1.9.0's commit message
OpenWhispr 1.9.0

windows-mic-listener-v1.1.0

Toggle windows-mic-listener-v1.1.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat(meetings): Auto-end forgotten meeting recordings (OpenWhispr#1494)

* feat(meetings): Auto-end forgotten meeting recordings

Track reliable external microphone activity and show a protected
60-second countdown after meeting activity ends. Preserve recording
during reconnects, unreliable detection, and Keep recording actions.

* fix(meetings): Harden auto-end against stale binaries and races

* fix(meetings): Keep auto-end alive through coverage loss and CI races

Code review found that every major failure path killed the feature
silently. All fixes preserve the fail-safe property: degradation can
only delay or disable auto-end, never stop a live recording.

- Windows: a single unattributable session or flaky endpoint made the
  helper exit, with no respawn and a polling fallback that also lost
  meeting prompts. It now announces CAPABILITY AGGREGATE once and keeps
  emitting best-effort events; unattributable sessions refcount under
  pid 0, which the JS side can never exclude as its own, so they count
  as external capture and park the countdown.
- macOS: a process vanishing between enumeration and its property query
  permanently downgraded PID mode to aggregate, and the 5s heartbeat
  re-rolled that race for the whole session. Skip the vanished object
  and let the next reconcile retry it instead.
- Linux: one pactl source-output without application.process.id
  (echo-cancel, loopbacks) dropped PID reliability entirely. Skip
  module streams; client streams always carry the pid.
- CI: the notarize build raced the listener-publishing workflow and
  could cache a stale binary under a fresh source hash. The release tag
  is now pinned to MIC_LISTENER_VERSION in the C source on both ends,
  and CI downloads fail hard instead of silently falling back.
- Renderer: a rejected auto-end stop was swallowed; it is now reported
  through a required onError hook wired to the meeting logger.

* style(notes): Revert drive-by Prettier reflows

Restore ShareNoteDialog, OverviewNoteList, and useNoteDragAndDrop to
their merge-base content. The reflows were format-only, and the
ShareNoteDialog hunk conflicts with the policy-enforcement merge on
main for no benefit.

* fix(meetings): Exclude own audio helpers and persist auto-end stops

Auto-end never fired when system audio was captured: the capture
helpers (macOS audio tap, Linux portal, Windows loopback) are plain
child processes absent from app.getAppMetrics(), so the OS attributed
their capture to non-excluded pids and externalMicActive never went
false for the whole recording — verified empirically on macOS via the
mic listener reporting the tap helper's pid. Feed the helpers' live
pids into the detector's exclusion provider.

Transcript persistence was keyed to mounted views, and an auto-end
stop is the first stop that can fire while the notes view is closed:
the final tail since the last 30s flush was lost and diarization
results were dropped. Persist the final transcript in the store's stop
path after the main result arrives, move the periodic saver to the
always-mounted MeetingRecordingMount, and persist diarization results
session-scoped to the note that was recorded. NoteEditor's handler is
now display-only and gated to the recording note, so enrichment can no
longer land on whichever note happens to be open.

Toast when an auto-end request ends the live session — including when
a Keep click loses the race with the countdown — so the user learns
the recording ended instead of assuming it was kept. New
notes.meeting.autoEnded key in all 10 locales.

* feat(meetings): Confirm auto-end with audio silence and add a fallback

Mic ownership alone had two blind spots: an app that releases the mic
on mute could stop a live call while remote voices still played, and
the feature was inert wherever ownership is unreliable (older macOS,
coverage loss) or never armed (in-person meetings).

Combine the two signals in a tick-driven controller. In ownership mode
the countdown runs only while the system-audio channel is also quiet,
so remote speech defers it; the mic channel is deliberately ignored
there so room noise, typing, or talking to a colleague after the call
can't mask the end. When ownership is unreliable or no app ever held
the mic, both channels quiet for 60s prompts instead, tightened to 10s
when the last tracked meeting app exits.

Every raw meeting PCM chunk of both channels feeds a pure energy
monitor via a single hook in sendMeetingAudio, sharing the echo-leak
detector's thresholds through an alignment-safe RMS helper. Chunks are
ignored until the controller session exists, since system audio starts
streaming before the session is registered. Sleep gaps discard
accumulated silence instead of stopping on wake, and a mic hold shorter
than 30s no longer arms the mic-ignoring path on an in-person
recording.

Keep recording is now per episode with a 5-minute cooldown, the card
explains which signal fired, and Settings → Meetings gains an
"Auto-end forgotten recordings" toggle that takes effect immediately.

* fix(meetings): Make auto-end recording fail safe

* fix(meetings): Queue detections while a meeting recording session is live

The engine's user-recording flag is shared with dictation, so a dictation
that ends mid-meeting (or a cancel-hotkey press) clears it while the meeting
recording is still live. From then on a detection — most plausibly the
calendar reminder for a back-to-back meeting, which fires one minute before
its start, right inside the auto-end countdown — bypassed the queue, and its
prompt replaced the visible countdown card. The replacement path never
notifies the controller, so the countdown ran on unseen and stopped the
recording without any chance to keep it.

Gate detections on the engine's own recording session as well, which nothing
outside the recording lifecycle can reset: new detections are queued behind
it like the user-recording gate, and a post-dictation cooldown flush holds
the queue until the recording ends. This also stops the pre-existing "Take
notes?" prompt that could appear during the user's own manual recording after
a dictation.

* fix(meetings): Persist the final transcript before awaiting the main-side stop

Moving the final transcript save into the store's stop path (so auto-end and
owner-loss stops persist without the notes view mounted) also moved it after
`cleanup()` and the `meetingTranscriptionStop` round trip. The note editor
swaps from live segments to the stored transcript the moment `isRecording`
flips, so for the duration of that stop — up to a few seconds with a local
Parakeet flush — the tail since the last 30s periodic save disappeared from
the note and reappeared once the stop returned. On main the notes-view effect
wrote it in the same commit as the state flip.

Persist the captured segments before awaiting the stop; they are final once
the session is released. Only a segment-less recording still waits for
main's final transcript, as before. `persistFinalTranscriptAroundStop`
replaces `buildFinalMeetingTranscript`, whose only caller was this path.

* fix: clear meeting flag after recording session ends
0