IP Camera Binding

This binding allows you to use most IP cameras in openHAB and has many hidden features, so please take the time to read through this guide to learn different ways to work with cameras that you may not know about. I recommend purchasing a brand of camera that has an open API, as many features use far less CPU when done with an API camera. They usually have better picture quality and more advanced features compared to lower priced cameras.

To see what features each brand has implemented from their APIs, please see this post:

https://community.openhab.org/t/ipcamera-new-ip-camera-binding/42771

How to Get Help

  • Check this readme for any setup steps for your brand.
  • Check if the camera is offline, if so there will be a reason listed.
  • Always look at the log files with TRACE enabled, as any FFmpeg and camera errors may not reach the INFO logs. To enable TRACE logging, enter this in the openHAB console log:set TRACE org.openhab.binding.ipcamera.
  • Search the forum using any log messages to find how others have already solved it.
  • Only after doing the above ask for help in the forum and create a new thread.

Special Notes for Different Brands

Generic Cameras

This binding can turn a RTSP stream into snapshots (.jpg still pictures), create motion and audio alarms, cast the camera and much more. FFmpeg is required to be installed for these features to work and this must be done manually. FFmpeg can be installed very easily see Video Streams.

If your camera has a snapshot URL, provide it to the binding via the config called snapshotUrl after first testing the URL in any browser. When using FFmpeg instead of a provided URL to create snapshots, it requires more CPU that you can turn on and off via the pollImage channel using a switch or rule.

Snapshots generated by FFmpeg use the key frames (iFrames) to lower the CPU load, and since some cameras only produce a key frame every 2+ seconds with their default settings, this will effect how often a snapshot is produced. Some cameras allow the key frame to be created every second or a different amount by the user, refer to your cameras manual and support on how to do this.

ESP32 Cameras

These cameras do not have the ability to create H.264 streams and hence can not be used with HLS, however all other features should work. See the Full Example section for how to setup these cameras. Due to many custom firmwares available, you may need to ask the firmware developer what the URLs are for snapshots and MJPEG streams if they have changed the defaults from what the Arduino IDE sample code uses.

Amcrest

It is better to always setup your Amcrest camera as a dahua thing type. The old alarm polling based method is used if you setup as amcrest, and the newer/better event based method is used if you setup as dahua instead. All other features should be the same between the two.

Dahua

For MJPEG to work, you need to set the first sub-stream to use MJPEG format for the default settings to work, otherwise you can override the default with mjpegUrl config with a valid URL for MJPEG streams.

Foscam

  • If the user/pass is wrong, the camera can lockout and refuse to answer the binding requiring a reboot of the camera, so be sure the details are correct before the camera tries to poll the camera too many times.
  • To use MJPEG streaming, you need to enable one of the streams to use this format. This can be done by entering this into any browser:http://ip:88/cgi-bin/CGIProxy.fcgi?cmd=setSubStreamFormat&format=1&usr=admin&pwd=password
  • If your camera does not support MJPEG as some Foscams no longer do, then you can set mjpegUrl to contain ffmpeg to use your CPU to generate a MJPEG stream.
  • Some Foscam cameras need to have a detection area listed in the URL when you enable the motion alarm.

As each Foscam model has a different resolution and two different URLs, this makes it difficult to automate, so an override feature was added to create your own "enable the alarm" URL. This setting is called customMotionAlarmUrl and the steps to using it are:

  1. Enable the motion alarm in the web interface of your camera and setup any areas you wish movement to be ignored in. E.g. tree branches moving in the wind.
  2. Use any web browser to fetch this URL https://x.x.x.x/cgi-bin/CGIProxy.fcgi?cmd=getMotionDetectConfig1&usr=xxxxx&pwd=xxxxx
  3. Use the information returned by the above URL to create the override settings.

An example for a Foscam C2 is...

/cgi-bin/CGIProxy.fcgi?cmd=setMotionDetectConfig1&isEnable=1&snapInterval=1&schedule0=281474976710655&schedule1=281474976710655&schedule2=281474976710655&schedule3=281474976710655&schedule4=281474976710655&schedule5=281474976710655&schedule6=281474976710655&x1=0&y1=0&width1=10000&height1=10000&sensitivity1=1&valid1=1&linkage=6&usr=xxxxx&pwd=xxxxx

Another example is:

/cgi-bin/CGIProxy.fcgi?cmd=setMotionDetectConfig&isEnable=1&linkage=0001&sensitivity=1&triggerInterval=15&schedule0=281474976710655&schedule1=281474976710655&schedule2=281474976710655&schedule3=281474976710655&schedule4=281474976710655&schedule5=281474976710655&schedule6=281474976710655&area0=1023&area1=1023&area2=1023&area3=1023&area4=1023&area5=1023&area6=1023&area7=1023&area7=1023&area8=1023&area9=1023&usr=username&pwd=password

Hikvision

  • For MJPEG to work, you need to set the first sub-stream to be in MJPEG format, otherwise you can override the default with the mjpegUrl config with a valid URL for MJPEG streams.
  • The CGI/API and also ONVIF features are disabled by default on these cameras, so enable and create user details for ONVIF that are the same user/pass as what you have given the binding. If your camera does not have PTZ (Pan Tilt Zoom) then you can leave ONVIF disabled and just enable the CGI/API.
  • Each alarm you wish to use must have Notify Surveillance Center enabled under each alarms settings in the control panel of the camera itself.

Hikvision NVRs

In case your Hikvision NVR does not communicate with the binding, make sure that:

  • ISAPI is enabled in the NVR settings.
  • ONVIF is enabled and a user/pass created that match the bindings.
  • RTSP is enabled.
  • Some NVR's allow each camera to be exposed on a set port to give direct access to each camera, some users report this works the best and needs to be enabled.

Some older versions of these NVRs require setting a different snapshot URL (snapshotUrl), as well as ffmpegInput. The older ones use the same URLs just with 'ISAPI' removed.

Thing ipcamera:hikvision:West "West Camera"
[
    ipAddress="192.168.0.XX",
    username="username",
    password="password",
    onvifPort=8000, //normally 80 check what it needs
    port=80,
    nvrChannel=4,
    serverPort=54324,
    ffmpegOutput="/etc/openhab2/html/cameras/camera-west/",
    ffmpegInput="rtsp://192.168.0.XX:554/ISAPI/Streaming/channels/401"
]

