Problem Statement#

Wyze makes some really great and unbelievably cheap WiFi cameras with some equally unbelievably garbage firmware, terrible subscription-pushing software, and Highly Questionable security practices. Good news: there are some wonderful projects out there to solve basically all the problems… but none of the docs I’ve come across are truly comprehensive and completely accurate. I’m going to attempt to fix that here.

References, Sources, Prior Art#

I am obviously standing on the shoulders of giants here, others have done WAY more work than I have, I’m just trying to synthesize and clarify what worked for me, if only so it’s all in one place whenever I decide I need yet another camera.

  • wz_mini_hacks - This is the core project that roots the camera, prevents forced firmware upgrades, and exposes a simple go2rtc stream. It does a TON of other stuff but this is the core functionality we will use it for.
  • Leo’s Notes - Leo’s article is WAY more extensive than the one I’m writing here, and goes into INCREDIBLE detail of otherwise completely undocumented settings for the software that runs directly on the camera.
  • Hound Hill Homestead - Hound Hill’s article is good but relies on setting the camera up via the Wyze App. If you follow this guide exactly you’ll end up on a firmware that physically cannot expose a go2rtc stream.
  • Josh’s Notes - Josh’s article is great – and I will be covering basically all the same ground – but it doesn’t go into Frigate setup or editing the camera config directly.

Additionally, a quick Alternative Considered:

  • docker-wyze-bridge - WyzeBridge is a great project, but it relies on having your camera authenticated with Wyze which I absolutely do not want, and requires even more overhead to process the feed before handing it over to Frigate.

Prerequisites#

  • A Wyze Cam V3 (~$35, sometimes a bit cheaper if you buy a multi-pack)
  • A FAT32 formatted MicroSD Card (wz_mini_hacks recommends a “decent” quality card, but it doesn’t need to be a huge capacity)
  • A local git checkout of wz_mini_hacks
  • An unpacked demo_wcv3.bin firmware binary, specifically v4.36.9.139, which is the final version fully supported by wz_mini_hacks.
    • This specific firmware revision is immensely important as if you use any newer version wz_mini_hacks will install and seem to work, but go2rtc will not work whatsoever
  • A working Frigate installation

Firmware Flashing & Installing wz_mini_hacks#

The goal for this step is to get the camera on a supported firmware revision and to get wz_mini_hacks installed and running.

  • Put only the uncompressed demo_wcv3.bin firmware file on your SDCard, insert it (under the little rubber flap on the bottom of the camera body), and power the camera while holding the “setup” button next to the SDCard flap.
    • This can be a bit clumsy to do, you may have an easier time powering it with the button held if you have the power on a switch or have a Helper holding the button down.
    • Keep holding it until the red + blue LEDs below the lens are on, which will look purple-ish, then you can release and wait a few moments for it to flash.
    • The camera LED will go steady blue when it’s done flashing and reboot, and will end with a blinking red light.
    • You’re now on 4.36.9.139!
  • Pull the power and pull the SDCard, delete everything on the card, and copy over the full contents of SD_ROOT from your wz_mini_hacks checkout.
  • Edit wz_mini/wz_mini.conf on the SDCard and flip the value of ENABLE_SELFHOSTED_MODE to "true". This will prepare it for local setup instead of app-based setup.
    • Note for Windows: This file needs Unix line-endings. There’s stuff in place to fix it, but I have no idea if it’s reliable.
  • Edit wz_mini/etc/ssh/authorized_keys on the SDCard and add your Public Key Signature.
    • Yes you’ll need to have key-based auth configured if you want to SSH into the camera.
    • Good News: You only have to SSH into the camera if you intend to edit some of the camera-specific settings as described below.
  • Pop the SDCard back in the camera and power it on.
    • It will audibly state “WZ mini initializing first boot” and then “Extracting swap. Please wait.”
  • When it’s complete the LED should again be blinking red.

Connecting to WiFi#

Normally you’d have to connect to the Wyze app at this point, but with ENABLE_SELFHOSTED_MODE="true" you can connect with a QRCode.

  • Prepare a WiFi Network Scan-to-Connect QRCode for a 2.4Ghz network.
    • You can do this a bunch of ways – Android can do it natively, various password managers can do it, etc – or you can use this CodePen that a bunch of people recommend.
  • Press the setup button again, listen for the “Ready to Connect” prompt, and point the camera at the QRCode.
  • It should then say “QRCode Scanned” and then “WiFi Connected”.
  • Now go to whatever on your network assigns IP addresses and figure out what IP the camera got.
    • Write that down! Or assign it a hostname! Or something!

