A SnapCam is a small fixed-focus action camera capable of producing a 720p H.264
video feed with AAC audio from the internal microphone. It can save the feed in
an MP4
container to a microSD card, stream the feed in RTSP over WiFi, or do
both of these things simultaneously.
The device appears to use a Broadcom Bluetooth chip (mine is a BCM20736
) with
an ARM Cortex M3 as the main application processor. It uses an OmniVision
OV788
chip (the same chip that the 720p
first generation Amazon Ring
doorbell uses) for interfacing with the CMOS camera module and real-time 720p
H.264+AAC encoding at 30 fps. It uses a Wolfson WM89606
ADC for the
microphone.
The camera first starts up with only Bluetooth-LE enabled. It uses Bluetooth for sending picture taking commands, sending video recording commands, and configuring the camera's various settings. All commands are in a JSON-like format with a simple checksum at the end (that the camera never checks). The camera will pair with any device upon request with no authentication whatsoever. 😈
To enable WiFi, you must send a special command (the Type 22
command) to the
camera's 0x2d
handle using the Bluetooth attributes protocol. Once that
command is sent, the camera will spin up a WiFi access point on the 2.4GHz band.
If this is your first time connecting to the camera's WiFi, you may also want to
send the Type 18
command to the camera to get the camera's WiFi SSID and WPA
PSK. Again, the camera will give this information to you with no authentication
whatsoever.
With WiFi access point enabled, you should be able to connect to it and get an
IP address from the camera's DHCP server on the 192.168.2.0/24 subnet. Every
SnapCam I've tried so far has its IP address statically assigned to
192.168.2.103. Once connected, you'll have access to the camera's very secure
(use admin:admin
for the HTTP basic auth login) web interface on port 80, as
well as the RTSP server running on port 554. There is also something that my
nmap
detects running on port 4000, but I have yet to poke around at it.
You can buy a SnapCam on Amazon while supplies last. The OmniVision video encoding/camera ASIC appears to be end-of-life, so I'm not sure how long these will be up for sale online.
Note that this project will only work on the SnapCam models with the onboard WiFi! The SnapCam Lite 1046 model uses a completely different application processor and lacks onboard Bluetooth/WiFi. Only buy the SnapCam 1045/1050 model if you intend to try out the code in this repository! Both are listed on the same Amazon page, so be sure to verify that you are purchasing the correct model.
This is a proof-of-concept that allows you to setup and stream video from an iON SnapCam without the need for the Android app. This software was made by reverse-engineering the Bluetooth traffic of the iON Camera+ app using my phone's onboard Android developer tools' Bluetooth packet capture.
I have written the Snapcam
and SnapcamRTSP
classes that allow you to
interact with and stream video from a SnapCam.
Currently this software only supports running on Linux systems with Python 3.8 or
newer. It also requires bluez-tools
, a recent version of ffmpeg
, and the
v4l2loopback
kernel module.
You must install the out-of-tree v4l2loopback
kernel module.
If you install the kernel module from your distro's package manager and have the
/etc/modprobe.d
directory, make a file named
/etc/modprobe.d/v4l2loopback.conf
with the following contents:
options v4l2loopback devices=4 video_nr=2 exclusive_caps=1
Once that file is in place, you can modprobe
the installed kernel module:
# modprobe v4l2loopback
If you build the v4l2loopback
module
from GitHub, you can insmod
it
thusly (make sure you build it first):
# insmod ./v4l2loopback.ko devices=4 video_nr=2 exclusive_caps=1
Currently my software is hardcoded to stream the video to /dev/video4
(see
Snapcam/rtsp_util.py
line 54). A lot of the video processing code will be
rewritten in the future, including the part that only streams to /dev/video4
.
Set up your virtual environment:
$ python3 -m venv .venv
Enter your virtual environment:
$ . .venv/bin/activate
Install the Snapcam
Python package:
(.venv)$ python3 setup.py install
Hold the power button on the camera until you hear two short beeps. The camera should now be on and ready to receive commands over Bluetooth-LE. See the camera's owner's manual for more information.
If you don't have a GUI control panel that allows you to enable your computer's
Bluetooth, you can run the following in a root
shell or with sudo
:
# systemctl start bluetooth
As your regular user, start bluetoothctl
:
(.venv)$ bluetoothctl
Agent registered
[bluetooth]#
From the bluetoothctl
prompt, power on your computer's Bluetooth:
[bluetooth]# power on
Changing power on succeeded
Start scanning for devices:
[bluetooth]# scan on
Discovery started
[CHG] Controller 98:8D:46:DC:AB:BC Discovering: yes
[CHG] Device D4:2C:3D:07:44:60 RSSI: -69
[CHG] Device D4:2C:3D:07:44:60 TxPower: 4
Locate your SnapCam:
[bluetooth]# devices
Device D4:2C:3D:07:44:60 Snap4460
Write/record the MAC address of your camera, it'll come in handy later.
You can now safely exit
the bluetoothctl
CLI:
[bluetooth]# exit
(.venv)$
To enable the WiFi run the enable-sc-wifi
followed by your camera's
Bluetooth MAC address:
(.venv)$ enable-sc-wifi D4:2C:3D:07:44:60
{"Type": 18, "ssid": "SnapCam_2264", "pwd": "123456789"}
Connect to it using your computer's WiFi settings (or wpa_cli
if you're too
cool for NetworkManager).
Plugging in your SnapCam into a micro-USB charger while running the demo is highly recommended, as its battery life is abysmal while streaming over WiFi.
The first demo shows how you can use my Snapcam
class to interact with a
SnapCam 1050.
Edit the Bluetooth MAC address in line 8 of examples/demo.py
to your
camera's Bluetooth MAC (find it by scanning with bluetoothctl
):
sc = Snapcam("d4:2c:3d:07:44:60", debug=True)
Run it like so:
(.venv)$ python3 examples/demo.py
This demo will demonstrate toggling and changing some settings on your SnapCam, just like the Android and iOS apps do.
Ensure your computer is connected to the SnapCam's WiFi AP and has gotten a DHCP address.
Run the demo in a terminal (keep the terminal open):
(.venv)$ python3 examples/rtsp-demo.py
With the other terminal open, you should now be able to use the SnapCam as a webcam in any software that uses Video4Linux webcams on Linux like Cheese, Discord, FFmpeg, MPV, OBS Studio, VLC, or Zoom!
- This software currently does not parse the RTP headers at all (will be handled in the future in a C extension), leading to some interesting video corruption and frame rate fluctuation from out-of-order video packets.
- This is just an initial proof-of-concept.