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
18 changes: 11 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,17 +120,21 @@ my-capture/
└── profiling.json
```

Video remains the default evidence format. Capture stages exact-timestamp,
lossless frames during the session, asks a separately provisioned FFmpeg
executable to encode them, verifies the resulting MP4, and promotes it
atomically. Capture never downloads, bundles, or links FFmpeg/PyAV. Set
Video remains the default evidence format. Capture streams in-memory RGB frames
directly to a separately provisioned FFmpeg executable while recording. Missing
integer PTS slots reuse the preceding frame, so encoding is deterministic and
independent of scheduler or queue latency. A compact MP4 metadata box retains
the logical capture-frame timestamps used by nearest-frame extraction. Capture
then verifies and atomically promotes the MP4; no intermediate screenshot
sequence is written. Capture never downloads, bundles, or links FFmpeg/PyAV. Set
`OPENADAPT_FFMPEG_PATH`, pass `Recorder(ffmpeg_path=...)`, use Desktop's
user-data `ffmpeg.json` provision manifest, or place `ffmpeg` and `ffprobe` on
`PATH`. Recording performs a real encode-and-decode probe and refuses before
input listeners start if the selected executable, codec, or PNG verification
path is unavailable. A minimal managed runtime must provide the selected video
encoder, MP4 demuxing/muxing, PNG decoding/encoding, the `image2pipe` muxer, and
the `select` video filter; Desktop provisions and probes that exact closure.
path is unavailable. A minimal managed runtime must provide raw-video input
through a pipe, the selected video encoder, MP4 demuxing/muxing, PNG
decoding/encoding, the `image2pipe` muxer, and the `select` video filter;
Desktop provisions and probes that exact closure.

## Window-scoped recording

Expand Down
27 changes: 16 additions & 11 deletions docs/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,16 +167,20 @@ class Capture:
### Video Encoding

Capture keeps its video-first behavior without importing PyAV. During a
recording it stages numeric-name lossless PNG frames plus exact integer PTS.
Finalization writes a safe `ffconcat` manifest, invokes an externally
provisioned FFmpeg argument vector with bounded execution, verifies the output
by decoding a PNG frame, and atomically promotes it. Successful finalization
deletes the transient stage; failure retains it for recovery and never reports
an MP4 as complete. A sibling or explicitly configured `ffprobe` preserves
nearest-frame extraction and metadata inspection without linking codec
libraries into Capture. The real preflight exercises the selected encoder,
MP4, PNG through `image2pipe`, and the `select` filter before any input listener
starts.
recording it streams in-memory RGB frames directly into an externally
provisioned FFmpeg process. Missing integer PTS slots reuse the preceding RGB
frame, producing a deterministic constant-rate stream without depending on
wall-clock arrival time. A compact ignored MP4 UUID box maps logical capture
timestamps to their decoded-frame indexes, preserving the existing
nearest-frame contract without an image sidecar. Finalization closes the
bounded process, appends that metadata, verifies the output by decoding a PNG
frame, and atomically promotes it. No intermediate screenshot sequence or
`ffconcat` manifest is written. Failure retains only an explicitly incomplete
partial MP4 and never reports it as complete. A sibling or explicitly
configured `ffprobe` supports legacy nearest-frame extraction and metadata
inspection without linking codec libraries into Capture. The real preflight
exercises raw-video input through a pipe, the selected encoder, MP4, PNG
through `image2pipe`, and the `select` filter before any input listener starts.

```python
codec = None # Probe platform encoders, then portable mpeg4 fallback
Expand Down Expand Up @@ -209,7 +213,8 @@ capture_abc123/
**Decision:** Default to video mode.

- More storage-efficient than permanent individual screenshots
- Exact timestamp alignment is preserved by staged-frame PTS and VFR durations
- Exact timestamp alignment is preserved by deterministic PTS-gap filling and
logical timestamps embedded in the MP4
- Screenshots can be extracted from video when needed
- Individual screenshots remain optional for debugging frame alignment

Expand Down
2 changes: 1 addition & 1 deletion openadapt_capture/recorder.py
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,7 @@ def write_video_event(
recording_timestamp: The timestamp of the recording.
event: A screen event to be written.
perf_q: A queue for collecting performance data.
video_container: The external-encoder staging container.
video_container: The direct external-encoder stream.
video_stream: The configured external-encoder stream.
video_start_timestamp (float): The base timestamp from which the video
recording started.
Expand Down
Loading
Loading