Releases: borexola/neolink.net
Release list
v1.0.5
AI Search lands on the Events page, and a long investigation of broken event clips ends with playback fixed for good.
Added
- AI Search (beta). Search events in plain language, in all six UI languages. Structured queries (types, cameras, dates, times) answer instantly; descriptive ones ("someone in a red jacket") use your configured AI model and its stored event descriptions. Works best with AI event descriptions enabled; basic keyword search works without a model.
- Download button on the event player: save the full-quality clip as a file.
- A live Events page. New events appear in the sidebar as they happen; a still-recording clip shows a clear amber banner and the player switches to the finished clip by itself when the event ends.
- Multi-select camera and threat-level filters that persist per user profile, and a camera filter on the Logs page.
- Signing in from a deep link returns you to the page you asked for.
Fixed
- Event clips no longer break in the browser. Watching a clip while it was still recording could serve corrupt video that browsers refused to decode (VLC concealed it), and a restart mid-recording froze clips in that state forever. The live index now stops at what is on disk, clips reach the disk continuously, and an event only reports closed once its file is final. Previously affected clips play again after upgrading; nothing needs re-recording.
- A camera failing mid-recording now ends the clip cleanly at the gap instead of gluing undecodable resumed footage onto it. The event itself continues and closes normally.
- Notification snapshots can no longer starve a recording. The snapshot decoder runs at low priority with capped threads, so sampling a clip cannot drop the camera connection that is feeding it.
- The SD preview falls back to the HD clip automatically when it cannot play, and captures that never received a frame stop advertising a clip.
v1.0.4
Notification polish: webhook messages are now push-sized and can link back to their event, plus a batch of fixes from a review of the 1.0.3 notification stack.
Added
- Push-sized webhook messages.
{message}is now the one line a phone notification wants — "Person on Driveway at 14:32". The email keeps its full story, still reachable in webhooks as{detail}(and adetailfield in JSON mode); snapshots ride along unchanged. - Event links. Set the new optional Server address for links under Webhook settings and every event notification links to its clip: ntfy opens it on tap automatically, JSON mode gains a
linkfield, and the Discord/Gotify/Slack presets end with a{link}line (re-pick your preset or add the placeholder to a saved template). Blank address = exactly the old behavior.
Fixed
- A full notification queue silently discarded alerts while reporting success — burning the camera's email cooldown and muting server alerts for hours. Drops are now detected, logged, and rolled back.
- The Home Assistant Email/Webhook events switches went stale after web-UI changes; they now republish immediately, so presence automations read the truth.
- Email and webhook send timeouts scale with snapshot payload size (up to ten minutes) instead of deterministically failing snapshot-heavy sends on slow uplinks.
- Webhook deliveries survive a header-name typo, quotes in camera names (values are JSON-escaped in JSON bodies), and Buddhist/Hijri-calendar server locales.
- A wedged ffmpeg is now killed for real (120 s, whole process tree) instead of hanging snapshot sampling forever on stalled storage.
- Changing the email delay mid-event no longer loses that event's notification.
- Web UI: an abandoned access token is no longer silently saved later, test verdicts reset when the dialog reopens, preset swaps keep half-typed header lines, and a camera opted into a channel that was since unconfigured says plainly that nothing is being sent.
- Update checker: correct newest-version selection in the tags fallback, and the daily timer shares the page-load nudge's one-check-in-flight gate.
Full detail in CHANGELOG.md. Home Assistant add-on users get 1.0.4 through the add-on store as usual. The Windows desktop installer is attached below once CI finishes building it.
v1.0.3
Notifications grow up in this release: your cameras can now reach you by email, by webhook, and through Home Assistant automations.
Event emails. Turn on Email events on a camera and every detection mails the notification recipient with snapshots attached — five seconds into the event by default (configurable; 0 waits for the event to end), sampled from the moment of detection so the subject is in frame instead of the empty pre-roll. Encrypted footage samples the same as plain, and without ffmpeg the event thumbnail goes instead. Snapshot count, send delay and a per-camera cooldown live under Server settings → Notifications.
Webhook notifications. A second channel for whatever your homelab already runs: presets for ntfy (snapshot as a real push attachment), Discord (images uploaded into the channel), Gotify, Slack, and full-event JSON for Node-RED / n8n / Home Assistant — plus raw knobs (method, body mode, placeholder template, extra headers) for anything without a preset. Homelab TLS is covered by an "Accept self-signed certificates" switch, access tokens are stored encrypted and sent as Authorization: Bearer, and a failed test reports the real reason instead of "see inner exception".
Home Assistant switches. Each recording camera's HA device gains Email events and Webhook events switches — the same settings as the camera panel toggles — so automations can arm notifications when you leave and silence them when you're home, even while a battery camera sleeps.
UI. The per-device tab is now Browser alerts, with a test button that tells you whether the browser or the OS swallowed the notification. The Notifications tab is regrouped into Email, Webhook, Event notification and Server alert sections, each with its own test button and green/red verdict. Shrinking a retention window now asks for confirmation before existing footage is deleted.
Fixes. Snapshot sampling delivers exactly the count you asked for, spread across the whole event; browser alerts over plain HTTP explain the HTTPS requirement instead of giving impossible advice; deleting more than 1000 events at once works (sent in batches) and failures show the server's own reason; the Server settings dialog grows with your screen instead of stopping at 700px.
Home Assistant add-on users get 1.0.3 through the add-on store as usual. The Windows desktop installer is attached below.
v1.0.2
Windows becomes a first-class home, and battery cameras get a fix they will feel.
Added
- Run everything on one Windows PC. The installer gained a checkbox: tick it and the full server installs alongside the desktop app as a Windows service - starts with Windows, records your cameras 24/7 whether anyone is signed in, keeps config and footage under C:\ProgramData\Neolink.NET, and opens the firewall to your local subnet only. The web UI's Restart button restarts the service, and the same recovery brings it back from a crash. Step-by-step guide with screenshots: docs/windows-install.md.
- A one-command demo.
docker run --rm -p 8655:8655 ghcr.io/borexola/neolink.net:latest --demoruns the whole product against four synthetic cameras - live video, detections, seeded history, timeline - with nothing saved and a self-resetting world. Safe to host as a public try-it instance (accounts are disabled in demo mode). - The desktop app keeps a server list. Switch between saved servers with a double-click, add new ones, remove one with a confirmation - credentials stay DPAPI-encrypted.
Fixed
- UDP battery cameras on Windows hosts stop losing to Hyper-V. Wake probes and UDP connects bound their local port inside a band that Hyper-V/Docker port exclusions can swallow almost entirely, and every miss was silent - awake cameras reported asleep at whatever rate the exclusions dictated. Binding now falls back to the OS's ephemeral allocator. If your battery camera's wake capture felt unreliable on a Docker/Hyper-V machine, this is why.
- Refreshing the page now checks for updates instead of waiting out the daily timer (throttled to one GitHub call per six hours).
- Desktop dialogs no longer clip on 125%/150% display scaling, and every button sizes to its text.
- The empty camera wall points at Server settings (the gear icon) instead of telling you to edit config.json - in all seven languages.
Also: the README slimmed down into focused guides (Docker, Recording, Troubleshooting, Windows install) and wears a fresh, consistent screenshot set from the demo world.
Full detail: CHANGELOG.md
v1.0.1
A fast follow-up to 1.0.0, fixing its headline feature on the camera models that refused the new writes.
Fixed
- Detection-zone saves and motion-sensitivity writes rejected on some models. Neolink writes the camera's motion config back whole to preserve schedules and sensitivity tables, and some firmwares refuse their own config re-ingested - "param error" on the Video Doorbell line, "err get data from json" on others - while models like the RLC-810WA accept it. Writes now step down a ladder the camera chooses: the full object, then the app-style partial object (channel plus only the changed section), then the legacy Alarm dialect. The accepted rung is remembered per camera, every step down is a log line, and a camera that exhausts the ladder logs what each dialect answered so it can be reported and fixed precisely.
New in 1.0.0, in case you missed it
1.0.0 shipped the same day - coming from 0.9.x, this update also brings:
- Detection-zone editor. Edit a camera's detection zone from the camera dialog: the camera's own cell grid painted over its latest snapshot, rectangle drags with an explicit Block/Watch toggle, per-type tabs on cameras that keep separate AI zones, and doorbell support. Also scriptable via
GET/POST /api/cameras/{name}/detectionzone. - Sign-in protection (opt-in). Account lockouts and intrusion blocking for the web sign-in, with an address-blocked log line fail2ban can watch.
- Recording from server settings, preserving the camera's recording configuration when switched off.
- Sturdier sessions. A dropped browser connection no longer tears the page down mid-edit; Enter signs in; Esc closes the event dialog.
- A security-review sweep. A crafted camera link can no longer run script in the web UI; an unreadable
users.jsonrefuses sign-ins instead of turning authentication off; the server log cannot be forged through camera or sign-in text; UDP battery-camera sessions only accept their own camera's packets; the desktop app only handshttp/httpslinks to the system browser; and more. - Cheaper recording and playback, codec fallback for browsers without H.265 hardware decoding, and tiles that are borrowed - not stolen - when you visit a camera off the wall.
Full detail in CHANGELOG.md.
v1.0.0
Neolink.NET 1.0.0 brings the detection-zone editor, opt-in sign-in protection, and a security-review sweep across the server and desktop app.
Added
- Detection-zone editor. Edit a camera's detection zone from the camera dialog: the camera's own cell grid painted over its latest snapshot, rectangle drags with an explicit Block/Watch toggle, per-type tabs on cameras that keep separate AI zones, and doorbell (legacy firmware) support. Also scriptable via
GET/POST /api/cameras/{name}/detectionzone. - Sign-in protection (opt-in). Account lockouts and intrusion blocking for the web sign-in, with an address-blocked log line fail2ban can watch.
- Recording from server settings. Recording switches on and off from the server settings dialog, and disabling it preserves the camera's recording configuration.
- Sturdier sessions. A dropped browser connection (closed tab, network blip, reconnect) no longer tears the page down mid-edit, and Esc closes the event playback dialog.
Changed
- Enter signs in from either sign-in field, and a held key no longer spends several sign-in attempts.
- A tile whose codec the browser cannot decode (H.265 without hardware decoding) falls back to the camera's sub stream and says why - per device, without touching the saved layout.
- Recording and playback are cheaper: lower CPU per recording camera, quicker timeline scrubbing over older footage, faster exports.
- The sidebar's battery-camera badge dropped its BETA; the UDP transport pill stays.
Fixed
- A crafted camera link could run script in the web UI on the app's own origin; the camera name is escaped now.
- An unreadable
users.jsonlooked like a fresh install and turned authentication off; the server now refuses sign-ins, says so, and preserves the file for repair. - Visiting a camera with a full wall permanently evicted a tile; tiles are now borrowed and put back, surviving chained visits and page reloads.
- The server log could be forged through newlines in camera or sign-in text - including the address-blocked line fail2ban watches; control characters are neutralised centrally.
- A UDP battery-camera session accepted datagrams from any device that found the port; sessions are pinned to the camera's address and the reordering buffer is bounded.
- H.265 streams could be declared ready without the parameter set that makes them playable, producing decoder configurations browsers reject.
- The desktop app handed any URL scheme to the shell; only
httpandhttpsare passed on now. Clicking a notification also no longer opens a duplicate browser window next to the app. - A snapshot URL could request arbitrarily old footage; freshness and staleness are capped at an hour.
- Smaller hardening from the same review: SMTP header injection refused in email addresses, secret files owner-only from creation, stricter forwarded-for parsing, and near-duplicate camera names warn at startup.
Full detail in CHANGELOG.md.
v0.9.9
Added
- Event footage over HTTP Basic. An event's thumbnail, preview and clip now accept the RTSP user credentials, exactly like the snapshot endpoint. A Home Assistant notification can attach the firing event's thumbnail using the credentials HA already holds, no web-session token needed.
- Desktop app: video pauses while hidden. With the window in the tray or minimised, live streams stop entirely (no bandwidth, no decoding) and resume the moment the window shows. On by default, toggleable from the tray menu; notifications are unaffected. Needs a server on this version.
- Timeline: "Events only" playback (beta). A toolbar toggle that plays the day as just its events: playback hops from event to event, skips the quiet stretches, and pauses after the day's last event. It follows the EVENTS filter, and classic continuous playback is untouched when the toggle is off.
Changed
- The translated READMEs moved to
docs/translations/; only the English README stays in the repository root.
Fixed
- A battery camera's wake event no longer claims pre-roll footage from before the wake, which read as "missing" video on the event tile.
- Desktop app: switching keyboard layout no longer crashes it.
- Desktop app: a black window now recovers by itself, and hiding to the tray no longer recreates the window handle each cycle, which was the likeliest cause of the black windows. Every hide, show and recovery is logged to desktop.log.
- Desktop app: notifications clicked in the Action Center now open the app on their event, even hours later and even if the app was quit in between.
- A recorded footage file smaller than 8 bytes no longer serves as an empty 500.
Full details for every change: CHANGELOG.md
v0.9.8
The desktop app for Windows, and a web UI that speaks seven languages. Everything that changed since 0.9.7, summarized — full details in the CHANGELOG.
Added
- Neolink.NET Desktop for Windows (beta) — the web UI as an MSI-installed tray app that starts with Windows and raises native toast alerts even while the window is closed. MSI below; it is not code-signed yet, so SmartScreen shows "Windows protected your PC" — click More info → Run anyway.
- Seven UI languages — French, German, Spanish, Dutch, Polish and Portuguese join English. Picked at first run or under Server settings → Language, applied instantly, saved to your account. AI-translated, corrections welcome; condensed translated READMEs link off the main one.
- Opus audio per RTSP client — add
?audio=opusto any camera URL and WebRTC ecosystems (go2rtc, Home Assistant cards, browsers) get audio natively, while an NVR keeps recording the camera's own AAC from the bare URL. - AUDIO section in camera settings — record-audio toggle plus speaker, alarm and microphone volumes.
- PORTS tab — the camera's own service switches (HTTP, HTTPS, RTSP, ONVIF…) read live, with HTTP/ONVIF enableable from Neolink (admin only, behind a confirmation).
- Sound on the timeline — recorded footage now plays its audio, muted per monitor.
- Timeline bookmarks — save a named stretch of a day's footage; it appears as a gold ribbon on the timeline.
- Threat-level filter on the Events page for AI-described events.
- Fixed-rate AI frame sampling, and an opt-in switch to keep sent AI frames on disk so you can audit exactly what the model saw.
Changed
- Out of beta: Baichuan-over-UDP connect, detection sensitivity and infrared brightness, the Cameras editor, and footage encryption at rest.
- AI event descriptions graduate to BETA, with a review pass: the Test button now proves vision, transient connection failures retry, narration is grounded (per-frame inline labels plus rules against invented movement), very long events are described in ordered parts, the 20-frame budget ceiling is gone, and an event's first seconds keep full frame density so fast subjects stay visible.
Fixed
- Two-way talk that "works" but says nothing is now diagnosable and fixable — a per-device microphone picker (Server settings → Connection), a warning naming the device when a live session is capturing only silence, and refused talk connections that report themselves. The desktop app was hit hardest: its permission prompt has no microphone picker of its own.
- The desktop app recovers from "Session expired" by itself — the shell reloads the page as soon as the server answers, and the overlay now explains the state honestly.
- HA add-on: a camera whose name is a substring of another's is added instead of silently swallowed; the Options page is documented as the bootstrap list it is (and gained
stream,uid,udp,wake_capture,keep_alive_hours,http_address); camera settings edited in the web UI survive restarts. - No more surprise browser password popups over the web UI.
- A deep-sleep wake no longer strands the viewer after a battery camera reconnects.
- The camera panel explains a missing "Camera settings" tab and grows it live once the camera's HTTP API becomes reachable.
- Busy installations no longer lose history in the timeline and events views.
- AI descriptions no longer trail off before the event ends, and no longer come up empty on events with a busy start.
- Stale stylesheets after updates are gone — asset URLs change with each release.
- "View release" goes to the releases page, and the Monitor's 6h/24h charts no longer render empty.
Install / upgrade
- Docker:
ghcr.io/borexola/neolink.net:0.9.8(also:latest) - Home Assistant add-on: update to 0.9.8 in the add-on store
- Windows desktop app:
Neolink.NET.DesktopMSI below
v0.9.7
Highlights:
- AI event descriptions (experimental) — point Neolink.NET at a vision-capable LLM and every detection event gets a written description and a GREEN/YELLOW/RED threat classification, shown in the web UI, the event metadata and Home Assistant. Three interchangeable backends: OpenAI-style, Ollama and Anthropic-style. Feedback welcome. AI event descriptions (EXPERIMENTAL)
- Battery wake hints without a logging firewall — a DNS-override "push decoy": point
pushx.reolink.comat Neolink and the camera's own event push becomes the wake signal. - More of
config.jsonis editable from the web UI, with validation — wake-hint ports, recording fast/archive tiers, and the full MQTT connection. - New Home Assistant sensors per camera — Last AI description, AI threat level, and Last event time.
- Suspend/resume tidy-up, log-hygiene fixes, and the HA add-on's NVR channel option.
See the full changelog for details.
v0.9.6
This release is a major battery-camera update, plus much faster live view and a large idle-CPU cut. Full details for every item: CHANGELOG.md.
Battery cameras (beta)
- UDP-only models supported (much of the Argus line never listens on TCP):
uid+"udp": true, host networking required in Docker. Selective-repeat acks and a saturation self-diagnosis included. - Sleep-friendly by default: tiles are click-to-watch with a view budget, the camera is released ~10 s after the last viewer, and
"always_on": trueopts a powered camera out of all of it — it behaves exactly like a wired one. - Wake-capture rebuilt: self-wakes are detected by listening to ping patterns (no packet a sleeping camera would react to), recording starts from the first keyframe, the scan is self-skeptical against false wakes, and background polling goes radio-silent while the camera sleeps.
- New: router wake hints — point an OPNsense/pfSense firewall log at Neolink (
"wake_hints": { "syslog_port": 5140 }) and the camera's own call to Reolink's push service becomes an instant, event-grade wake signal. Requires push notifications enabled on the camera;POST /api/cameras/{name}/wake-hintaccepts hints from anything else (e.g. Home Assistant). - Events actually stick: PIR detections now store as Motion events (they were silently discarded), wake sessions wait out the camera's late detection push, and wake footage tapes passively to the Timeline at zero battery cost. 24/7 recording is enforced off while a camera is allowed to sleep.
- Each wake costs far less charge, and a keep-awake slider (0-24 h) covers the times you want the camera responsive regardless.
Setup guide: docs/battery-cameras.md
Live view and UI
- Live view starts near-instantly — a server-side keyframe buffer hands new viewers decodable video in milliseconds (measured 7-20 ms) instead of waiting seconds for the camera's next keyframe.
- "Stats for nerds": right-click a camera view for a live technical readout that tells device trouble apart from network trouble, with a copy button for bug reports.
- One-click resume for suspended cameras, browser alerts for system events and camera-offline, Wi-Fi signal and wired-link icons, and a camera-settings panel that no longer reshuffles while it loads.
- Fixes: stale snapshots are age-bounded and dissolve into live video, fast zoom clicks no longer reset the view, offline cameras say so on the tile, sidebar badges no longer squeeze out the camera name, and two browser windows can no longer disagree about a camera's state.
Performance
- Idle CPU cut ~5x (measured 0.85% → 0.17% of a core) and the periodic spikes reported against 0.9.5 are gone; MQTT re-publishes are deduplicated and per-tick camera polls now run once a minute.
Battery camera support is beta and under active development — if yours misbehaves, open an issue with the [wake-diag] log lines.
If Neolink.NET saves you or your business time, sponsorship funds the hours and the test hardware that keep it moving: Sponsor Neolink.NET.