Help with reverse engineering WebRTC with VicoHome Camera

I’ve managed to intercept most of the TLS communications after patching the app with reflutter to disable flutter’s SSL pinning. I’ve also managed to create a script to request a new username and password to access the TURN servers. So far my understanding is that ICE makes it easier to access the stream by having the client (KVS WebRTC) access relays if a direct connection to the webcam is unavailable:

I’m using this example to build a WebRTC client that is able to use ICE with TURN to (hopefully) access the stream and somehow get it into Frigate:
simple_webrtc_python_client/examples/webcam at main · aljanabim/simple_webrtc_python_client · GitHub.

Because this uses KVS WebRTC (which is what AWS Kinetic uses) I thought maybe I could get go2rtc to work since it supports Kinetic streams but so far I haven’t had any luck going that route.

2 Likes

I understand nothing :sweat_smile: but I hope you can find a solution.

marbleskyle even though I am a developer myself, I have almost no knowledge on networking and the stuff you are doing. I hope you find a way to make this work and we can use Vicohome cameras in Home Assistant. If you need any help to test stuff out, let me know.

Following. Got a birdcam aswell

following bc they seem like they’re good cams for a good price. Lack of HA integration is the only thing holding me back from purchasing a couple

I’m still here and waiting hopefully for a solution :slight_smile: im not a developer but I believe on you people.

1 Like

My man! Best of luck, you’re far beyond my capabilities.

Hey man. Any progress on that? Those cameras are great for the price and would be great to use them in frigate. I can get bird feeder with camera and solar for like 20 bucks. Nothing can best it.

Maybe it would be good to set a bounty?

I’m not finding a good datasheet on an Ingenic T23 or the wifi chip, but I think I see UART test pads on that board (VCC_3v3, LOG_TX, LOG_RX). It might be worth finding a ground on there and connecting to the UART if you can

So I figured out a round about way of getting Vico into HA (unfortunately this solution can’t work in my specific situation, but might be able to help someone else).

I basically:

  1. Added a guest account on the vico app and shared the camera.
  2. I then installed Genymotion on my linux machine, and had to fiddle with some extra packages (I think it was libhoudini) to get the arm apk installed (landed on a pixel 5, android 11, api 30).
  3. Got the apk installed (vico is available in Aurora Store and on their website, this is part of the official way to get it running on a pc: VicoHome for PC – How To use VicoHome On Your Computer - VicoHome) and added the guest account.
  4. Was content with the full screen view (live-video on my computer inside Genymotion) and alerts etc. This is how I’m currently using it, works great (need to reboot the geny-phone once in a while).
  5. Realized I could stream part of my screen so installed mediamtx to run a local rtsp server: docker run --rm -it --network=host bluenviron/mediamtx:latest
  6. In a separate terminal, sent it only the Genymotion screen: ffmpeg -f x11grab -framerate 30 -window_id 0x00c0001b -i :0.0 -c:v libx264 -preset veryfast -f rtsp rtsp://localhost:8554/geny (change the window_id: (List windows: wmctrl -l | grep -i genymotion) and also the IP/url if mediamtx is running on another machine, also open a firewall port: sudo ufw allow 8554/tcp)
  7. Added to HA as a regular rtsp.

Haven’t played more (frigate etc.), but I assume you could setup some automations now. It does easily show up on your dashboards, and via vlc remotely etc. You could also potentially use this fix for any camera app that isn’t officially supported but does have an android apk. Good luck!

That seems an interesting workaround. Could you rewrite the steps you described in a tutorial style?

AI helped:

Vico → Home Assistant via Genymotion — Complete tutorial

Summary: run Vico’s Android app inside Genymotion, capture the emulator window with ffmpeg, publish to a local mediaMTX (RTSP) server, and add the stream to Home Assistant.

Prerequisites

  • Linux host with X11 session (x11grab). If using Wayland, switch to X11 or use an alternate capture method.
  • Genymotion installed and a virtual device (e.g., Pixel 5, Android 11 / API 30).
  • ffmpeg, wmctrl, docker (for mediaMTX), and optionally docker-compose installed.
  • Basic Home Assistant access.

Step 1 — Share camera via guest account

  1. In the Vico app on your phone, create/add a guest account and share the camera with that guest.

