security-union / security-union/remote-shutter
Video recording failures hang both devices instead of erroring
Nobody has claimed this yet.
- Dominant language
- Swift
- Stars
- 19
- Forks
- 3
- Avg merge
- 28m
- Merged PRs (30d)
- 6
Description
Found while fixing the Mac-as-camera recording hang (PR #157). That bug's root cause is fixed, but the three things that turned a settings rejection into a permanent two-device freeze are all still present. The next stop-side failure — from any cause — will hang exactly the same way.
Three silent-failure amplifiers, in the order they bite:
1. configureAudioForRecording reports success when it failed
RemoteCam/CaptureEngine.swift:213-219
if captureSession.canAddInput(audioDeviceInput) {
captureSession.addInput(audioDeviceInput)
} else {
print("Could not add audio device input to the session") // ← prints, then falls through
}
if captureSession.canAddOutput(audioDataOutput) { ... } // ← no else at all
...
return true // ← unconditional
RecordingPipeline.swift:107's guard self.configureAudio(...) therefore passes, and the deliberate MicrophoneAccessDenied bail-out at :107-114 never fires. Fix: return false when the input or the output can't be added. That alone routes it to the already-wired clean failure (error ack + "Unable to record audio" alert).
2. stopRecording silently drops the whole protocol
RemoteCam/RecordingPipeline.swift:147
if self.recordingWillBeStopped || !self.isRecordingStorage {
return // no finishWriting, no StopRecordingVideoResp, no error, no log
}
The guard conflates two different states. Split them:
recordingWillBeStopped→ a stop is in flight, ignore (correct today).!isRecordingStoragewithrecordingWillBeStarted == true→ the start never completed. Tear down the pending writer, clearrecordingWillBeStarted(today it staystrueforever, poisoning every futurestartRecordingvia the guard at:97), and emitStopRecordingVideoResp(error:)so the monitor unblocks.
Also guard the assetWriter? optional-chain at :157: a nil writer means the completion never runs and recordingWillBeStopped stays true forever — the same permanent poison. Never call finishWriting on a .unknown-status writer (it throws).
3. .monitorWaitingForVideo is the only monitor wait state with no timeout
RemoteCam/SessionCoordinator.swift:1540
Every other wait state arms a scheduleTimeout (:1187, :1200, :1209, :1229, :1258, :1507), and the watch path recovers from the identical underlying no-op via :1739/:1753. The multipeer path is the outlier.
⚠️ A flat 10s would break large transfers, which legitimately take minutes. Needs to be transfer-aware: arm until the transfer starts, then rely on progress.
Why it matters
Any one of these alone is survivable. Together they convert any recording-side failure into both devices hanging forever with no error and no log. Worth fixing as one PR.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the named paths in RemoteCam/CaptureEngine.swift, RecordingPipeline.swift, and SessionCoordinator.swift, especially the cited line ranges and the existing timeout and watch recovery paths. Trace the recording start/stop protocol and failure acknowledgements before changing behavior. Done means every cited failure unblocks both devices, clears poisoned recording state, reports an error, and uses a transfer-aware timeout without interrupting large transfers.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- ios, swift
- Domain
- audio-video-rtc, mobile-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 63/100