Instar

  • For MJPEG to work, you need to set the first sub-stream to be MJPEG format for the default settings to work, otherwise you can override the default with mjpegUrl with a valid URL for MJPEG streams.
  • Be sure to update to the latest firmware for your camera as Instar have made a lot of improvements recently, including adding MQTT features (MQTT is not needed for this binding to work).

Discovery

The discovery feature of openHAB can be used to find and setup any ONVIF cameras. This method should be preferred as it will discover the camera, ports and URLs for you, making the setup much easier. To use the discovery, just press the + icon located in the Inbox, then select the IpCamera binding from the list of installed bindings. If your camera is not found after a few searches, it may not be ONVIF and in this case you will need to manually add via the UI your camera as a generic thing type and provide the URLs manually.

Supported Things

If using openHAB's textual configuration, or when needing to setup HABpanel/sitemaps, you may need to know what your camera is as a "thing type".

Example: The thing type for a camera with no ONVIF support is "generic".

Thing Type ID Description
generic For any camera that is not ONVIF compatible, yet has working RTSP or HTTP URLs.
onvif Use for all ONVIF cameras that do not have an API.
amcrest Only use for if your Amcrest cameras wont work as a dahua thing. This uses an older polling based method for alarms that is not as efficient as the newer method used in dahua. Amcrest are made by Dahua and hence the API is similar.
dahua Use for all Dahua and Amcrest cameras that support the API.
doorbird Use for all current Doorbird cameras as they support an API as well as ONVIF.
foscam Use for all current Foscam HD cameras as they support an API as well as ONVIF.
hikvision Use for all current Hikvision cameras as they support an API as well as ONVIF.
instar Use for all current Instar cameras as they support an API as well as ONVIF.
group Used to display or cast multiple cameras like they are a single camera. This is an advanced feature that may require some tweaking of the cameras settings to fully work.

Thing Configuration

After a camera is added, the first step is to provide login details and a valid serverPort for your camera before it will come online. If your camera is not ONVIF/API based, you will also need to provide the binding with the cameras URLs to the relevant config field/s. For ONVIF cameras that auto detect the wrong URL, these same fields can be used to force a URL of your choosing but leaving them blank will allow the binding to find the URL for you.

NOTE: Leave any user:[email protected] out of any URLs, the binding will handle this for you. Not only does this hide your login details, it will also make changing your password much easier if it is only located in 1 field.

Below is a list of all configuration parameters (useful for textual config) with a short description. If you do not specify any of these, the binding will use the default which should work in most cases and should be tried first.

Parameter Description
ipAddress The IP address or host name of your camera.
port This port will be used for HTTP calls for fetching the snapshot and any API calls.
onvifPort The port your camera uses for ONVIF connections. This is needed for PTZ movement, events, and the auto discovery of RTSP and snapshot URLs.
serverPort The port that will serve the video streams and snapshots back to openHAB without authentication. You can choose any number, but it must be unique and unused for each camera that you setup. Setting the port to -1 (default), will turn all file serving off and some features will fail to work.
username Leave blank if your camera does not use login details.
password Leave blank if your camera does not use login details.
onvifMediaProfile 0 (default) is your cameras Mainstream and the numbers above 0 are the substreams. Any auto discovered URLs will use the streams that this indicates. You can always override the URLs should you wish to use something different for one of them.
pollTime Time in milliseconds between fetching a JPG. Note: Most features will not poll non stop and are done "on demand" to keep network traffic to a minimum. The exception is when using the GIF preroll feature, this will cause the camera to always fetch a snapshot every poll.
updateImageWhen The Image channel can be set to update in a number of ways to help reduce network traffic. Recommend that you DO NOT USE the image channel unless you use a very large pollTime.
0 - Default and the RECOMMENDED setting, the Image channel never updates.
1 - Update the Image channel only when the pollImage channel is turned on.
2 - Start of Motion Alarms will update the Image channel.
3 - Start of Audio Alarm will update the Image channel.
23 - Start of Motion and Audio Alarms will update the Image channel.
4 - During Motion Alarm the Image channel will update every poll until Alarm stops.
5 - During Audio Alarm the Image channel will update every poll until Alarm stops.
45 - During Motion and Audio Alarms the Image channel will update every poll until both alarms stop.
nvrChannel Set this to 1 (default) if it is a standalone camera, or to the input channel number of your NVR that the camera is connected to. This effects the hard coded URLs for the API based cameras.
snapshotUrl Leave this empty to auto detect the snapshot URL if the camera has ONVIF, or enter a HTTP address if you wish to override with a different address. Setting this to ffmpeg forces the camera to use FFmpeg to create the snapshots from the RTSP stream.
alarmInputUrl A URL you can use for the FFmpeg created Audio and Motion Alarms as they don't require high res feeds as they are not seen.
customMotionAlarmUrl Foscam only, for custom enable motion alarm use. More info found in Foscam's setup steps.
customAudioAlarmUrl Foscam only, for custom enable audio alarm use. More info found in Foscam's setup steps.
mjpegUrl A HTTP URL for MJPEG format streams. If you enter 'ffmpeg' the stream can be generated from the RTSP URL.
ffmpegInput Best if this stream is in H.264 format and can be RTSP or HTTP URLs. Leave this blank to use the auto detected RTSP address for ONVIF cameras.
ffmpegInputOptions Allows you to specify any options before the -i on the commands for FFmpeg. If you have a ESP32 camera that only has a mjpeg stream then make this equal -f mjpeg.
ffmpegLocation The full path including the filename for where you have installed FFmpeg. The default should work for most Linux installs but if using windows use this format: c:\ffmpeg\bin\ffmpeg.exe
ffmpegOutput The full path where FFmpeg has the ability to write files to ending with a slash. For windows use this format: c:\openhabconf\html\ipcamera\. If you would like to expose the GIF files to your static server, you can set it to /etc/openhab2/html/cameras/camera-name/
hlsOutOptions This gives you direct access to specify your own FFmpeg options to be used. Default: -strict -2 -f lavfi -i aevalsrc=0 -acodec aac -vcodec copy -hls_flags delete_segments -hls_time 2 -hls_list_size 4
gifOutOptions This gives you direct access to specify your own FFmpeg options to be used for animated GIF files. Default: -r 2 -filter_complex scale=-2:360:flags=lanczos,setpts=0.5*PTS,split[o1][o2];[o1]palettegen[p];[o2]fifo[o3];[o3][p]paletteuse
mjpegOptions Allows you to change the settings for creating a MJPEG stream from RTSP using FFmpeg. Possible reasons to change this would be to rotate or re-scale the picture from the camera, change the JPG compression for better quality or the FPS rate.
motionOptions This gives access to the FFmpeg parameters for detecting motion alarms from a RTSP stream. One possible use for this is to use the CROP feature to ignore any trees that move in the wind or a timecode stamp. Crop will not remove the trees from your picture, it only ignores the movement of the tree.
gifPreroll Store this many snapshots from BEFORE you trigger a GIF creation. Default: 0 will not use snapshots and will instead use a realtime stream from the ffmpegInput URL
gifPostroll How long in seconds to create a GIF from a stream. Alternatively if gifPreroll is set to value greater than 0, this is how many snapshots to use AFTER you trigger a GIF creation as snapshots occur at the poll rate.
ipWhitelist Enter any IPs inside brackets that you wish to allow to access the video stream. DISABLE the default value will turn this feature off. Example: ipWhitelist="(127.0.0.1)(192.168.0.99)"
ptzContinuous If set to false (default) the camera will move using Relative commands, If set to true the camera will instead use continuous movements and will require an OFF command to stop the movement.

