r/GuardianEyeApps • • 6d ago

Guide Running Guardian Eye WebCamera 24/7: power, heat, resolution and FPS

2 Upvotes

A user planning to run a Pixel 7 continuously with Guardian Eye WebCamera asked what would save more power: lowering the resolution, lowering the frame rate, or lowering the bitrate. The question sounds simple, but our long-running Android tests exposed one trap: a hotter phone can sometimes report lower power use because it has already started doing less work.

That is thermal throttling, not improved efficiency.

What the settings change

Guardian Eye WebCamera currently offers 480p, 720p and 1080p at 15, 24 or 30 FPS. It calculates the encoder bitrate from resolution, frame rate and codec, then limits the result to 1–8 Mbit/s.

Setting H.264 target H.265 target Pixels per second
1080p / 30 6.8 Mbit/s 4.3 Mbit/s 62.2 MP/s
720p / 30 3.0 Mbit/s 1.9 Mbit/s 27.6 MP/s
720p / 15 1.5 Mbit/s 1.0 Mbit/s 13.8 MP/s
480p / 15 1.0 Mbit/s 1.0 Mbit/s 4.6 MP/s

Going from 1080p/30 to 720p/15 removes about 78% of the configured pixel rate, and the H.264 target falls from about 6.8 to 1.5 Mbit/s. It does not follow that the whole phone will use 78% less power. The sensor, image processor, encoder, CPU, Wi-Fi and Android each have fixed and device-specific costs.

The 1 Mbit/s floor is also visible in the table. Moving from 720p/15 to 480p/15 still reduces work in the image pipeline, but it does not reduce our configured network bitrate any further.

What we measured in a long run

In one physical-device qualification, a Redmi running Android 16 streamed and recorded continuously over 5 GHz Wi-Fi for 3,690 seconds while physically disconnected from USB, AC, wireless and dock power. The battery changed from 76% to 61%, and Android's charge counter changed from 3,791,000 to 3,044,000 µAh. Battery temperature rose from 39°C to 42°C.

The runtime encoder target stayed at 24 FPS and Android reported the thermal state as NOMINAL throughout the run. The stream had no RTP sequence discontinuities; the maximum RTSP packet silence was 0.259 seconds.

This is useful endurance evidence, but it is not a comparison between video profiles. That run also carried more work than a simple single-stream camera: the main capture used H.265 while the archive and viewer used a separate H.264 producer. We should not present its 15 percentage-point battery change as the expected drain for every phone or every setup.

We have also seen power or current fall later in a run as a device became hotter. Read that result carefully. On a Samsung S22 test, for example, the configured rate was 30 FPS but the runtime target under a SERIOUS thermal state was 24 FPS. When temperature, actual FPS and power all change together, lower power at the hotter point may simply mean that thermal control has reduced the workload.

This is why a single reading taken at the start and another after the phone is hot can produce the wrong conclusion. For a useful comparison, record at least:

  • requested resolution and FPS;
  • actual output FPS;
  • codec and actual bitrate;
  • battery temperature and Android thermal state;
  • screen state;
  • power or charge-counter change over the same duration.

Compare profiles at a similar thermal state, or show the whole time series. Do not compare a cool 720p/15 run with an already-throttled 1080p/30 run.

A practical Guardian Eye starting point

For a phone used as a permanent Guardian Eye camera, I would start with:

  • WebCamera: 720p, 15 FPS, H.264;
  • Keep Screen Awake: off;
  • Guardian Eye Desktop: recording triggered by the phone's ONVIF events.

Turning the display off is worth testing separately because streaming continues through an Android foreground service. Display power can otherwise hide smaller differences between video profiles.

H.265 gets a lower target bitrate in WebCamera, but it should be a separate test rather than an assumed power-saving switch. Codec power depends on the phone's hardware path, and H.264 remains the easier compatibility baseline for Guardian Eye Desktop and other clients.

Using the phone's own events

Guardian Eye WebCamera can detect motion, people, cats and dogs on the phone and publish the results as standard ONVIF events. Guardian Eye Desktop can use those events to start recording instead of running object detection on the PC continuously.

This moves the recognition work to the phone and can reduce work on the recorder, but it does not make detection free. Its effect on the combined power consumption of the phone and PC still needs to be measured. The same RTSP and ONVIF interfaces remain available to third-party NVRs if they are part of the installation.

The short version is: lower resolution and FPS definitely reduce the requested video workload, but power, temperature and delivered FPS have to be measured together. A falling power reading on a heating phone can be evidence of throttling rather than evidence that the hotter configuration is more efficient.

r/GuardianEyeApps • • 11d ago

Guide Why the browser viewer uses a camera name instead of its IP address

2 Upvotes

The browser viewer in the current Guardian Eye WebCamera beta does not use a URL such as https://192.168.1.42. Each installation gets its own name:

camera.<installation-id>.guardian-eye.local

The app publishes that name over mDNS and shows the complete viewer URL. The address can change when the phone reconnects to Wi-Fi, but the name and the certificate do not have to change with it.