Step 2 — Set up Genymotion and install Vico

  1. Install Genymotion on your Linux machine and create a virtual device (Pixel 5, Android 11 / API 30 recommended).
  2. Install ARM translation (e.g., Genymotion ARM translation / libhoudini) to allow ARM APKs.
  3. Install the Vico APK (Aurora Store or VicoHome for PC). Grant necessary permissions (storage, notifications, camera if asked).
  4. Log into the guest account in the Vico app and confirm live view and alerts work. Reboot the virtual device occasionally if the app becomes unstable.

Step 3 — Run mediaMTX (RTSP server)

  1. Quick test (ephemeral):
docker run --rm -it --network=host bluenviron/mediamtx:latest
  1. For persistence, use docker-compose with a config file (examples below in the systemd/docker-compose section).

mediaMTX will listen on port 8554 by default when using host networking.


Step 4 — Capture Genymotion window and stream to mediaMTX

  1. Find the Genymotion window id:
wmctrl -l | grep -i genymotion

Note the hex window id (e.g., 0x00c0001b).

  1. Start ffmpeg to capture that window and push RTSP (replace window_id and host as needed):
/usr/bin/ffmpeg -f x11grab -framerate 30 -window_id 0x00c0001b -i :0.0 -c:v libx264 -preset veryfast -b:v 2000k -g 60 -f rtsp rtsp://localhost:8554/geny
  • Adjust -b:v (bitrate), -framerate, and -preset for CPU/quality tradeoffs.
  • If mediaMTX runs on another host, replace localhost with that host IP.
  • To capture audio, add the appropriate audio input and mapping.

Step 5 — Open/forward port 8554 (if accessing from other machines)

  • UFW:
sudo ufw allow 8554/tcp
  • iptables:
sudo iptables -A INPUT -p tcp --dport 8554 -j ACCEPT
  • Router: forward external TCP port 8554 → host LAN IP port 8554.

Step 6 — Add RTSP stream to Home Assistant

  • Use the RTSP URL:
rtsp://<host>:8554/geny

Replace <host> with the IP/hostname of the mediaMTX host (e.g., 192.168.1.50).
Add as a generic camera or via integrations that accept RTSP. Verify the stream in HA dashboards and in VLC.


Persistence: docker-compose + systemd examples

  1. docker-compose.yml (save to /opt/mediamtx/docker-compose.yml)
version: "3.8"
services:
  mediamtx:
    image: bluenviron/mediamtx:latest
    container_name: mediamtx
    restart: unless-stopped
    network_mode: "host"
    volumes:
      - /opt/mediamtx/config.yml:/etc/mediamtx/config.yml:ro
      - /opt/mediamtx/data:/var/lib/mediamtx
    environment:
      - TZ=UTC

Example minimal /opt/mediamtx/config.yml

log:
  level: info

rtsp:
  protocols: [tcp]

paths:
  /geny:
    source: rtsp://127.0.0.1:8554/geny

Start:

mkdir -p /opt/mediamtx
# place files
docker compose -f /opt/mediamtx/docker-compose.yml up -d
  1. systemd unit for ffmpeg (save as /etc/systemd/system/geny-ffmpeg.service)
[Unit]
Description=FFmpeg Genymotion screen capture -> mediaMTX
After=network.target
Wants=docker.service

[Service]
Type=simple
User=YOUR_USER
Environment=DISPLAY=:0
ExecStart=/usr/bin/ffmpeg -f x11grab -framerate 30 -window_id 0x00c0001b -i :0.0 -c:v libx264 -preset veryfast -b:v 2000k -g 60 -f rtsp rtsp://127.0.0.1:8554/geny
Restart=always
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
  • Replace YOUR_USER and window_id, and adjust DISPLAY if needed.
    Enable and start:
sudo systemctl daemon-reload
sudo systemctl enable --now geny-ffmpeg.service
  1. Optional systemd for docker-compose (save as /etc/systemd/system/mediamtx-docker.service)
[Unit]
Description=mediamtx docker-compose
After=network.target docker.service
Requires=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/mediamtx
ExecStart=/usr/bin/docker compose -f /opt/mediamtx/docker-compose.yml up -d
ExecStop=/usr/bin/docker compose -f /opt/mediamtx/docker-compose.yml down
TimeoutStartSec=120

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable --now mediamtx-docker.service