Channels

Each camera brand will have different channels depending on how much of the support for an API has been added. The channels are kept consistent as much as possible from brand to brand to make upgrading to a different camera easier.

Channel Type Description
activateAlarmOutput Switch Toggles a cameras relay output 1.
activateAlarmOutput2 Switch Toggles a cameras relay output 2.
audioAlarm Switch (read only) When the camera detects noise above a threshold this switch will move to ON.
autoLED Switch When ON this sets a cameras IR LED to automatically turn on or off.
cellMotionAlarm Switch (read only) ONVIF cameras only will reflect the status of the ONVIF event of the same name.
doorBell Switch (read only) Doorbird only, will reflect the status of the doorbell button.
enableAudioAlarm Switch Allows the audio alarm to be turned ON or OFF.
enableExternalAlarmInput Switch Hikvision and Instar allow the Alarm input terminals to be disabled by this control.
enableFieldDetectionAlarm Switch Allows the field detection alarm to be turned ON or OFF. Some cameras will call this the Intrusion Alarm.
enableLED Switch Turn the IR LED ON or OFF. Some cameras have 3 states the LED can be in, so see the autoLED channel.
enableLineCrossingAlarm Switch Turns the line crossing alarm for API cameras, ON and OFF.
enableMotionAlarm Switch Turns the motion alarm ON and OFF for API cameras. This will not effect FFmpeg based alarms which have their own control.
enablePirAlarm Switch Turn PIR sensor ON or OFF.
externalAlarmInput Switch (read only) Reflects the status of the alarm input terminals on some cameras.
externalAlarmInput2 Switch (read only) Reflects the status of the alarm input 2 terminals on some cameras.
externalLight Switch Some cameras have a dedicated relay output for turning lights on and off with.
externalMotion Switch Can be used to inform the camera if it has motion in its view area. Handy if you own a PIR or any other kind of external sensor. If you use the autofps.mjpeg feature, this could increase the frame rate when a door that was closed is opened. Note: It will not be passed onto your camera and will not trigger any recordings.
faceDetected Switch (read only) When a camera detects a face (API cameras only) this switch will move to ON.
fieldDetectionAlarm Switch (read only) Reflects the cameras status for the field or intrusion alarm.
ffmpegMotionAlarm Switch (read only) The status of the FFmpeg based motion alarm.
ffmpegMotionControl Dimmer This control allows FFmpeg to detect movement from a RTSP or HTTP source and inform openHAB. The channel that will move is called ffmpegMotionAlarm.
gifHistory String The 50 most recent filenames the binding has used unless reset.
gifHistoryLength Number How many filenames are in the gifHistory.
gotoPreset String ONVIF cameras that can move only. Will cause the camera to move to a preset location.
hlsUrl String The URL for the ipcamera.m3u8 file.
imageUrl String The URL for the ipcamera.jpg file.
itemLeft Switch (read only) Will turn ON if an API camera detects an item has been left behind.
itemTaken Switch (read only) Will turn ON if an API camera detects an item has been stolen.
lastMotionType String Cameras with multiple alarm types will update this with which alarm last detected motion, i.e. a lineCrossing, faceDetection or item stolen alarm. You can also use this to create a timestamp of when the last motion was detected by creating a rule when this channel changes.
lineCrossingAlarm Switch (read only) Will turn on if the API camera detects motion has crossed a line.
mjpegUrl String The URL for the ipcamera.mjpeg stream.
motionAlarm Switch (read only) The status of the 'video motion' events in ONVIF and API cameras. Also see cellMotionAlarm as these can give different results.
mp4History String The 50 most recent filenames the binding has used unless reset.
mp4HistoryLength Number How many filenames are in the mp4History. Setting this to 0 will clear the history.
pan Dimmer Works with ONVIF cameras that can be moved.
parkingAlarm Switch (read only) When an API camera detects a car, this will turn ON.
pirAlarm Switch (read only) When a camera with PIR ability detects motion, this turns ON.
recordingGif Number (read only) How many seconds recording to GIF for. 0 when file ready.
recordingMp4 Number (read only) How many seconds recording to MP4 for. 0 when file ready.
rtspUrl String The URL for the cameras auto detected RTSP stream.
sceneChangeAlarm Switch (read only) When an API camera detects the camera has moved, this turns ON.
startStream Switch Starts the HLS files being created, if it not manually moved it will indicate if the files are being created on demand.
storageAlarm Switch (read only) When an ONVIF cameras storage is full and/or removed, this turns ON.
tamperAlarm Switch (read only) When an ONVIF cameras tamper switch is tripped, this turns ON.
textOverlay String Dahua, Instar and Hikvision can overlay any text you enter here over the video stream.
thresholdAudioAlarm Dimmer This channel can be linked to a Switch and a Slider. The value of the slider is the value in dB that is detected as noise/alarm down from digital full scale. Higher values are more sensitive and will trigger the alarm with quieter / less noise.
tilt Dimmer Works with ONVIF cameras that can be moved.
triggerExternalAlarmInput Switch Hikvision cameras can change if the alarm input terminal is ON when high or low. This can be used to manually cause an alarm input event to occur.
tooBlurryAlarm Switch (read only) ONVIF cameras only will reflect the status of the ONVIF event of the same name.
tooBrightAlarm Switch (read only) ONVIF cameras only will reflect the status of the ONVIF event of the same name.
tooDarkAlarm Switch (read only) ONVIF cameras only will reflect the status of the ONVIF event of the same name.
pollImage Switch This control can be used to manually start and stop using your CPU to create snapshots from a RTSP source. If you have a snapshot URL setup in the binding, only then can this control can be used to update the Image channel.
zoom Dimmer Works with ONVIF cameras that can be moved.