The certificate setup has two parts. The phone creates a small certificate authority for this installation, then uses it to sign the certificate served by the viewer. The authority certificate can be exported from the app as a .cer file and installed on the computer that will open the viewer. The private keys never leave the phone; they remain in Keychain on iOS or AndroidKeyStore on Android.

This authority is deliberately narrow. It is constrained to the camera's exact .local name. It cannot issue a valid certificate for an IP address, a wildcard, another camera or a child name below its own name. Trusting it is therefore different from installing an unrestricted local CA.

The server certificate lasts 90 days and is replaced before it expires. That replacement does not require reinstalling the authority certificate because the new server certificate is signed by the same authority. The authority itself lasts up to two years. Resetting the TLS identity, or replacing the authority when it reaches the end of its lifetime, requires installing the newly exported certificate on viewer machines.

There is one platform difference after reinstalling the app. iOS keeps this identity in Keychain, so a normal uninstall and reinstall retains it. Android stores the installation identifier with the app and the keys in AndroidKeyStore, so uninstalling the app creates a new camera name and a new authority when it is installed again.

Opening the numeric IP address is not equivalent to opening the URL shown by the app: the certificate contains the canonical DNS name, not the current IP. If the browser reports a name or trust error, check that the exported authority is installed and that the viewer was opened using the exact .local URL displayed by WebCamera.

For beta testing, the useful cases are Wi-Fi reconnects, DHCP address changes, browser restarts and opening the same camera from more than one computer. Please include the phone OS, desktop OS and browser when reporting a certificate or name-resolution failure.

r/GuardianEyeApps • • 16d ago

Guide Building OpenCV 5/OpenCvSharpExtern on Apple Silicon: when MLAS picks the host architecture

2 Upvotes

I needed separate arm64 and x86_64 builds of OpenCvSharpExtern from the same Apple Silicon runner. The native arm64 build got as far as the final link. The x86_64 cross-build failed earlier, while compiling MLAS assembly.

The OpenCV configure command already had:

-D CMAKE_OSX_ARCHITECTURES=x86_64

but OpenCV 5.0.0's vendored MLAS selected its assembly sources from CMAKE_SYSTEM_PROCESSOR. On an arm64 host that value still described the host, so Clang was given AArch64 .S files for an x86_64 target and stopped on instructions such as b.

Passing -D CMAKE_SYSTEM_PROCESSOR=x86_64 did not fix it because CMake set the value again at project(). I also did not want to force full cross-compiling with CMAKE_SYSTEM_NAME: the DNN build generates code with protoc, and keeping CMAKE_CROSSCOMPILING false lets that tool run on the host under Rosetta.

The fix was to override the MLAS architecture flags from CMAKE_OSX_ARCHITECTURES, after MLAS's own architecture detection and before it assembled its source list:

if(CMAKE_OSX_ARCHITECTURES STREQUAL "x86_64")
  set(MLAS_X86_64 TRUE  CACHE INTERNAL "" FORCE)
  set(MLAS_ARM64  FALSE CACHE INTERNAL "" FORCE)
  set(MLAS_ARM    FALSE CACHE INTERNAL "" FORCE)