Tuning, reliability, and tips

  • ffmpeg tuning: libx264 with -preset veryfast/fast and -b:v 1500–3000k; set GOP (-g) to ~framerate×2.
  • If the Genymotion window id changes on restart, use a fixed capture region (x11grab with +X,Y and -video_size) or a small script to discover the window id and restart ffmpeg.
  • Run ffmpeg as the X session user; if running system-wide, set XAUTHORITY to the session owner’s cookie.
  • Enable mediaMTX authentication in config.yml if exposing the stream beyond your LAN.
  • For motion detection use (Frigate, etc.), point the detector at the RTSP feed or use Vico alerts inside the emulator.
  • GPU acceleration: enable if available (reduce CPU).
  • Reboot the Genymotion virtual device occasionally if the Vico app degrades.

Legal / safety note

Confirm your usage complies with Vico’s terms of service and local laws. Secure RTSP endpoints and credentials if accessible outside your LAN.


Checklist (quick)

  • ARM translation (libhoudini) installed
  • Genymotion running under X11
  • Vico APK installed and guest account logged in
  • wmctrl used to get window_id
  • mediaMTX running and port 8554 reachable
  • ffmpeg streaming to rtsp://:8554/geny
  • Stream added to Home Assistant
  • Persistence (systemd/docker-compose) configured
1 Like

This is all written by ChatGPT but hey it’s working.

I hacked together an unofficial Home Assistant add-on that brings Vicohome cameras into HA using vico-cli and MQTT.

Repo (with full README, install steps, dashboard YAML, and troubleshooting) is here:

The add-on:
• Uses vico-cli (all the heavy lifting is done there):

• Logs into Vicohome (I recommend a separate “bridge” account that your main account shares cameras to)
• Polls for events and device info
• Publishes everything to MQTT and uses MQTT Discovery so HA auto-creates entities

Per camera you get:
• Last event sensor (with attributes like timestamp, imageUrl, videoUrl, eventType, serialNumber, etc.)
• Motion binary sensor
• Battery %, WiFi signal, and online/offline sensors

Everything else (detailed install, config, MQTT notes, optional Lovelace dashboard, and troubleshooting) is in the README in the repo.

1 Like

I have created a web-interface at https://vicoweb.lovable.app with Lovable, which uses Supabase edge functions to replace vico-cli and make calls directly. All auth is stored locally and encrypted with AES-GCM and a random IV. Of course, the edge function can decrypt this, so best to create a separate account and share the device with.

1 Like

Bro, thank you so much for that!

is it possible/available to add live feed there and/or rings? I’ve connected my doorbell through VicoHome to HA, not would like some notifications :slight_smile:

Hah yall don’t mess around! Who knew home automation folks are basically OffSec!! kudos!

I found this post after finding the the subreddit for bird watch people just laughing at how bad it was.

Thought I would share my personal open source project for Android emulation / OffSec !!

JAMBOREE Java Android Magisk Burp Objection Root Emulator Easy: https://JAMBOREE.rmccurdy.com

Is your supabase edge function using different API endpoints/params then vico-cli?

I’m unable to list events via vico-cli but can see them through your hosted app (vicoweb).

Hey everyone, I’m not an HA user myself, but I figured that this might be of use to you all.

I implemented a lightweight client for these cameras in pure Go, no android emulator necessary. Check out the repo here: GitHub - bbielsa/vicostream: Go client for Vico Home brand cameras · GitHub.

It outputs a raw h264 stream which can be piped to ffmpeg for endless possibilities. Right now, the audio stream is not outputted so the resulting video will be silent. If that’s something people are interested in I can work on that.

Note: This only works for the WebRTC cameras. You can confirm if your camera supports WebRTC by calling the selectsingledevice API endpoint and checking if "streamProtocol": "webrtc" is present. I believe the vico-cli mentioned in this thread could provide this info.

This is still a WIP, if the video does not connect try killing the client and trying it again. I am working on retry logic to handle this more gracefully, like in the official app.

How do you obtain the jwt token?