Moving PTZ Cameras

To move a camera with this binding you need an ONVIF camera that supports one of the following:

  • Absolute movements
  • Relative movements
  • Continuous movements
  • Presets

To test your cameras compatibility and also to create some preset locations, use a free program called ONVIF Device Manager (ODM for short). Not all ONVIF cameras work with all of the methods, so testing first to confirm what works is a good idea and the presets can not be created with the binding, only loaded after they are already created in a program like ODM. After creating new or changing existing presets, it is necessary to send the REFRESH command to the gotoPreset channel or you can restart the binding if that is easier. You can create names using the mappings feature of the selection element. See docs here https://www.openhab.org/docs/configuration/sitemaps.html#mappings

Moving the camera using Relative or Continuous (config ptzContinuous must be true) movements can be done by sending the INCREASE and DECREASE commands to the Pan, Tilt and Zoom channels. The OFF command (to any of the PTZ channels) will stop the cameras movements in the case of continuous being selected. When the config is set to false (the default if not specified) the binding will send relative movements. There are some widgets created in the HABpanel widget gallery that you can download and use right away saving you time if your camera supports either presets, relative or continuous modes.

For sitemaps, the below examples can be used.

item:


String BabyCamGotoPreset "Goto Preset" { channel="ipcamera:dahua:BabyCamera:gotoPreset" }
Dimmer BabyCamPan "Pan [%d] left/right" { channel="ipcamera:dahua:BabyCamera:pan" }
Dimmer BabyCamTilt "Tilt [%d] up/down" { channel="ipcamera:dahua:BabyCamera:tilt" }
Dimmer BabyCamZoom "Zoom [%d] in/out" { channel="ipcamera:dahua:BabyCamera:zoom" }

sitemap:


Selection item=BabyCamGotoPreset
Switch item=BabyCamPan mappings=[INCREASE="Left",OFF="STOP",DECREASE="Right"]
Switch item=BabyCamTilt mappings=[INCREASE="Down",OFF="STOP",DECREASE="Up"]
Switch item=BabyCamZoom mappings=[INCREASE="Zoom In",OFF="STOP",DECREASE="Zoom Out"]
Slider item=BabyCamPan icon=movecontrol
Slider item=BabyCamTilt icon=movecontrol
Slider item=BabyCamZoom icon=zoom

Moving the camera to an EXACT repeatable location (Preset 1 saved location) with a rule:

BabyCamGotoPreset.sendCommand(1)

Moving the camera to an EXACT repeatable location using Absolute movement with a rule:

BabyCamPan.sendCommand(22)
BabyCamTilt.sendCommand(60)
BabyCamZoom.sendCommand(0)

FFmpeg Motion and Audio Alarms

Any camera can use FFmpeg to create either a ffmpegMotionAlarm or audioAlarm. Before using this feature, consider if the https://www.openhab.org/addons/bindings/ftpupload/ is better used if your camera can upload to a FTP (binding can creates a virtual FTP so you don't need one). A Zwave or Zigbee PIR sensor is another way to save the CPU load this feature creates.

Even if your camera has a motion alarm, you may find that it does not provide enough flexibility to ignore moving trees, or have its sensitivity adjusted on the fly to reduce its sensitivity during rain. This is where this feature can come in handy, as you can add any of the many FFmpeg filters like crop as this wont effect the video feeds you watch. https://ffmpeg.org/ffmpeg-filters.html#Examples-52

To get this working:

  • Provide a URL to the bindings config alarmInputUrl or leave it blank to use the auto detected URL if your camera has ONVIF.
  • Install FFmpeg.
  • You have the resolution and FPS at realistic settings for your CPU. You need to reach 1.x speed otherwise the alarm will lag further behind realtime the longer you have this running. 1080p and 10 fps maximum for an ARM processor is probably a good place to start testing or even lower if you can.
  • Set the ffmpegMotionControl channel to 16 with a slider control and if the alarm stays on increase the value until it works as desired. If it will not trigger, lower the control until it does.
  • Set the ffmpegMotionControl to OFF or 0 and it stops using your CPU. You can link this same channel to BOTH a switch and a slider at the same time if you like to have both types of controls.
  • The output of the alarm will go to a channel called ffmpegMotionAlarm and you can use the lastMotionType channel to determine which alarm was last tripped if your camera has multiple alarm types.

audioAlarm

This works in the same way, just with different channels. If you setup a lower resolution URL in the config alarmInputUrl you need to ensure it contains audio otherwise this feature wont work. A value of 10 on a slider translates to -10dB below max volume (digital full scale) and when the audio goes above the -10dB threshold the alarm will turn ON.

Image / Snapshots

There are a number of ways to use snapshots with this binding.

Ways to use snapshots are:

  • Use the cameras URL so it passes from the camera directly to your end device. ie a tablet. This is always the best option if it works.
  • Request a snapshot with the URL http://192.168.xxx.xxx:54321/ipcamera.jpg. The IP is for your openHAB server not the camera, and 54321 is the serverPort number that you specified in the bindings setup. If you find the snapshot is old, you can set the gifPreroll to a number above 0 and this forces the camera to keep updating the stored JPG in RAM. The ipcamera.jpg can also be cast, as most cameras can not directly cast their snapshots.
  • Use the http://192.168.xxx.xxx:54321/snapshots.mjpeg to request a stream of snapshots to be delivered in MJPEG format. See the streaming section for more info.
  • Use the updateGif feature and use a gifPreroll value > 0. This creates a number of snapshots in the FFmpeg output folder called snapshotXXX.jpg where XXX starts at 0 and increases each pollTime. This allows you to get a snapshot from an exact amount of time before, on, or after triggering the GIF to be created. Handy for cameras which lag due to slow processors, or if you do not want a hand blocking the image when the door bell was pushed. These snapshots can be fetched either directly as they exist on disk, or via this URL format. http://192.168.xxx.xxx:54321/snapshot0.jpg
  • Also worth a mention is that you can off load cameras to a software package running on a separate server such as, Motion, Shinobi and Zoneminder.

