changelog
What's new.
Every release, in plain language. NVR keeps getting better — included with your license.
- v0.2.57-preview
Faster remote viewing, async clip export, and DVR signal health.
- Remote sessions now load thumbnails and recordings natively instead of re-encoding every image in the browser, which makes scrubbing and playback noticeably faster away from the office.
- Clip export runs as a background job with real progress: start a long export, close the laptop, and collect it later.
- Exports spanning a recorder restart now build correctly instead of failing; a clip that crosses a gap no longer has to be stitched together by hand.
- Downloads that were cut short by a recording gap now report the problem instead of silently returning a near-empty file.
- DVR inputs with no camera attached are flagged as NO SIGNAL, and repeated signal drops are counted so a failing cable can be identified.
- Camera tiles keep their last good image instead of being overwritten by a NO VIDEO placeholder.
- Multi-camera review is reachable from the Wall: pick a group and scrub every camera against one timeline.
- The snapshot button on playback works again.
- Scrubbing no longer jumps backwards and replays after you release the timeline.
- v0.2.56-preview
Review several cameras at once — one timeline, every camera in sync.
- New: pick a camera group in Playback and get a synced grid — drag the timeline and every camera seeks to the same instant; press play and they run in unison.
- Playback pauses cleanly at the end of recorded footage instead of stalling.
- Event queries are lighter on the wire and filter in the database, and the events browser reuses what it already fetched.
- Automatic updates now install silently in the background as designed.
- v0.2.55-preview
Faster event queries and a smarter events browser.
- Event queries no longer carry each event's raw camera payload over the wire, and type filters run in the database instead of after the fetch.
- The events browser and the timeline's event ribbon now remember what they already fetched — repeating a search or panning over covered ground is instant, with no new requests.
- v0.2.54-preview
Recent footage becomes scrubbable within seconds, without waiting for disk.
- Every recording camera now rolls small in-memory chunks continuously, so the last few minutes are scrubbable almost immediately.
- Scrub previews hand off cleanly to playback — the decoder is released before the player takes over, fixing a stall when resuming after a scrub.
- v0.2.53-preview
Faster, more accurate scrubbing — and a buffer ribbon that tells the truth.
- Dragging the scrubber no longer cancels the preview images it just asked for, so previews actually appear while you drag instead of after you stop.
- A warm scrub now paces itself by how quickly each seek finishes rather than on a fixed timer, so fast dragging stays smooth instead of lurching.
- The buffer ribbon now marks only the ranges where scrubbing is genuinely instant, instead of promising footage that still has to be fetched.
- Motion markers no longer vanish when the timeline redraws from its cache at fine zoom levels.
- Zooming and panning a busy camera's timeline stops re-fetching motion events it already has, so the timeline settles faster.
- Cameras with no recorded events no longer generate repeated failed requests while you browse the timeline.
- Recording diagnostics now report how disk space is reserved for each segment, making storage fragmentation visible before it starts costing performance.
- v0.2.52-preview
Smoother scrubbing, bounded memory, and a readable timeline at every zoom.
- Scrub back over ground you already covered and it is instant — the scrub buffer now holds 15 minutes around the cursor instead of 5.
- Playback opens at a zoom level where scrubbing plays real video instead of thumbnail previews.
- The timeline ruler now shows the time at every zoom level; tight zooms label with seconds.
- Browser memory during playback is now bounded, so long review sessions no longer stall or drop buffered footage without warning.
- A full SourceBuffer no longer tears down the player or reports itself as a codec problem — it frees the oldest footage and carries on.
- The live grid can now show up to 56 cameras per page (still 16 by default; raise it under Cameras per page).
- v0.2.51-preview
Local motion detection can now run without polling your cameras
- Local motion detection can sample the video the recorder already has in memory instead of fetching a still image from each camera every few seconds — no extra connection, no extra request, no extra disk read. Set detection.local_motion.source to ram.
- Detection sensitivity is unchanged when you switch: the new lane samples at the same interval you already configured, spread across each recording segment, rather than once per segment.
- Evidence images are stamped with the time the frame was actually captured, so timeline markers line up with the footage they point at.
- A camera whose video is too sparse to compare now switches its own detection off and says so in diagnostics, instead of silently producing nothing.
- Storage maintenance: reclaiming space from the index database now works on installations that were migrated before generation tracking existed.
- v0.2.50-preview
Detection evidence gets its own bounded store
- Detection evidence images can now live on their own drive with a real size limit. Set detection.evidence.dir and the store gets a byte cap, a free-space floor, and a share-of-disk ceiling — enforced continuously, not just written in config.
- Evidence no longer competes with recording for the same spindles, and a full evidence store can never stop the recorder: recording is untouched, and a detection is refused rather than saved as a card with no image behind it.
- Evidence you have already reviewed or kept is pinned and never evicted, so the store bounding itself cannot eat your saved set.
- Moving evidence to a dedicated drive keeps the images already recorded viewable — existing detection cards still open from where they were written.
- v0.2.49-preview
Recording storage: fewer, larger, contiguous segments and honest maintenance tools
- Reclaim footage the index lost track of: a reindex sweep could never adopt orphaned recordings on any real camera, because it required a stream to have exactly one init segment and every encoder change leaves another behind.
- Maintenance sweeps now report progress as they run instead of going silent for hours.
- New nvrd -storage-evict drains a retention backlog in one pass instead of over hours of 60s ticks.
- Segments are now reserved as one contiguous run on disk, so recordings stay in one piece on a near-full drive.
- New storage.max_used_pct keeps a dedicated recording drive below a share of its capacity, which a fixed GB floor cannot do as disks grow.
- v0.2.48-preview
Health and Settings are organized into sections instead of one endless page, and camera groups now filter Live and Wall.
- Health is split into eight sections — Overview, Reliability, Uptime, Playback, Network, Recorder host, Storage and Index — with only one on screen at a time. Each section in the list shows a marker when it needs attention, so nothing is hidden by being collapsed.
- Settings is organized the same way: Updates, Branding, Notifications, Recording, Resources, Advanced and Maintenance. The advanced editor keeps an 'unsaved' marker while you have edits pending, and settings history now sits beside the editor it loads into.
- Both pages remember which section you are on in the address bar, so a link to a specific section keeps working and a refresh returns you to it.
- Camera groups finally do something: Live and Wall have a group picker that filters the cameras on screen, defaulting to all of them. The chosen group is part of the link, so a group view can be shared or bookmarked.
- A group that is deleted or renamed while someone is viewing it falls back to showing every camera rather than an empty screen.
- v0.2.47-preview
Seeking in recorded footage is dramatically faster: it now fetches only the moment you asked for instead of the whole segment around it.
- A seek now downloads just the group of frames it needs to show you a picture, then loads the rest behind you. Previously every seek waited on up to 20x the data required, which is why scrubbing felt heavy — especially over a remote connection.
- Scrubbing back over footage you already loaded no longer re-downloads it. Only the genuinely missing part is fetched.
- v0.2.46-preview
Scrub preview quality is now yours to choose, and a failed thumbnail no longer floods the recorder with retries.
- Scrub preview tiers are configurable: playback.scrub_hq and playback.scrub_thumbnails let you turn off the full-resolution chase or the thumbnail filmstrip and scrub purely on the low-latency substream.
- A scrub thumbnail that fails to load now backs off instead of being re-requested on every cursor movement — one drag could previously issue thousands of requests against a handful of images.
- The backoff expires rather than blacklisting, so a thumbnail that failed because the link was momentarily busy comes back on its own.
- New GET /api/stats/rechttp reports request counts, bytes and latency for recorded-playback reads, split by local versus remote, so slow scrubbing can be measured instead of guessed at.
- Camera settings changes are now verified on every path that makes them, not just the Optimize button: repairing a stream ladder, the background keyframe sweep, and the command-line tools all read the setting back and report a failure if the camera quietly kept its old value.
- v0.2.45-preview
Protects recorded resolution from a camera-firmware trap, verifies every settings change against the camera, and steadies playback on mixed-aspect cameras.
- Recording quality is now protected from a camera-firmware trap: on some models a "third stream" is really the main stream under a different number, so changing its resolution silently reconfigured the main recording. Four 6MP cameras recorded at 1280x720 instead of 3200x1800 before this was caught. The NVR now detects those duplicate streams, refuses to write them, and flags them so you can remove them from your setup.
- A lower-quality stream's bitrate is now sized from the main stream instead of from its own previous value, so changing a resolution can no longer compound the bitrate upward or leave a sub-stream provisioned above the main one.
- Every camera settings change is read back and confirmed before it is reported as applied. Cameras that accept a setting and quietly ignore it no longer look successful.
- When a camera rejects a setting it now tells you why, using the camera's own explanation instead of a bare error code.
- Playback no longer jumps around while scrubbing on cameras whose sub-stream has a different shape than the main stream, which is most DVR and analog channels. The picture is letterboxed into a stable frame instead of resizing the page.
- Turning off the FAST scrub tier no longer takes the timeline ribbon and coarse scrub with it.
- Storage stats now report every configured recording drive, not just the ones present at startup.
- v0.2.44-preview
Self-healing storage index, white-label branding, a major scrubbing-quality overhaul, and faster, more reliable remote viewing.
- The recorder now survives a drive being disconnected mid-write: a corrupt index partition is truncated back to the last valid record and rebuilt instead of crash-looping the whole service.
- White-label branding: set your own company name and logo in Settings — they appear on the sign-in screen, the header, and Setup instead of product branding.
- Scrubbing is priority-based: full-quality video wherever it is already buffered, the fast scrub stream elsewhere, thumbnails as the last resort — and a SCRUB · HQ/SD/FAST badge now says which one you are seeing. Thumbnails can no longer paint over decoded video.
- Timeline lanes are readable again: green recorded band, cyan preview lane, near-white playhead.
- Grids shape themselves to the camera count and never clip on short windows; empty and loading states share one designed pattern.
- Live view fills the screen instead of leaving empty margins, and you can now choose how many cameras to show per page — 2, 4, 6, 8, 10, 12 or 16.
- Playback has a date picker: jump to any date and time, with dots marking the days that actually have footage for that camera.
- Snapshot is reachable on phones — it used to exist only inside the controls sheet.
- Remote viewing starts faster: video begins over the secure tunnel straight away and upgrades to a direct peer-to-peer connection in the background.
- Remote viewers now get the recorder's own sign-in screen when it asks for one, instead of landing on an error.
- A Problems tab spots cameras whose stream quality has drifted from their configured ladder and repairs them on request.
- The scrub cache keeps itself to 80% of its drive, so it can no longer fill the disk and stop recording.
- v0.2.43-preview
Storage failure domains: the recorder survives a full, unmounted, or failing drive and rebalances onto drives that come back.
- Each recording drive is verified as the real mounted volume before any write, so an unmounted external drive can never be silently filled with recordings landing on the wrong filesystem.
- Disk errors are now classified — out of space, drive unavailable, read-only, or hardware failure — and handled accordingly: a full drive triggers an immediate cleanup pass, while a failing or disconnected drive fails recording over to a healthy drive with backoff instead of retrying in a tight loop.
- When a drive is mounted late or comes back online it is automatically re-probed and returned to service, and cameras already recording are gracefully rebalanced onto it a few at a time — segments are finalized cleanly first, with no torn footage and no double recorders.
- Operator-pinned drives are never failed over or rebalanced automatically.
- New storage-health counters — root failovers, volume-identity failures, cooldowns, and redistributed recorders — are visible in the stats API and web UI.
- v0.2.42-preview
Recording durability: bad segments are never indexed, lost index entries self-heal, and the network link is monitored.
- A recording segment now counts as saved only when both its file and its database entry are confirmed on disk; failed writes are quarantined instead of silently indexed.
- Database index writes retry automatically with bounded backoff, and anything lost in a crash or forced shutdown is found and restored by a paced background reconciliation that never touches good footage.
- A corrupted or emptied database index is now detected immediately and rebuilt from the recordings on disk automatically.
- The daemon now reports which network link it is using (Ethernet vs Wi-Fi, negotiated speed) and warns immediately when the connection degrades below gigabit — including in the menu bar.
- New storage durability and network counters are visible in the stats API.
- v0.2.41-preview
Self-healing recording and honest health reporting.
- Recording now automatically reattaches within seconds after a disk or write error, instead of silently stopping until a restart.
- Every camera stream (not just the main one) is watched for stalls and restarted automatically, with incidents tracked per stream.
- The health endpoint and menu-bar dot now report the worst stream, degraded reasons, and recording progress — a single healthy camera can no longer mask problems elsewhere.
- Empty DVR channels that occasionally blip no longer cause false health warnings or false incident records.
- All reliability drop and shed counters from the previous release are now visible in the stats API.
- v0.2.40-preview
Reliability hardening: memory bounds on every media queue and chaos-test foundations.
- Live viewer connections are now capped per stream (default 32, configurable) across both direct and H.264-compatibility lanes, so a runaway client cannot exhaust daemon memory.
- Remote viewing, camera event, and thumbnail pipelines now enforce byte budgets that shed stale or oversized data instead of growing without limit under pressure.
- Recording is never interrupted by thumbnail or preview work: oversized auxiliary buffers are dropped and resynchronize automatically at the next keyframe.
- Malformed video streams from remote transcoding are detected and terminated per-session instead of accumulating unbounded memory.
- v0.2.39-preview
Live cameras open faster, while the Wall loads snapshots with less duplicate work.
- Hovering a camera now warms the exact stream Playback will use and transfers that connection when opened, keeping the snapshot visible until the first decoded frame is ready.
- Bounded keyframe replay stays available during moderate memory pressure, avoiding unnecessary waits for the camera's next keyframe and exposing replay health in diagnostics.
- Snapshot refreshes now revalidate cached images, coalesce concurrent work per camera, and skip offscreen Wall tiles until they approach the viewport.
- v0.2.30-preview
Continuous recording integrity checks now catch storage failures before footage is lost.
- The daemon audits recent recordings every five minutes for missing, truncated, or size-mismatched media and missing init/audio sidecars.
- Retention failures, dangerously low free space, and fresh unindexed fragments are surfaced as reliability incidents in the API and Stats UI.
- v0.2.29-preview
Reliability evidence and safer automatic updates.
- Records local incidents for stream outages, recording stalls, database slowdowns, and update outcomes.
- Certifies Sparkle updates against the healthy pre-update camera and recording baseline before declaring success.
- Adds guarded rollback archives plus optional privacy-minimized reliability summaries that are off by default.
- v0.2.28-preview
A unified graphite design across the app and the website.
- Polished the viewer after the graphite revamp — status colors, radii, and canvas details now match the design system everywhere.
- The glidevizion.com website and the studio dashboard are now dark graphite too, matching the app.
- Sign-in, license portal, and plugin pages share the same refined look and readable contrast.
- v0.2.21-preview
Accurate system-stats rates on the dashboard.
- Fixed the live stats dashboard reporting wildly inflated per-second rates (e.g. DB write/op rates) when more than one stats view was open — rates are now computed once per interval from a single sampler, so the numbers are trustworthy for diagnosing real load.
- v0.2.20-preview
Scrub thumbnails generate from the low-res sub stream — far gentler on disk, and crisper.
- The backlog thumbnail generator now decodes the small sub recording instead of the full 4K main file, and reads one camera at a time in disk order — so it no longer thrashes the recording drives (which had made the timeline slow to load and live views drop on busy multi-camera systems).
- Thumbnail generation concurrency is now split into a fast in-memory live path and a gentle disk-reading backlog path (thumbnails.reconcile_concurrency), so live thumbnails keep up without the backlog starving the recording disk.
- Set thumbnail cell_width/cell_height to your sub stream's resolution for the crispest preview.
- v0.2.19-preview
Scrub thumbnails fill in across the whole timeline much faster.
- The thumbnail generator now uses all available cores and runs continuously to backfill missing previews — instead of a slow, capped trickle that could never catch up on a busy multi-camera recorder. The scrub track fills across your full recording history (and after a restart or update) far faster.
- Clears the large backlog of un-thumbnailed footage that previously left most of the timeline without scrub previews.
- v0.2.18-preview
Scrub previews play across the whole timeline; the thumbnail track shows where previews exist.
- The scrubbing preview now updates everywhere a thumbnail exists — before, it could freeze on the last sharp frame outside the buffered window, so only part of the timeline updated as you scrubbed.
- The thumbnail track now reads at a glance: solid where previews are ready, faint where they exist, and diagonal stripes where none are available — instead of looking sparse.
- v0.2.17-preview
Scrub thumbnails load instantly; preview stops flickering.
- Recent thumbnails now load straight into the scrub timeline's preview buffer (they were being fetched the slow per-image way and never showed as buffered, so the thumbnail track looked empty for recent footage).
- The scrub preview no longer flickers between sharp and blurry frames while you scrub — the sharp frame now holds steady throughout.
- v0.2.16-preview
Build version shown in the sidebar.
- The running build version now appears pinned at the bottom of the navigation sidebar, including the exact commit it was built from — so you can tell at a glance which build you're on (no more digging or guessing).
- v0.2.15-preview
Scrub preview flicker — fully fixed.
- Fixed the remaining case where the scrubbing preview still flickered between sharp and blurry frames while scroll-scrubbing with both buffers loaded. The high-quality frame now holds steady throughout the scrub.
- v0.2.14-preview
Updates now install themselves — no more prompts.
- New versions now download and install automatically in the background and the app relaunches itself, instead of interrupting you with an 'install now?' dialog every time. Note: this particular update is the last one you'll confirm by hand — every release after it installs silently.
- v0.2.13-preview
Smoother scrubbing — no more quality flicker.
- When scrubbing the timeline by scrolling, the preview no longer flickers between sharp (high-quality) and blurry (thumbnail) frames. The high-quality preview now holds steady as you scrub, dropping to the quick thumbnail only across genuine recording gaps.
- v0.2.12-preview
Cleaner motion timeline, leaner recorder.
- Camera motion now appears as clean blocks on the scrub timeline. Previously a camera's constant stream of internal status pings and motion 'heartbeats' drowned out the actual motion, leaving the motion track empty; the recorder now coalesces these into clear start-to-end motion events.
- Far fewer database writes. Cameras emit a continuous torrent of status events; the recorder now collapses them to one entry per real event, keeping the recording index small and the timeline responsive over long uptimes.
- v0.2.11-preview
Timeline scrubbing stays fast on busy multi-camera systems.
- Fixed a slowdown where the recording index's write-ahead log could grow without bound on a busy recorder, making the scrub timeline and thumbnail preview load slower and slower over time. The log is now compacted on every checkpoint, so scrubbing stays responsive no matter how long the system has been running.
- v0.2.10-preview
Backfill keeps up without stalling live recording.
- Scrub-thumbnail index writes are now coalesced into shared database transactions instead of one per image, so the background backfill no longer competes with live recording for the single writer — the root cause of the earlier scrubbing stalls.
- Backfill can drain its historical backlog faster while live scrubbing and recording stay responsive.
- v0.2.9-preview
Restore scrubbing responsiveness — the previous tune went too far.
- Backfill concurrency dialed back from 8 to 2 parallel workers. The historical thumbnail backlog now drains slower in the background, but live scrubbing and recording stay responsive.
- v0.2.8-preview
Tuned thumbnail pools for fleets that finalize their footage all at once.
- Bigger absorption buffer for the thumbnail pipeline: 35 NTP-aligned cameras hitting their segment boundary in the same second no longer overflow the queue and drop sprite work.
- More parallel ffmpeg workers by default on multi-core boxes — uses up to (CPU cores − 2) workers, doubling the rate the historical backfill backlog drains.
- v0.2.7-preview
Smarter thumbnail backfill — uses your spare cores, ignores footage about to be deleted.
- Backfill workers now run in parallel (auto-tuned to half your CPU cores, default 4 on a 10-core box). At 35 cameras that drains a large backlog roughly 4× faster.
- Skip backfilling segments that are already past their retention window — no point thumbnailing footage that's going to be deleted in seconds.
- Auto-scale the RAM thumbnail pool to the fleet size: one worker per ~8 record-enabled streams, with a sensible floor. Drops from the prebuffer-to-extractor handoff (the cause of dropped scrub thumbs at high camera counts) go to near zero.
- v0.2.6-preview
Scrubbing slowdowns at high camera counts — the actual culprit, fixed.
- The thumbnail backfill bookkeeper used to recount the entire pending backlog every 2 minutes — at 35 cameras that meant ~105 heavy database scans per cycle, each holding a connection for 2-4 seconds. Cut to once every 20 minutes; the gauge stays accurate between recounts by subtracting completed backfills.
- Net effect on the office Mac Studio: the multi-second read tail (was 3.9 s worst-case) drops, scrub data loads cleanly even when a long backlog is being healed in the background.
- v0.2.5-preview
Scrubbing performance — significantly faster at high camera counts.
- Scrub thumbnails for wide timeline windows now load up to ~8× faster: the daemon reads sprites in parallel — closest-to-the-cursor first — instead of one at a time.
- New in-memory cache for scrub thumbnail bytes (256 MiB by default, configurable via playback.sprite_cache_mb): scrubbing back and forth over recent footage hits zero disk on the second pass.
- Per-camera thumbnail bookkeeping is now independent across cameras — housekeeping work on one camera never pauses scrubbing on the others.
- Lookup metadata for the thumbnail timeline is briefly cached, cutting two database round-trips off every sustained scrub.
- Validated at 35 cameras: timeline reads stay fast at the office Mac Studio's full fleet load.
- v0.2.4-preview
Performance — significantly less CPU spent on memory allocation, smoother live UI under load.
- Auto-tuned Go GC: the daemon now collects garbage about 5× less often by default (GOGC=400), and respects a soft memory ceiling of 80% of system RAM. Tested on the office Mac Studio: GC pauses fall from over a second to a few hundred ms.
- Pooled the per-packet buffer on the RTSP ingest path. At a 16-camera fleet that's roughly 1000× less heap churn on the source side — the visible result is a snappier live UI when many cameras are recording.
- Both knobs are config-overridable (server.gc_percent, server.memory_limit_mb) for advanced operators.
- v0.2.0-preview
Auto-update via Sparkle, a Swift app launcher, remote access foundation, and iOS app preview.
- macOS app now self-updates via Sparkle — install once, every future release flows automatically.
- Native iOS app: live grid, click-to-focus, playback with WebRTC peer-to-peer over Tailscale when available.
- Remote-access plumbing: WebRTC data-channel transport via a managed coordinator (replaces the earlier Tailscale-only plan).
- Recorded-video transcode fallback for browsers without HEVC decode (H.264 lane).
- Live and recorded audio playback.
- Scrub-thumbnail rework: thumbnails now come from an in-memory prebuffer + a durable reconciler, so scrubbing is instant at every zoom level.
- Snapshot API for the live tile / vendor-specific JPEG snapshot when available.
- Plus a long list of hardening fixes: WebSocket origin checks, HTTP timeouts, per-IP login lockout, license activation + 1-seat enforcement, signed plugin packages.
- v0.1.0
The first public preview of NVR.
- Watch all your cameras live in the browser and record them 24/7, straight to your own disk.
- Scrub the timeline and jump to any moment of recorded footage instantly.
- One-time $50 license for up to 50 cameras — no subscription, no cloud, footage never leaves your network.
- Runs on macOS, Linux, and Docker; free to try on one camera.