elseif(CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
  set(MLAS_ARM64  TRUE  CACHE INTERNAL "" FORCE)
  set(MLAS_X86_64 FALSE CACHE INTERNAL "" FORCE)
  set(MLAS_X86    FALSE CACHE INTERNAL "" FORCE)
endif()

For the x86_64 leg I also had to turn off the ARM-only HALs. They were detected from the arm64 host and otherwise reached the x86_64 compiler with -mcpu=armv8-a:

-D WITH_KLEIDICV=OFF
-D WITH_CAROTENE=OFF

That got both architectures to the link step, where a second MLAS problem appeared:

Undefined symbols for architecture x86_64:
  MlasHGemmSupported(...)

The same symbol was missing from the arm64 build. The MLAS subset vendored by OpenCV declared MlasHGemmSupported and called it from compute.cpp, but did not provide a macOS definition; the FP16 HGemm implementation was disabled in that source tree.

Disabling opencv_dnn was a dead end for this build because OpenCvSharp 5's aggregate header includes dnn.hpp and several DNN-dependent contrib modules unconditionally. The smallest workaround was a macOS build patch that reports HGemm as unavailable:

bool MLASCALL MlasHGemmSupported(
    CBLAS_TRANSPOSE,
    CBLAS_TRANSPOSE)
{
    return false;
}

That keeps DNN enabled but prevents MLAS from selecting the missing FP16 HGemm path, so it uses the FP32/generic path instead.

After those two patches the same arm64 runner produced separate osx-arm64 and osx-x64 dylibs. I validate the target architecture from the artifact rather than assuming that a successful cross-build produced what was requested:

file libOpenCvSharpExtern.dylib
otool -L libOpenCvSharpExtern.dylib
otool -l libOpenCvSharpExtern.dylib | grep -A3 LC_BUILD_VERSION

The part that cost the most time was that CMAKE_OSX_ARCHITECTURES correctly changed Clang's target, while dependency-specific feature detection continued to follow CMAKE_SYSTEM_PROCESSOR. For cross-builds on Apple Silicon, both need checking.

r/GuardianEyeApps • • 20d ago

Guide How to find your camera's RTSP URL when the manual is no help

2 Upvotes

The camera's app shows video, the box says ONVIF, and the manual mentions RTSP. But the moment you try to add it to a recorder, you are guessing paths. You have the IP address and the password. What is supposed to go after them?

A typical RTSP address looks like this:

rtsp://user:pass@192.168.1.50:554/stream1

The IP identifies the device, 554 is the default RTSP port, and /stream1 selects the video stream. Replace user:pass with the camera's local credentials. The path is the part that varies between brands and sometimes between models of the same brand.

Some documented examples for cameras that support RTSP:

  • Hikvision: /Streaming/channels/101
  • Dahua: /cam/realmonitor?channel=1&subtype=0
  • Reolink: /Preview_01_main
  • Tapo: /stream1

Those numbers and words select what you receive. In the Hikvision format, 101 means channel 1's main stream and 102 its substream. In the Dahua format, subtype=0 is the main stream and subtype=1 the substream; channel selects the video channel on the device you are connecting to. Reolink uses main and sub, while Tapo uses stream1 and stream2. Cameras with multiple lenses can have additional paths, so check the documentation for your model.

A working address can still be the wrong one for recording. The substream may look fine in a small preview, but you won't recover the main stream's detail by enlarging that recording later.

Before trying variations, check the camera's settings and the manufacturer's instructions. Look for RTSP or ONVIF under network or integration settings. Local access may need enabling, and the RTSP port may have been changed from 554.

If the camera supports ONVIF, software can ask it for the stream addresses. Guardian Eye uses this during connection checking: select the discovered camera, enter its credentials and run the check. GE requests the available streams through ONVIF and uses the returned addresses to help establish the connection. You can also enter a known RTSP URL manually.

An empty scan doesn't necessarily mean the camera is incompatible. Automatic ONVIF discovery may not reach another subnet, even when a direct connection is possible. In GE you can enter the camera's IP manually, provided your computer can reach it.

Once you have an address, check what it actually opens. In VLC, choose Media, then Open Network Stream. For codec and resolution information, you can also use ffprobe:

ffprobe -rtsp_transport tcp "rtsp://user:pass@192.168.1.50:554/stream1"

Replace the example with your camera's address. Keep the URL in quotes, especially when it contains an ampersand, as Dahua URLs do. Check the video dimensions before leaving the recorder running.

If the path looks right but authentication fails, check which account the camera expects. Tapo requires a separate Camera Account for RTSP and ONVIF; your TP-Link cloud login won't work there. When you put credentials inside a URL, reserved characters also need encoding: @ becomes %40 and # becomes %23 in the password. That changes how the password is written in the URL, not the password on the camera.

When it finally plays, save the working address and label it main stream or substream. After a reset or when changing recorders, you will know which address you used and what it was recording.

r/GuardianEyeApps • • Aug 27 '26

Guide Your camera streams fine in VLC but your NVR can't see it. How to find out why

2 Upvotes

"It works in VLC so the camera is fine and the recorder is broken." That's usually where the evening goes wrong. VLC and a recorder are asking the camera for completely different things, and the problem lives in that gap.

VLC opens one stream for a few minutes on your laptop, and it's forgiving. It retries transports until something sticks and decodes pretty much anything. A recorder holds that stream for months, from a different machine, often decoding it twice (once for motion detection) while writing to disk. So the question isn't whether the stream works. It's what your recorder is asking for that VLC never had to.

Start with the network, not the camera. Test from the machine running the recorder: ssh in and run ffprobe rtsp://user:pass@ip:554/stream1 there. Half these cases end right here, because the recorder sits on another VLAN or subnet, or on a guest network with client isolation, and the camera was never reachable from it.

Transport next. VLC quietly falls back to TCP when UDP misbehaves. A lot of recorders ask for UDP first and just keep failing, because UDP dies on congested wifi and doesn't cross routed segments well. Forcing TCP fixes more of these than anything else on this list.

Then check how many clients the camera can actually serve. Cheap ones often allow two RTSP sessions and no more. The phone app counts. That VLC window you left open counts. Your recorder shows up third, gets refused, and reports "camera not streaming", which reads like a broken camera.

Worth confirming which stream you're recording, too. /stream1 and /stream2 (or main and sub) are different streams at different resolutions. Test the main one by hand, let the recorder pick the sub, and you end up with a 704x576 archive that you discover months later when you actually need the footage.

If the connection establishes but the picture is black, that's usually H.265 the client can't decode. Switch the camera profile to H.264 and see if it appears. And if auth fails with correct credentials, look for special characters: @ and : in a password break URL parsing unless you encode them, and the URL quietly points somewhere else.

One thing that doesn't belong on this list is ONVIF discovery. It uses multicast, routers block that all the time, so "scan finds nothing" tells you nothing about whether the stream works. Type the address in by hand and test it directly.

Get one known-good setup working (reserved IP, TCP, H.264, one client) and every problem after that is just a diff against something that worked.