See this forum thread for examples of how to use snapshots and streams in a sitemap. https://community.openhab.org/t/ip-camera-how-to-clickable-thumbnail-overview-in-sitemaps-that-opens-up-to-a-larger-view/77990

Video Streams

To get some of the video formats working, you need to install FFmpeg. Visit their site here to learn how https://ffmpeg.org/

Under Linux, FFmpeg can be installed very easily with this one command.

sudo apt update && sudo apt install ffmpeg

IMPORTANT: The binding has its own file server that works by allowing access to the snapshot and video streams with no user/password for requests that come from an IP located in the ipWhitelist. Requests from external IPs or internal requests that are not on the ipWhitelist will fail to get any answer. If you prefer to use your own firewall instead, you can also choose to make the ipWhitelist equal "DISABLE" (the default since the feature also needs a valid serverPort set) to turn this feature off and then all internal IPs will have access.

There are multiple ways to get a moving picture, to use them just enter the URL into any browser using http://192.168.xxx.xxx:serverPort/name.format replacing the name.format with one of the options that are listed below:

  • ipcamera.m3u8 HLS (HTTP Live Streaming) which uses H.264 compression. This can be used to cast to Chromecast devices, or can display video in many browsers (some browsers require a plugin to be installed). Please understand that this format due to the way it works will give you lag behind realtime, more on this below.
  • ipcamera.mjpeg whilst needing more bandwidth, it is far more compatible for displaying in a wider range of UIs and browsers. It is normally 1 second or less behind real-time. FFmpeg can be used to create this stream if your camera does not create one for you, but this uses more CPU. A lot of cameras limit the resolution in this format, so consider using HLS, autofps.mjpeg, or snapshots.mjpeg instead which will be in a higher resolution.
  • snapshots.mjpeg is a special MJPEG stream created from the cameras snapshots that are taken at the polling rate.
  • autofps.mjpeg This requires a camera that has a motion alarm to be turned on or it will only send a picture every 8 seconds. You can also use the externalMotion channel to change the framerate. This feature is designed to keep data traffic to your mobile devices as low as possible by automatically sending 1fps when motion is occurring, but only 1 picture every 8 seconds when the picture has no motion. The idea is to not send lots of pictures if the picture has not changed as doing so only eats up your data plan.
  • ipcamera.gif This is small in size and very compatible and handy to use in push notifications, Pushover, Telegram, or emails. You can cast it which can be handy to show a moving picture that keeps repeating on a Google/Nest home hub or your wall mounted tablet.
  • MP4 recordings can be created by the binding and FFmpeg, more on this below.

MJPEG Streams

Cameras that have built in MJPEG abilities can stream to openHAB with the MJPEG format with next to no CPU load, less than 1 second lag, and FFmpeg does not need to be installed. Cameras without this ability can still use this binding to convert their RTSP H.264 format to MJPEG (keep reading for more on this below) and this will take a lot of CPU power to handle the conversion. The alternative is to use HLS format which does not need the conversion and does not use any CPU to speak of. For video without a delay, you need MJPEG and without a camera that can create it, you will need to use a lot of CPU power. This can be done in a dedicated video server which will be the only way with lots of cameras, unless you purchase cameras that have the ability built in.

An alternative way to keep the CPU load low is to use the snapshots.mjpeg feature of the binding to create a stream from the cameras snapshots instead of the RTSP stream.

The main cameras that can do MJPEG with very low CPU load are Amcrest, Dahua, Hikvision, Foscam HD and Instar HD. To set this up, see Special Notes for Different Brands. The binding can then distribute this stream to many devices around your home whilst the camera only sees a single open stream.

To request the MJPEG stream from the binding, all you need to do is use this link changing the IP to that of your openHAB server and the serverPort to match the settings in the bindings setup for that camera.

http://openHABIP:serverPort/ipcamera.mjpeg

Creating MJPEG with FFmpeg

To use this feature, all you need to do is set the config mjpegUrl to contain "ffmpeg" to use your CPU to generate the MJPEG stream with FFmpeg. For cameras that have an API you can opt to not use the cameras stream and use FFmpeg instead should you run out of available streams.

FFmpeg may require you to lower the resolution and/or the FPS to lower the CPU load down enough to run, you may need to experiment. To change the settings used by this feature the binding exposes the config mjpegOptions which the default is currently -q:v 5 -r 2 -vf scale=640:-2 -update 1 where 5 is the JPG quality/compression setting, and -r 2 is how many frames per second to try and create. In this case it will create 2 frames every second. -vf scale=640:-2 will lower the resolution down to make the video 640 pixels wide. You can remove this to use the same resolution as the camera is set to use, however it may become a trade off and you may get less frames per second if you raise the resolution. Always try to get the default settings working first before you begin to experiment and if your stream is above 1080p and 10 frames per second, consider lowering it if you have issues on an ARM based server like a Raspberry PIx.

snapshots.mjpeg and autofps.mjpeg

These similar features allow you to request a MJPEG stream created by the binding with low CPU usage from the cameras snapshots. Snapshots are usually high resolution and look great, however they are limited to a max of 1 frame per second (1 FPS). The reason this is more useful than snapshots on their own, is some UIs will flash white or black when a snapshot is refreshing, this does not happen with snapshots.mjpeg and is the same bandwidth and CPU load as just using snapshots!

The autofps.mjpeg feature will display a snapshot that updates every 8 seconds to keep network traffic low, then when motion is detected it will automatically increase the frames to every second until the motion stops. This means lower traffic unless the picture is actually changing.

Request the stream to be sent to an item with this URL. NOTE: The IP is openHAB's not your cameras IP and the 54321 is what you have set as the serverPort.

