- modules/Screen_Record: a region of one screen to H.264 in a fragmented MP4. A capture thread
duplicates the screen (DuplicateOutput1, else DuplicateOutput) on a D3D11 device of its own on
the screen's adapter, copies the region on the GPU, reads it back through three staging
textures and draws the cursor in (colour, masked colour and monochrome shapes). An encoder
thread feeds FFmpeg: h264_nvenc, else h264_amf, h264_qsv, h264_mf, libx264, each tried in turn;
BGRA straight to NVENC, swscale to NV12 or YUV 4:2:0 (BT.709) for the rest. A frame is sent
when the screen or cursor changed and its turn on an fps schedule is due, with a repeat each
second of an unchanged screen; the encoder falling 8 frames behind drops the oldest. A lost
duplication (mode change, secure desktop) is made again and recording goes on. record_start
says fall_back when duplication cannot run (unsupported, too many, rotated screen). Regions
under 240 x 180 are refused, then sizes are rounded down to even; a process whose view of the
desktop is scaled is refused.
- tools/record_probe.jai (jai first.jai - record_probe): lists the screens, records a screen or
region and reports source, encoder, frames captured, sent, written and dropped, time per stage
and file size; -legacy, -cuda, -exclude-test, -animate, -snapshot DIR, -check FILE.
- On the RTX 5080 laptop: 60 s of 4K at 30 fps, 1802 frames, none dropped, 18 MB a minute; every
change kept at 60 fps; plain DuplicateOutput works when DPI aware; a CUDA context changes
nothing; WDA_EXCLUDEFROMCAPTURE is respected; QSV, Media Foundation and libx264 keep up too;
a recording killed mid-way still plays. The two-GPU failure was not reproduced: the screens are
on the NVIDIA GPU in this mode. The plan records the results.
- capture_region, a new [global_hotkeys] action, on PrintScreen by default (Windows only; none on
macOS). Existing settings files get the line appended on the next launch. When the key cannot be
registered, the log names Snagit and Windows' "Print screen opens screen capture" setting.
- app/screen_capture_win32.jai: every screen copied the moment the key fires (BitBlt with
CAPTUREBLT over the virtual desktop), shown darkened in a topmost GDI window in a modal loop of its
own, so it works with mcap hidden in the tray. Dragging shows the region bright and outlined; a
magnifier shows the pixels under the cursor with its position or the selection's size; arrow keys
move a pixel (ten with Shift). A click or Enter takes the whole screen under the cursor; Escape,
a right click or losing the focus cancels. Only the parts that change are redrawn.
- app/screen_capture.jai: the region goes on the clipboard (CF_DIB) at once, then a thread writes it
into the library's "Screen Captures" folder as a PNG .mcap: metadata.json with the window under
the region's middle (its title as WindowName, its program's description as AppName) and
capture.json (where on the desktop, the program's path, the hash). mcap then comes to the front
showing it, and OCR, labels and segmentation read it as they read an import.
- A "screen capture" group in the import tests: the file written, its pixels, preview and Capture
Text read back. README and the format's README describe it.
- The Capture window draws a segmented image's segments over it: each class in its colour, a shade
of it for each instance, edges darker; under the OCR boxes, at any fit and zoom. A viewer worker
reads the segs and mask chunks (never the images); the main thread makes the texture from the
mask when the capture, the opacity or the classes hidden change.
- Above the image: Segments on or off, the opacity, and a legend of the classes (largest first,
with counts): untick one to hide it, right click it to search has: for it. Hovering the image
shows the segment's class, score and share of the image.
- Colours: a class's own is a hue from its name's hash. Its legend swatch is a colour picker
(ImGui ColorEdit3) to choose another, kept in %APPDATA%\mcap\segment-colours.config for every
image and library; right click it to go back to its own.
- Tests: the overlay's pixels (shades, edges, hidden classes, opacity), reading a file's segments
for it, and chosen colours.
- This completes segmentation-plan.html's six phases.
- has: searches what segmentation found, by the whole class name: has:dog, has:"dining table"
(has:table is a table, not a dining table). Plain words do not match segments.
- The catalog keeps each capture's segments (class, score, area) and its classes between newlines,
so a has: term is one contains per capture.
- Stats: "What is in the images", how many of the segmented images hold each class, each one a
has: search; shown even when nothing has been read by OCR. -stats logs it.
- Tests: has: (whole names, quoted names, case, combinations, plain words not matching).
- .library-folders in the library (src/app/library_folders.jai): each library folder's options,
starting with segment: true. Every folder starts off; unknown keys are kept when it is rewritten.
- The Segmentation window (Segments, above the grid): each folder's Segment checkbox, how many of
its images are segmented, and Erase per folder; a button to segment the folders set to segment.
- The segmentation scan (src/app/segment_ui.jai) runs on the OCR thread as its own task, with the
OCR scan's progress, pause and cancel: images only (never videos), not yet segmented, in folders
set to segment. The engine loads with the first scan (2.4 GB of GPU memory). Each image's segs and
mask are stored in one rewrite and its catalog entry loaded again.
- Importing into a folder set to segment segments the new images; the Import window's checkbox is
the folder's setting.
- -segment segments and exits; -erase segments, and -erase all now includes segments.
- The catalog reads each capture's segs (class list hash, segment count). The exit overlay names the
segmentation scan and model. segment_mcap_chunks moved into modules/Segment, shared with
segment-probe. The quoting helpers of Capture_File's text formats are public.
- Tests: .library-folders read and written back (quoted names, unknown keys, versions).
- Import brings in videos (MP4, MOV, MKV, WebM, AVI, WMV, MPEG, MTS/M2TS, FLV) on Windows, read with
FFmpeg: the file as it was in the original, a frame a tenth of the way in (at most 3 s), turned
the right way up, as the rendered image (what the grid, Capture window, OCR and labels see), and
import.json with Duration, FrameRate, VideoCodec, Rotation, PosterTime, Audio, and the camera,
date and location from the container. Elsewhere videos are skipped as "video (Windows only)".
- .mcap version 4: the original's size is a u64, so a video can be any size. Versions 1-3 still read.
mcap_read_without_original and mcap_write_streamed read and rewrite a file with its original left
on disk; mcap_store, mcap_erase, the import index and the import itself never hold a video in memory.
- Animated GIFs: Frames and Duration in import.json (gif_info).
- Grid: a play mark and duration on video thumbnails, GIF on animations. Capture window: what the
video is, and Play in the default player (written out to %TEMP%\mcap).
- modules/ffmpeg: FFmpeg 6.0 bindings and the five DLLs used (avformat, avcodec, avutil, swscale,
swresample), copied beside the executable by the build.
swscale converts into a buffer of its own allocator with padded rows: an exact-sized one let
its SIMD write past the end, crashing on frames of odd widths (1916, 1106 ...).
- image-probe shows videos and GIF frame counts; ocr-bench reads a video's frame.
- Tests: new video formats, display-matrix rotation, ISO 6709, video dates, GIF frames, and v4
serialize/parse, v3 compatibility, streamed writes, store/erase and extraction.
SnagitConverter's copy of Capture_File needs syncing to read version 4 files.
- Import window (and -import SOURCE DEST): every image under a folder (PNG, JPEG, HEIC, AVIF, WebP,
GIF, BMP, TIFF, camera RAW) becomes an .mcap holding the file as it was, a preview turned by its
EXIF orientation, and metadata.json and import.json Capture Text (date from EXIF, the file name or
its time; file name as title; camera as app). .snagx files become the same .mcap SnagitConverter
makes. Duplicates across the whole library are skipped by a hash index (.import-index); videos
and sidecars are skipped; source files are only read.
- modules/Image_Decode: stb_image, then WIC for everything else; EXIF; orientation; previews.
tools/image_probe.jai shows what it reads.
- modules/Snagx (and modules/jaison), copied from SnagitConverter.
- The library is a folder of folders: recursive scan, a folder filter, and a folder: search prefix.
- OCR, the viewer and ocr-bench decode any image format, turned the right way up.
- Rename D:\SnagitIndex to D:\McapIndex.