- switch Liveviews on Viewports
- list Viewports, Liveviews, or Cameras
- Display a snapshot of a camera's current view (inline, in a terminal that can draw images)
USAGE: camview <subcommand>
OPTIONS:
-h, --help Show help information.
SUBCOMMANDS:
list Show a list of liveviews, viewports or cameras
show Set a Liveview for a Viewport
snapshot Capture a snapshot of a camera's current view
config Manage tool configuration (protect host, api key) and
defaults
See 'camview help <subcommand>' for detailed help.
1 . Generate an API Key to allow access to the Protect API. You can generate an API key from the UniFi Protect web interface by navigating to Settings → Control Plane → Integrations. The API Key is a 32 character string
2 . Run the following commands to set the API key and host:
camview config write api-key <your-API-Key>
camview config write protect-host <your-Unifi-Protect-web-interface-hostname-or-IP-Address>
3 . Confirm that they are set correctly by running
camview config read # Note: the api-key will be slightly obfuscated
4 . Try out camview!
camview list cameras
camview list viewports
camview list liveviews
camview show Backyard --viewport MyViewport # assumes a liveview called Backyard and a viewport named MyViewport
camview snapshot Backyard # if your terminal supports iTerm image protocal (e.g. iTerm, Warp, Wezterm)
You can tell a viewport to switch to a specific Liveview by passing the Liveview name on the cmd line, and the Viewport with --viewport (-v). Names are case-INsensitive.
e.g. camview show Driveway --viewport MyViewport
If you don't give a Viewport name, it will use the first viewport returned by the camview list viewports command
e.g. camview show Backyard
If you don't give either a Liveview name or a Viewport name it will, it will try a liveview called "Default" on the first viewport returned by camview list viewports
e.g. camview show
The viewport used to be a second positional argument, which meant camview show MyViewport
silently looked for a Liveview called MyViewport. Making it an option removes the
ambiguity: the single positional is always the liveview.
- You can list available Viewports with
camview list viewports - You can list available Liveviews with
camview list liveviews(or justcamview list) - You can list available Cameras with
camview list cameras - You can get more data in csv format by adding
-f csv. For example:camview list cameras -f csv
Note: The listings are minimal and ugly. There is a lot that can be improved in future versions.
The camview snapshot [-c | --clipboard ] <camera-name> command will capture a snapshot from the specified camera and write it to the clipboard (with -c) or to the terminal (without -c).
Without -c, where the image goes depends on whether stdout is a terminal:
camview snapshot Backyard # inline in the terminal
camview snapshot Backyard > backyard.jpg # raw JPEG bytes, a usable file
- It's a static snapshot, not a streaming video.
- It uses the iTerm image protocol, not Kitty's.
Not every terminal implements that protocol, and one that doesn't will print the escape sequence instead of drawing it — a snapshot is roughly half a megabyte of base64 scrolling past. So camview only draws inline when it recognises the terminal:
| Recognised from | Values |
|---|---|
TERM_PROGRAM |
iTerm.app, WarpTerminal, WezTerm — the ones I've actually tested |
TERM |
the ghostty and wezterm families, which is what catches forks and wrappers that report their own TERM_PROGRAM |
Anywhere else it refuses and names the alternatives rather than filling your scrollback:
camview snapshot -c Backyard # to the clipboard
camview snapshot Backyard > shot.jpg # to a file
camview snapshot --inline Backyard # draw anyway
--inline is the escape hatch for a terminal that supports the protocol but isn't on
either list. Neither list can be complete — there's no cheap way to ask a terminal what it
can do — so the default is to refuse, on the grounds that one extra flag is a much smaller
cost than half a megabyte of base64 you can't scroll back past.
Camview needs two configuration strings:
- your Unifi Protect host IP or DNS name. For example
192.168.1.99orunvr.local - your Unifi Protect API Key (a 32 character string which you can generate in Protect -> Settings -> Control Plane -> Integrations)
Use the config write subcommand to store them where camview can find them.
- The API Key is stored securely in the macOS keychain as an
application passwordundercom.peterichardson.camview - The Protect host is stored in user preferences in the App Group "group.com.peterichardson.camview", key "protect-host"
camview config write api-key XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
camview config write protect-host unvr.local
camview config read
Of course, you can also use built in macOS tools (security and defaults) to set and validate these items:
# Get API Key
security find-generic-password -a api-key -s com.peterichardson.camview -w
# Set API Key
security add-generic-password -a api-key -s com.peterichardson.camview -w XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# Get Protect Host
defaults read group.com.peterichardson.camview protect-host
# Set Protect Host
defaults write group.com.peterichardson.camview protect-host unvr.local
To change the live view on your Viewport by pushing a button on an Elgato Stream Deck, you can wrap the cli "camview show" call in a mac app using Automator. Or, you can use the code in the Streamdeck Extras folder to quickly generate smaller, faster apps. For more info, see this readme.
MIT — see LICENSE. Use it, change it, ship it.