http://192.168.xxx.xxx:54321/snapshots.mjpeg

Use the following to display it in your sitemap.

Video url="http://192.168.0.32:54321/autofps.mjpeg" encoding="mjpeg"

Video url="http://192.168.0.32:54321/snapshots.mjpeg" encoding="mjpeg"

HLS (HTTP Live Streaming)

HLS is a way of splitting the live stream up into small H.264 based files so it can be played in many browsers (some require addons to be installed) without using much CPU power as cameras generally are already in H.264 and this does not transcode the data. Because the files need to be created, this creates a lag/delay behind real time that can be reduced (more on that below).

The channel called 'startStream' can be used to create HLS files non stop and will remove the startup delay that comes with using this type of stream. The startup delay and the lag are two different things, with the startup delay easily solved by turning this channel ON. If the channel is OFF, the stream will start and stop automatically as required and the channel will reflect its current status. With a fast openHAB server it should only need to be requested once, but on slower ARM systems it takes a while for FFmpeg to get up and running at full speed.

It can be helpful sometimes to use this line in a rule to start the stream before it is needed further on in the rule sendHttpGetRequest("http://192.168.0.2:54321/ipcamera.m3u8") as the stream will stay running for 64 seconds. This 64 second delay before the stream is stopped helps when you are moving back and forth in a UI, as the stream does not keep stopping and needing to start each time you move around in a UI.

To use the HLS feature, you need to:

  • Ensure FFmpeg is installed.
  • For generic cameras, you will need to use the config ffmpegInput to provide a HTTP or RTSP URL.
  • Supply a folder that the openhab user has write permissions for to the config ffmpegOutput.
  • Set a valid serverPort as the default value of -1 will turn this feature off.
  • Consider using a SSD/HDD or a tmpfs (ram drive) can be used if you only have micro SD/flash based storage.

Ram Drive Setup

To create a tmpfs of 20mb at /tmpfs/ run this command to open the file for editing. Recommend using 20Mb per camera that uses this location although it could use less than half that amount if carefully streamlined for less ram. If using the FFmpeg -hls_wrap wrap option (causes issues for my Home Hub), you can get away with 5Mb per camera.

nano /etc/fstab

Enter and save this at the bottom of the file using ctrl X when done.

tmpfs /tmpfs tmpfs defaults,nosuid,nodev,noatime,size=20m 0 0

FFmpeg HLS Settings

Please get the default settings working first before playing with the advanced settings.

To get audio working you need to have the camera include audio in the stream and in a format that is supported by Chromecast or your browser. Only AAC is supported by Google/Nest if you are wanting to cast the stream with audio included. Then you need to change the HLS settings to what you need, some are suggestions are below.

Less delay behind realtime (no audio) if your cameras iFrames are 1 second apart (-hls_time 1):

-strict -2 -f lavfi -i aevalsrc=0 -acodec aac -vcodec copy -hls_flags delete_segments -hls_time 1 -hls_list_size 4

For cameras with no audio in the stream (default setting).

-strict -2 -f lavfi -i aevalsrc=0 -acodec aac -vcodec copy -hls_flags delete_segments -hls_time 2 -hls_list_size 4

For cameras with audio in the stream. Note: will break Chromecast if the camera does not send audio which is why this is not the default.

-strict -2 -acodec aac -vcodec copy -hls_flags delete_segments -hls_time 2 -hls_list_size 4

Some browsers require larger segment sizes to prevent choppy playback, this can be done with this setting to create 10 second segment files which increases the time before you can get playback working.

-strict -2 -f lavfi -i aevalsrc=0 -acodec aac -vcodec copy -hls_flags delete_segments -hls_time 10 -hls_list_size 4

HLS Sitemap Examples

The webview version allows you to zoom in on the video when using the iOS app, the Video element version does not zoom, but it will pass through myopenHAB.


Text label="HLS Video Stream" icon="camera"{Video url="http://192.168.1.9:54321/ipcamera.m3u8" encoding="hls"}

Text label="HLS Webview Stream" icon="camera"{Webview url="http://192.168.1.9:54321/ipcamera.m3u8" height=15}

Display multiple HLS streams side by side

In order to display camera hls streams side by side you can also create a webView item and link it to a HTML file in the conf/html directory as follows: The webView URL is that of your openHAB installation.

Webview url="http://192.168.6.4:8080/static/html/file.html" height=5

<!DOCTYPE html>
<html>
    <body>
        <div style="width: 50%; float: left;">
            <video playsinline autoplay muted controls style="width:100%; " src="http://192.168.6.4:50001/ipcamera.m3u8" />
        </div>
        <div style="width: 50%; float: left;">
            <video playsinline autoplay muted controls style="width: 100%; " src="http://192.168.6.4:50002/ipcamera.m3u8" />
        </div>
        <div style="width: 50%; float: left;">
            <video playsinline autoplay muted controls style="width:100%; " src="http://192.168.6.4:50003/ipcamera.m3u8" />
        </div>
        <div style="width: 50%; float: left;">
            <video playsinline autoplay muted controls style="width: 100%; " src="http://192.168.6.4:50004/ipcamera.m3u8" />
        </div>
    </body>
</html> 

How to Cast a Camera

There are two ways to cast a camera.

  1. openHAB Cloud Connector and using metadata/tags.
  2. Chromecast Bindings playuri channel.

The first method once setup allows you to ask "OK Google show X camera", or "OK Google show X camera on Y display". By optionally naming the display that you wish to use, it can be cast directly to your Chromecast (connected to your TV) by speaking to a Google Nest Mini. This must use the HLS format and use the metadata tag shown below with the openHAB Cloud Connector setup. Don't forget to ask Google to 'sync my devices' after adding the metadata. The synonyms in the tag allows Google to understand multiple names that the camera may be called by different people in your family.

Example of how this is done in an items file.

String FrontDoorCamHlsUrl "Front Door" { channel="ipcamera:ONVIF:FrontDoor:hlsUrl", synonyms="door bell, front camera", ga="Camera" [ protocols="hls" ] }

The second method is by using the Chromecast Binding and by sending the URL you wish to cast to the playuri channel. You can cast the ipcamera.jpg (static picture), ipcamera.gif (looping moving picture), and ipcamera.m3u8 (aka HLS) for a non stop stream that uses low CPU and can also contain audio.