Configuring wz_mini_hacks#

You can configure wz_mini_hacks three different ways:

  • SSH - ssh root@[camera ip] then run wz_mini_edit.sh to edit directly on the device with nano.
  • SDCard - Pull the SDCard and edit wz_mini/wz_mini.conf
  • WebUI - Add WEB_SERVER_OPTIONS="cam config car jpeg multicam diag status" to the config file, and then hit the camera’s IP/hostname in a browser

(Note that for both SSH and the WebUI you’ll have to power cycle the device for changes to take effect.)

I think the SDCard is the best option and technically you can do that before even configuring wz_mini_hacks, but it’s fine to wait until this point.

  • Enable all the go2rtc settings, this is how you’ll be getting a low-latency stream
    • Note: I don’t care about audio as my cameras are all behind glass, so I have it disabled.
GO2RTC_SERVER_ENABLED="true"
GO2RTC_HI_RES_ENABLED="true"
GO2RTC_HI_RES_ENABLE_AUDIO="false"
GO2RTC_LOW_RES_ENABLED="true"
GO2RTC_LOW_RES_ENABLE_AUDIO="false"
  • Configure your stream authentication. Or don’t. Pick one!
# configure auth
RTSP_LOGIN="some_login"
RTSP_PASSWORD="some_password"

# ...or disable it
RTSP_AUTH_DISABLE="true"
  • Enable and configure auth for the built-in webserver, or don’t
WEB_SERVER_ENABLED="true"
WEB_SERVER_OPTIONS="cam config car jpeg multicam diag status"

# configure auth
WEB_SERVER_AUTH="true"
WEB_SERVER_LOGIN="some_login"
WEB_SERVER_PASSWORD="some_password"

# ...or disable it
WEB_SERVER_AUTH="false"
  • Put the SDCard back in, power the camera back up, and it should be back on your network in ~20-30s.

Testing go2rtc#

At this point you should have a working camera on your network fully de-fanged and locked on a known-good firmware. Time to verify that.

  • You should be able to go to http://[camera ip]/ and get a simple web UI
  • You should be able to go to http://[camera ip]:1984 and get an equally simple go2rtc web UI
    • Here you should be able to click the “stream” link next to your 1080p stream and get a live feed that Just Works
  • If you get video, awesome, you’ve done everything right so far.

Configuring the camera itself#

Before loading this up in Frigate you may want to do some configuration at the camera-level first: stuff like flipping the video, turning off the OSD, configuring the night-vision, turning off motion bounding-box, etc. The Web UI has a means of viewing this but you can’t change the settings. Good news, you can configure this by SSH’ing in. Note that you have to edit this on the device directly, you can’t edit it via the SDCard.

Leo’s Notes has extensive docs on all the available settings and their values, but please note that the path to the config file on the camera is /configs/.user_config not .user_configs as Leo’s Notes state.

So:

ssh root@[camera]
nano /configs/.user_config

There are a ton of settings in there, but I personally needed to set these under the [SETTING] header:

  • I like to mount my cameras upside down, so I flip the output on both axes. I could do this with ffmpeg later, but… why not do it right on the device if you can?
verSwitch=2
horSwitch=2
  • I don’t need a timestamp watermark or a big WYZE watermark so I turn them off too.
osdSwitch=2
watermark_flag=2
  • The awful neon-green bounding-box when movement is detected is wildly unnecessary, so I killed it too.
drawBoxSwitch=2
  • Turn off the motion-detected light, or put some gaffer’s tape over it.
indicator=2

Write out the config, power cycle the camera, and you should see the results on next boot.

Frigate Configuration#

Frigate recommends bouncing streams through go2rtc, and from testing this go2rtc method vs just shoving your rtsp stream straight into your ffmpeg input, the CPU load is way lower for this approach and it’s apparently better supported in Home Assistant. Just fill in your camera’s name and its ip as noted below. Note that you’ll still need to configure all your other roles and configs if you want to record stuff.

go2rtc:
  streams:
    your_camera_name:
      - rtsp://[camera_ip]:8554/1080p?mp4

cameras:
  your_camera_name:
    ffmpeg:
      inputs:
        - path: rtsp://127.0.0.1:8554/your_camera_name # the name from the *go2rtc stream* def not *camera* def
          input_args: preset-rtsp-restream
          roles:
            - detect
      hwaccel_args: preset-nvidia # if you've got it!
    detect:
      enabled: true
      width: 1280
      height: 720

Restart Frigate and your camera should pop up and you’re done!

At this point you can lock down the camera to a VLAN with no external internet access or whatever else you might want.