Repository navigation
Allow local Program recording without a Zoom meeting (#1009) - #1025
Merged
Merged
Conversation
The Studio Record button (CanToggleRecording) and the control API's transport.record.set (CanSetRecording) both required Settings.IsInMeeting, so a show of webcam/screen/media sources could not record with Zoom offline. Both now go through RecordingControlPolicy, which keeps only the in-flight and outputs-closing guards. Engine on/off stays meeting-gated; Zoom-guest ISO still needs the guest in the roster and Zoom capture on. - TransportCoordinator.SetRecordingAsync re-asks RecordBlockReason of the core it just started, so an offline start against a core whose encoder did not construct is refused with the reason instead of armed. - OutputResumeAfterCoreRestart: a recording made with no meeting (CoreOnly) now resumes after a core crash; a recording whose Zoom rejoin failed is still not resumed and says so. - Show readiness text no longer says Zoom must be joined first. - Leave/rejoin: traced; nothing stops a recording. Pinned by shell (coordinator, snapshot merge) and native (stub core join/leave/rejoin) tests. The old gate did disable the Record button after a leave, so a recording running at leave could not be stopped from the Studio button until a rejoin (the API stop was still allowed); that is gone too. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…sts (#1009) - SetRecordingAsync starts the core and asks RecordBlockReason BEFORE arming the Record intent, so no production sync can carry recording=true to a core that is then refused. A core that cannot start fails the start before anything is armed. The in-try Ensure is kept for the stop path and as a no-op on a start. - Leave/rejoin tests renamed and re-commented to say what they cover: CoordinatorEngineOff_..._FakeHost (coordinator, fake host), LeaveAndRejoinSnapshots... (snapshot merge/mapping), StubCoreZoomJoinLeaveRejoin... (stub core; ZoomEngineRuntime not run). - New test: OfflineStart_StartsTheCoreBeforeArming. - core-restart-drill.md and core-on-air-policy.md: the recording resume rule from #1025 is marked PENDING OWNER RULING; the old rule is stated. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
iamfatness
marked this pull request as ready for review
October 23, 2026 12:44
This was referenced Oct 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1009. This is a draft: the installed-app checks are not done (see "Not verified").
Cause
Two predicates required
Settings.IsInMeeting:StudioViewModel.CanToggleRecording, which gates the Studio Record button.CanSetRecording, which gates the control API'stransport.record.setand the resume after a core restart.Program recording records whatever Program renders, including webcam and screen capture. The meeting term therefore blocked local recording for no reason.
Change
RecordingControlPolicy(ViewModels/Transport), and both predicates now call it. It keeps the in-flight guard and the "Stop and close" (outputs-closing) guard. It has no meeting input.CanToggleCapture(Engine on/off) stays meeting-gated.TransportCoordinator.SetRecordingAsync.EnsureMediaCoreRunningAsync) and checksMediaCoreOnAirPolicy.RecordBlockReasonbefore the Record intent is armed.recording=trueto a core that is then refused.OutputResumeAfterCoreRestart, the parameterrequiresMeetingis renamedrequiresZoomRejoin.CoreOnly) is now resumed.core-restart-drill.mdandcore-on-air-policy.mdmark it pending owner ruling and state the old rule.BuildIsoSourceTargets) and Zoom capture on (IsoCapturePreflight).Leave/rejoin finding
I checked the real leave and rejoin paths by reading them. The tests cover only the coordinator, the snapshot merge and the stub core.
What the real paths do:
SettingsViewModel.LeaveZoomAsynccallsonBeforeLeaveMeeting, which callsUnsubscribeZoomCapture(Engine off). It then calls_bridge.LeaveZoomAsync(zoom-leave). The core stays up. None of these steps touchesRecordingRequested.Recording = RecordingRequestedwhatever the meeting state.RecordingRequestedis cleared only on three things: a core-reported failure or interruption, a core restart, or a deliberate core stop.MediaCore::leaveZoomandZoomEngineRuntime::leavereset only Zoom state. Join does not touch outputs.The old gate had one effect on leave: with no meeting, the Record button was disabled. A recording still running after a leave could therefore not be stopped from the Studio button until a rejoin. A stop through the API was still allowed. Removing the meeting term removes that too.
What the tests cover, and what they do not:
CoordinatorEngineOff_DoesNotStopAnArmedRecording_FakeHost: only the Engine-off path inTransportCoordinator, against a fake host. The realUnsubscribeZoomCaptureis not run.LeaveAndRejoinSnapshotsKeepTheProgramRecordingObservedAndArmed(MediaCore): only how the shell reads a recording across leave/rejoin snapshots (ZoomCaptureSnapshotMergerplusLiveProductionSync).StubCoreZoomJoinLeaveRejoinDoesNotStopAnOfflineStartedRecording(native): the realJsonRpcServerzoom-join and zoom-leave handlers on stub modules.MediaCoretakes its stub-meeting branch, soZoomEngineRuntime::leaveandjoinare not run.I could not add a test of the real leave sequence without
StudioViewModel:UnsubscribeZoomCaptureis a private method ofStudioViewModel, which cannot be constructed in tests.SettingsViewModelcannot be constructed either:MediaCoreBridgeService, not theIMediaCoreBridgeseam.DispatcherQueue.GetForCurrentThread()at field init.%LOCALAPPDATA%\CoreVideoPro, and starts the telemetry service.SettingsViewModelfirst. That refactor is outside Local Program recording is incorrectly gated on joining a Zoom meeting #1009.Tests
COREVIDEO_STUB=ON, Release),EncoderRecordingSession.*JsonRpcServer.*New WinUI tests:
transport.record.setstarts with no meetingThe full native suite and the dev/real-adapter tier were not run.
Not verified
CoreOnlycrash-resume change. It needs owner sign-off and was not drilled against a real core crash.🤖 Generated with Claude Code