Example:

items

String KitchenHomeHubPlayURI { channel="chromecast:chromecast:KitchenHomeHub:playuri" }

In a rule...

KitchenHomeHubPlayURI.sendCommand("http://192.168.1.2:54321/ipcamera.m3u8")

MP4 and GIF Recordings

You can use FFmpeg to recording to either GIF or MP4 format.

The steps to do this are:

  • Use the Action called recordMP4(String filename, int secondsToRecord) or recordGIF(String filename, int secondsToRecord) with the first argument being the filename you wish to use, and the second the time in seconds you wish to record for.
  • Once the file is created, the channel recordingMp4 or recordingGif will change itself back to 0, which can be used to trigger a rule to send/use the file which will appear in the ffmpegOutput folder.
  • The channel mp4History or gifHistory keeps a string of the last 50 filenames (comma separated values CSV) until you reset the history. If you use ipcamera as the filename, this stops the history from growing.
  • The channel mp4HistoryLength and gifHistoryLength keeps track of how many recordings were made since it was last reset. You can send the 0 command to this channel to clear the mp4History at the same time as setting this channel back to 0.
  • You can use the mp4OutOptions or gifOutOptions config's to apply any FFmpeg filters that you wish.

There is also a HABpanel Widget worth checking out that uses the history feature to display a list of recent recordings. https://community.openhab.org/t/custom-widget-camera-history-and-live-popup/103082

NOTE: If you are using a tmpfs folder, you will need to ensure you do not run out of space by moving the files with a rule.

GIF Preroll

There is also a config called gifPreroll to be aware of. When gifPreroll is 0 (the default) the binding will use the ffmpegInput stream to record from. By changing the gifPreroll to a value above 0, the binding will change to using snapshots as the source, preventing the need to have or open a RTSP stream. The time between the snapshots then becomes the pollTime of the camera (1 second by default) and can be raised if you desire. The snapshots are saved to disk and can be used as a feature that is described in the snapshot section.

You can request the GIF and MP4 by using this URL format, or by the direct path to where the file is stored:

http://openHAB.IP:serverPort/ipcamera.gif

.items


Number Doorbell_recordingGif "Update GIF" { channel="ipcamera:dahua:DoorCam:recordingGif" }

.rules

rule "Create front door camera GIF when front doorbell button pushed"
when
    Item FrontDoorbellButton changed to ON
then
    //Start creating the GIF
    getActions("ipcamera", "ipcamera:dahua:DoorCam").recordGIF("ipcamera",5)
    //Cast a doorbell sound using the Chromecast binding.
    KitchenHomeHubPlayURI.sendCommand("http://192.168.1.8:8080/static/doorbell.mp3")
end

rule "Send doorbell GIF via Pushover"
when
    Item Doorbell_recordingGif changed to 0
then
    sendPushoverMessage(pushoverBuilder("Sending GIF from backyard").withApiKey("dsfhghj6546fghfg").withUser("qwerty54657").withDevice("Phone1").withAttachment("/tmpfs/DoorCam/ipcamera.gif"))
end

HABpanel

This section is about how to get things working in HABpanel.

I highly recommend you check out the easy to use WIDGETS of which there are now 3 that are discussed on the forum here. https://community.openhab.org/t/custom-widget-camera-clickable-thumbnails-that-open-a-stream/101275

The widgets in the link above are the easiest way to get an advanced stream working in openHAB and you are welcome to open them up, look at how they work and change them to something even better that suits your needs.

Group Displays

The Full Example section shows how to setup a group of cameras to be displayed like they are a single camera.

Some additional things to check to get it working are:

  • If using the groups HLS feature, the poll time of the group must be the same or less than the total time contained in each cameras m3u8 file. If you have 3 seconds worth of video segments in each cameras HLS stream, this is the max you can set the poll time of the group to.
  • All cameras in a group should have the same HLS segment size setting, 1 and 2 second long segments have been tested to work.

This is still a very new feature and if you have any issues, please send some TRACE level log output of when the problem occurs.

Full Example

Use the following examples to base your setup on to save some time if you wish to use textual config. Textual config should only be used by advanced users as the Discovery method should be preferred by new users.

You can do a find and replace on the thing type from dahua, as all cameras use consistent naming of channels and configs so changing between them is easy.

In the examples you will see the format is: bindingID:thingType:UID [param1="string",param2=x,param3=x]

bindingID: is always ipcamera. thingType: is found listed above under Supported Things. UID: Can be made up but it must be UNIQUE, hence why it is called uniqueID.

openHAB's discovery method will use the IP address with the dots removed as the UID. By using textual config, you can name it something useful like "DrivewayCamera" if you wish, or stick with the same convention.

*.things


Thing ipcamera:group:OutsideCameras
[
    pollTime=2000, serverPort=54320, 
    ffmpegOutput="/tmpfs/OutsideGroup/",
    firstCamera="001",
    secondCamera="002",
    thirdCamera="TestCam",
    forthCamera="",
    motionChangesOrder=true
]

Thing ipcamera:dahua:001
[ 
    ipAddress="192.168.0.5", password="suitcase123456",
    username="admin",
    serverPort=54321,
    ffmpegOutput="/tmpfs/camera1/"
]

Thing ipcamera:hikvision:002
[
    ipAddress="192.168.0.6", password="suitcase123456",
    username="admin",
    serverPort=54322,
    ffmpegOutput="/tmpfs/camera2/"
]

Thing ipcamera:generic:TestCam
[
    ipAddress="192.168.0.7", password="pass123", username="admin", serverPort=54323,
    snapshotUrl="http://192.168.1.65/tmpfs/snap.jpg", //remove this line if your camera has none
    mjpegUrl="ffmpeg",
    ffmpegOutput="/tmpfs/HttpTest/", 
    ffmpegInput="rtsp://192.168.1.65:554/11"
]

Thing ipcamera:generic:TTGoCamera "ESP32 TTGo Camera" @ "Cameras"
[
    ipAddress="192.168.1.181",
    serverPort=51321,
    port=80,
    gifPreroll=1,
    gifPostroll=6,
    snapshotUrl="http://192.168.1.181/capture",
    mjpegUrl="http://192.168.1.181:81/stream",
    ffmpegOutput="/tmpfs/TTGoCamera/",
    ffmpegInput="http://192.168.1.181:81/stream",
    ffmpegInputOptions="-f mjpeg",
    ipWhitelist="(192.168.2.8)(192.168.2.83)(192.168.2.99)"
]

*.items


Number BabyCamDirection "Camera Direction"
Switch BabyCamEnableMotion "MotionAlarm on/off" { channel="ipcamera:dahua:001:enableMotionAlarm" }
Switch BabyCamMotionAlarm "Motion detected" { channel="ipcamera:dahua:001:motionAlarm" }
Switch BabyCamEnableAudioAlarm "AudioAlarm on/off" { channel="ipcamera:dahua:001:enableAudioAlarm" }
Switch BabyCamAudioAlarm "Audio detected" { channel="ipcamera:dahua:001:audioAlarm" }
Dimmer BabyCamAudioThreshold "Audio Threshold [%d]" { channel="ipcamera:dahua:001:thresholdAudioAlarm" }
Dimmer BabyCamLED "IR LED [%d]" { channel="ipcamera:dahua:001:enableLED" }
Switch BabyCamAutoLED "Auto IR LED" { channel="ipcamera:dahua:001:autoLED" }
String BabyCamTextOverlay "Text to overlay" { channel="ipcamera:dahua:001:textOverlay" }
String BabyCamHlsUrl "HLS Stream" { channel="ipcamera:dahua:BabyCamera:hlsUrl" }
DateTime BabyCamLastMotionTime "Time motion was last detected [%1$ta %1$tR]"
String BabyCamLastMotionType "Last Motion Type" { channel="ipcamera:dahua:BabyCamera:lastMotionType" }
Switch BabyCamStartHLS { channel="ipcamera:dahua:BabyCamera:startStream" }

Dimmer GenericMotionControl "Motion Threshold [%d]" { channel="ipcamera:generic:TestCam:ffmpegMotionControl" }
Switch GenericMotionAlarm "Motion detected" { channel="ipcamera:generic:TestCam:motionAlarm" }
Dimmer GenericAudioThreshold "Audio Threshold [%d]" { channel="ipcamera:generic:TestCam:thresholdAudioAlarm" }
Switch GenericAudioAlarm "Audio detected" { channel="ipcamera:generic:TestCam:audioAlarm" }

String OutsideCameraGroupHlsUrl "Outside Cameras" { channel="ipcamera:group:OutsideCameras:hlsUrl", ga="Camera" [ protocols="hls" ] }
Switch OutsideCameraGroupStartHLS "Start outside HLS" { channel="ipcamera:group:OutsideCameras:startStream" }

*.sitemap

Text label="Outside Camera Group" icon="camera"{Image url="http://192.168.0.2:54320/ipcamera.jpg" refresh=1000} 

    Text label="BabyMonitor" icon="camera"{
        Default item=BabyCamMotionAlarm icon=siren
        Default item=BabyCamAudioAlarm icon=siren
        Text label="Advanced Controls" icon="settings"{
            Switch item=BabyCamEnableMotion
            Default item=BabyCamEnableAudioAlarm
            Default item=BabyCamAudioThreshold icon=recorder
            Slider item=BabyCamLED
            Default item=BabyCamAutoLED
        }
        Text label="Last Movement" icon="motion"{
                    Webview url="http://192.168.0.2:54321/ipcamera.gif" height=9
                    Default item=BabyCamMotionAlarm icon=siren
                    Default item=BabyCamLastMotionTime
                    Default item=BabyCamLastMotionType
        }
            Text label="Cameras MJPEG Stream" icon="camera"{Video url="http://192.168.0.2:54321/ipcamera.mjpeg" encoding="mjpeg"}
            Text label="Snapshot 1FPS Stream" icon="camera"{Video url="http://192.168.0.2:54321/snapshots.mjpeg" encoding="mjpeg"}
            Text label="autofps Stream" icon="camera"{Video url="http://192.168.0.2:54321/autofps.mjpeg" encoding="mjpeg"}
            Text label="HLS Video Stream" icon="camera"{Video url="http://192.168.0.2:54321/ipcamera.m3u8" encoding="hls"}
            Text label="HLS Webview Stream" icon="camera"{Webview url="http://192.168.0.2:54321/ipcamera.m3u8" height=15}
            Text label="Image using JPG method" icon="camera"{Image url="http://192.168.0.2:54321/ipcamera.jpg" refresh=2000}        
    }
    
    Text label="Generic Camera" icon="camera"{
            Switch item=GenericMotionControl
            Slider item=GenericMotionControl
            Default item=GenericMotionAlarm
            Switch item=GenericAudioThreshold
            Slider item=GenericAudioThreshold          
            Default item=GenericAudioAlarm
            Text label="MJPEG Stream" icon="camera"{Video url="http://192.168.0.2:54323/ipcamera.mjpeg" encoding="mjpeg"}
            Text label="snapshots 1FPS Stream" icon="camera"{Video url="http://192.168.0.2:54323/snapshots.mjpeg" encoding="mjpeg"}
            Text label="autofps Stream" icon="camera"{Video url="http://192.168.0.2:54323/autofps.mjpeg" encoding="mjpeg"}
            Text label="HLS Video Stream" icon="camera"{Video url="http://192.168.0.2:54323/ipcamera.m3u8" encoding="hls"}
            Text label="HLS Stream" icon="camera"{Webview url="http://192.168.0.2:54323/ipcamera.m3u8" height=15}
            Text label="Image JPG method" icon="camera"{Image url="http://192.168.0.2:54323/ipcamera.jpg" refresh=1000}                
        }

*.rules

rule "Camera detected crying"
when
    Item BabyCamAudioAlarm changed from OFF to ON
then
if(BabyMonitor.state==ON){

    if(MumAlerts.state==ON){
    sendNotification("[email protected]", "Mum, the baby is awake.")
    }

    if(DadAlerts.state==ON){
    sendNotification("[email protected]", "Dad, the baby is awake.")
    }

    if(TvAlerts.state==ON){
    myKodi_notification.sendCommand("Baby is crying.")
    }
}
end

rule "Create time of last movement"
    when
    Item BabyCamLastMotionType received update
    then
    BabyCamLastMotionTime.postUpdate( new DateTimeType() )
end