[ipcamera] Fix null URL channels and fix multiple cameras use the same ffmpeg output folder. (#10846)

* Fix urls are null until binding restarts.


Signed-off-by: Matthew Skinner <matt@pcmus.com>

* Change to using port config.


Signed-off-by: Matthew Skinner <matt@pcmus.com>

* automate the ffmpeg output folder to follow the UID.


Signed-off-by: Matthew Skinner <matt@pcmus.com>

* spotless fixes.


Signed-off-by: Matthew Skinner <matt@pcmus.com>

* Update readme.


Signed-off-by: Matthew Skinner <matt@pcmus.com>

* change to using the userdata folder.


Signed-off-by: Matthew Skinner <matt@pcmus.com>

* change to better field description.


Signed-off-by: Matthew Skinner <matt@pcmus.com>

* Add advanced.


Signed-off-by: Matthew Skinner <matt@pcmus.com>

* Add link to docs.


Signed-off-by: Matthew Skinner <matt@pcmus.com>

* improve readme.

Signed-off-by: Matthew Skinner <matt@pcmus.com>

* improve example path in readme.


Signed-off-by: Matthew Skinner <matt@pcmus.com>

* Update bundles/org.openhab.binding.ipcamera/README.md

Cut and paste bandit strikes again. thanks.

Signed-off-by: Matthew Skinner <matt@pcmus.com>

Co-authored-by: Fabian Wolter <github@fabian-wolter.de>

* Change to using ipcamera as folder loc.

Signed-off-by: Matthew Skinner <matt@pcmus.com>

Co-authored-by: Fabian Wolter <github@fabian-wolter.de>
This commit is contained in:
Matthew Skinner 2021-06-16 07:50:00 +10:00 committed by GitHub
parent f506ec299b
commit f263c13c6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 66 additions and 38 deletions

View File

@ -115,7 +115,7 @@ Thing ipcamera:hikvision:West "West Camera"
port=80, port=80,
nvrChannel=4, nvrChannel=4,
serverPort=54324, serverPort=54324,
ffmpegOutput="/etc/openhab2/html/cameras/camera-west/", ffmpegOutput="/var/lib/openhab/ipcamera/West/",
ffmpegInput="rtsp://192.168.0.XX:554/ISAPI/Streaming/channels/401" ffmpegInput="rtsp://192.168.0.XX:554/ISAPI/Streaming/channels/401"
] ]
``` ```
@ -192,7 +192,7 @@ If you do not specify any of these, the binding will use the default which shoul
| `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. | | `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`. | | `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` | | `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/` | | `ffmpegOutput`| The full path to a unique folder (different for each camera) where FFmpeg has the ability to write files to ending with a slash. If you leave this blank, the binding will automatically use `$OPENHAB_USERDATA/ipcamera/UID`. See here for where this is located on your installation, <https://www.openhab.org/docs/installation/#getting-installation-info> |
| `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` | | `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` | | `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. | | `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. |
@ -485,8 +485,7 @@ To use the HLS feature, you need to:
+ Ensure FFmpeg is installed. + Ensure FFmpeg is installed.
+ For `generic` cameras, you will need to use the config `ffmpegInput` to provide a HTTP or RTSP URL. + 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 value of -1 will turn this feature off.
+ Set a valid `serverPort` as the default value of -1 will turn this feature off.
+ Consider using a SSD/HDD, zram location, or a tmpfs (ram drive) can be used if you only have micro SD/flash based storage. + Consider using a SSD/HDD, zram location, or a tmpfs (ram drive) can be used if you only have micro SD/flash based storage.
### Ram Drive Setup ### Ram Drive Setup

View File

@ -94,6 +94,10 @@ public class CameraConfig {
return ffmpegOutput; return ffmpegOutput;
} }
public void setFfmpegOutput(String path) {
ffmpegOutput = path;
}
public boolean getPtzContinuous() { public boolean getPtzContinuous() {
return ptzContinuous; return ptzContinuous;
} }

View File

@ -57,6 +57,7 @@ import org.openhab.binding.ipcamera.internal.IpCameraDynamicStateDescriptionProv
import org.openhab.binding.ipcamera.internal.MyNettyAuthHandler; import org.openhab.binding.ipcamera.internal.MyNettyAuthHandler;
import org.openhab.binding.ipcamera.internal.StreamServerHandler; import org.openhab.binding.ipcamera.internal.StreamServerHandler;
import org.openhab.binding.ipcamera.internal.onvif.OnvifConnection; import org.openhab.binding.ipcamera.internal.onvif.OnvifConnection;
import org.openhab.core.OpenHAB;
import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.IncreaseDecreaseType; import org.openhab.core.library.types.IncreaseDecreaseType;
import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OnOffType;
@ -467,7 +468,7 @@ public class IpCameraHandler extends BaseThingHandler {
String temp = longUrl; String temp = longUrl;
URL url; URL url;
if (longUrl.isEmpty() || longUrl.equals("ffmpeg")) { if (longUrl.isEmpty() || "ffmpeg".equals(longUrl)) {
return longUrl; return longUrl;
} }
@ -772,7 +773,7 @@ public class IpCameraHandler extends BaseThingHandler {
if (start) { if (start) {
if (mjpegChannelGroup.isEmpty()) {// first stream being requested. if (mjpegChannelGroup.isEmpty()) {// first stream being requested.
mjpegChannelGroup.add(ctx.channel()); mjpegChannelGroup.add(ctx.channel());
if (mjpegUri.isEmpty() || mjpegUri.equals("ffmpeg")) { if (mjpegUri.isEmpty() || "ffmpeg".equals(mjpegUri)) {
sendMjpegFirstPacket(ctx); sendMjpegFirstPacket(ctx);
setupFfmpegFormat(FFmpegFormat.MJPEG); setupFfmpegFormat(FFmpegFormat.MJPEG);
} else { } else {
@ -794,7 +795,7 @@ public class IpCameraHandler extends BaseThingHandler {
mjpegChannelGroup.remove(ctx.channel()); mjpegChannelGroup.remove(ctx.channel());
if (mjpegChannelGroup.isEmpty()) { if (mjpegChannelGroup.isEmpty()) {
logger.debug("All ipcamera.mjpeg streams have stopped."); logger.debug("All ipcamera.mjpeg streams have stopped.");
if (mjpegUri.equals("ffmpeg") || mjpegUri.isEmpty()) { if ("ffmpeg".equals(mjpegUri) || mjpegUri.isEmpty()) {
Ffmpeg localMjpeg = ffmpegMjpeg; Ffmpeg localMjpeg = ffmpegMjpeg;
if (localMjpeg != null) { if (localMjpeg != null) {
localMjpeg.stopConverting(); localMjpeg.stopConverting();
@ -979,7 +980,7 @@ public class IpCameraHandler extends BaseThingHandler {
localGIF.startConverting(); localGIF.startConverting();
if (gifHistory.isEmpty()) { if (gifHistory.isEmpty()) {
gifHistory = gifFilename; gifHistory = gifFilename;
} else if (!gifFilename.equals("ipcamera")) { } else if (!"ipcamera".equals(gifFilename)) {
gifHistory = gifFilename + "," + gifHistory; gifHistory = gifFilename + "," + gifHistory;
if (gifHistoryLength > 49) { if (gifHistoryLength > 49) {
int endIndex = gifHistory.lastIndexOf(","); int endIndex = gifHistory.lastIndexOf(",");
@ -1003,7 +1004,7 @@ public class IpCameraHandler extends BaseThingHandler {
localRecord.startConverting(); localRecord.startConverting();
if (mp4History.isEmpty()) { if (mp4History.isEmpty()) {
mp4History = mp4Filename; mp4History = mp4Filename;
} else if (!mp4Filename.equals("ipcamera")) { } else if (!"ipcamera".equals(mp4Filename)) {
mp4History = mp4Filename + "," + mp4History; mp4History = mp4Filename + "," + mp4History;
if (mp4HistoryLength > 49) { if (mp4HistoryLength > 49) {
int endIndex = mp4History.lastIndexOf(","); int endIndex = mp4History.lastIndexOf(",");
@ -1193,6 +1194,26 @@ public class IpCameraHandler extends BaseThingHandler {
onvifCamera.sendPTZRequest(OnvifConnection.RequestType.AbsoluteMove); onvifCamera.sendPTZRequest(OnvifConnection.RequestType.AbsoluteMove);
} }
@Override
public void channelLinked(ChannelUID channelUID) {
if (cameraConfig.getServerPort() > 0) {
switch (channelUID.getId()) {
case CHANNEL_MJPEG_URL:
updateState(CHANNEL_MJPEG_URL, new StringType(
"http://" + hostIp + ":" + cameraConfig.getServerPort() + "/ipcamera.mjpeg"));
break;
case CHANNEL_HLS_URL:
updateState(CHANNEL_HLS_URL,
new StringType("http://" + hostIp + ":" + cameraConfig.getServerPort() + "/ipcamera.m3u8"));
break;
case CHANNEL_IMAGE_URL:
updateState(CHANNEL_IMAGE_URL,
new StringType("http://" + hostIp + ":" + cameraConfig.getServerPort() + "/ipcamera.jpg"));
break;
}
}
}
@Override @Override
public void handleCommand(ChannelUID channelUID, Command command) { public void handleCommand(ChannelUID channelUID, Command command) {
if (command instanceof RefreshType) { if (command instanceof RefreshType) {
@ -1488,7 +1509,7 @@ public class IpCameraHandler extends BaseThingHandler {
if (rtspUri.isEmpty()) { if (rtspUri.isEmpty()) {
logger.warn("Binding has not been supplied with a FFmpeg Input URL, so some features will not work."); logger.warn("Binding has not been supplied with a FFmpeg Input URL, so some features will not work.");
} }
if (snapshotUri.isEmpty() || snapshotUri.equals("ffmpeg")) { if (snapshotUri.isEmpty() || "ffmpeg".equals(snapshotUri)) {
snapshotIsFfmpeg(); snapshotIsFfmpeg();
} else { } else {
sendHttpRequest("GET", snapshotUri, null); sendHttpRequest("GET", snapshotUri, null);
@ -1500,7 +1521,7 @@ public class IpCameraHandler extends BaseThingHandler {
cameraConfig.getOnvifPort()); cameraConfig.getOnvifPort());
onvifCamera.connect(thing.getThingTypeUID().getId().equals(ONVIF_THING)); onvifCamera.connect(thing.getThingTypeUID().getId().equals(ONVIF_THING));
} }
if (snapshotUri.equals("ffmpeg")) { if ("ffmpeg".equals(snapshotUri)) {
snapshotIsFfmpeg(); snapshotIsFfmpeg();
} else if (!snapshotUri.isEmpty()) { } else if (!snapshotUri.isEmpty()) {
sendHttpRequest("GET", snapshotUri, null); sendHttpRequest("GET", snapshotUri, null);
@ -1664,6 +1685,10 @@ public class IpCameraHandler extends BaseThingHandler {
snapshotUri = getCorrectUrlFormat(cameraConfig.getSnapshotUrl()); snapshotUri = getCorrectUrlFormat(cameraConfig.getSnapshotUrl());
mjpegUri = getCorrectUrlFormat(cameraConfig.getMjpegUrl()); mjpegUri = getCorrectUrlFormat(cameraConfig.getMjpegUrl());
rtspUri = cameraConfig.getFfmpegInput(); rtspUri = cameraConfig.getFfmpegInput();
if (cameraConfig.getFfmpegOutput().isEmpty()) {
cameraConfig
.setFfmpegOutput(OpenHAB.getUserDataFolder() + "/ipcamera/" + this.thing.getUID().getId() + "/");
}
if (cameraConfig.getServerPort() < 1) { if (cameraConfig.getServerPort() < 1) {
logger.warn( logger.warn(

View File

@ -76,10 +76,10 @@
<parameter name="ffmpegOutput" type="text" required="false" groupName="FFmpeg Setup"> <parameter name="ffmpegOutput" type="text" required="false" groupName="FFmpeg Setup">
<label>FFmpeg Output Folder</label> <label>FFmpeg Output Folder</label>
<description>The full path where FFmpeg has the ability to write files to ending with a slash. For windows use this <description>Leave this blank and the binding will use the openHAB userdata folder. Alternatively, a unique path for
format, c:\openhabconf\html\ipcamera\ each camera that ends with a slash and has write permissions can be entered.
</description> </description>
<default>/etc/openhab/html/camera1/</default> <advanced>true</advanced>
</parameter> </parameter>
<parameter name="serverPort" type="integer" required="true" min="-1" max="65535" groupName="Settings"> <parameter name="serverPort" type="integer" required="true" min="-1" max="65535" groupName="Settings">
@ -218,10 +218,10 @@
<parameter name="ffmpegOutput" type="text" required="false" groupName="FFmpeg Setup"> <parameter name="ffmpegOutput" type="text" required="false" groupName="FFmpeg Setup">
<label>FFmpeg Output Folder</label> <label>FFmpeg Output Folder</label>
<description>The full path where FFmpeg has the ability to write files to ending with a slash. For windows use this <description>Leave this blank and the binding will use the openHAB userdata folder. Alternatively, a unique path for
format, c:\openhabconf\html\ipcamera\ each camera that ends with a slash and has write permissions can be entered.
</description> </description>
<default>/etc/openhab/html/camera1/</default> <advanced>true</advanced>
</parameter> </parameter>
<parameter name="hlsOutOptions" type="text" required="false" groupName="FFmpeg Setup"> <parameter name="hlsOutOptions" type="text" required="false" groupName="FFmpeg Setup">
@ -447,10 +447,10 @@
<parameter name="ffmpegOutput" type="text" required="false" groupName="FFmpeg Setup"> <parameter name="ffmpegOutput" type="text" required="false" groupName="FFmpeg Setup">
<label>FFmpeg Output Folder</label> <label>FFmpeg Output Folder</label>
<description>The full path where FFmpeg has the ability to write files to ending with a slash. For windows use this <description>Leave this blank and the binding will use the openHAB userdata folder. Alternatively, a unique path for
format, c:\openhabconf\html\ipcamera\ each camera that ends with a slash and has write permissions can be entered.
</description> </description>
<default>/etc/openhab/html/camera1/</default> <advanced>true</advanced>
</parameter> </parameter>
<parameter name="hlsOutOptions" type="text" required="false" groupName="FFmpeg Setup"> <parameter name="hlsOutOptions" type="text" required="false" groupName="FFmpeg Setup">
@ -699,10 +699,10 @@
<parameter name="ffmpegOutput" type="text" required="false" groupName="FFmpeg Setup"> <parameter name="ffmpegOutput" type="text" required="false" groupName="FFmpeg Setup">
<label>FFmpeg Output Folder</label> <label>FFmpeg Output Folder</label>
<description>The full path where FFmpeg has the ability to write files to ending with a slash. For windows use this <description>Leave this blank and the binding will use the openHAB userdata folder. Alternatively, a unique path for
format, c:\openhabconf\html\ipcamera\ each camera that ends with a slash and has write permissions can be entered.
</description> </description>
<default>/etc/openhab/html/camera1/</default> <advanced>true</advanced>
</parameter> </parameter>
<parameter name="hlsOutOptions" type="text" required="false" groupName="FFmpeg Setup"> <parameter name="hlsOutOptions" type="text" required="false" groupName="FFmpeg Setup">
@ -997,10 +997,10 @@
<parameter name="ffmpegOutput" type="text" required="false" groupName="FFmpeg Setup"> <parameter name="ffmpegOutput" type="text" required="false" groupName="FFmpeg Setup">
<label>FFmpeg Output Folder</label> <label>FFmpeg Output Folder</label>
<description>The full path where FFmpeg has the ability to write files to ending with a slash. For windows use this <description>Leave this blank and the binding will use the openHAB userdata folder. Alternatively, a unique path for
format, c:\openhabconf\html\ipcamera\ each camera that ends with a slash and has write permissions can be entered.
</description> </description>
<default>/etc/openhab/html/camera1/</default> <advanced>true</advanced>
</parameter> </parameter>
<parameter name="hlsOutOptions" type="text" required="false" groupName="FFmpeg Setup"> <parameter name="hlsOutOptions" type="text" required="false" groupName="FFmpeg Setup">
@ -1271,10 +1271,10 @@
<parameter name="ffmpegOutput" type="text" required="false" groupName="FFmpeg Setup"> <parameter name="ffmpegOutput" type="text" required="false" groupName="FFmpeg Setup">
<label>FFmpeg Output Folder</label> <label>FFmpeg Output Folder</label>
<description>The full path where FFmpeg has the ability to write files to ending with a slash. For windows use this <description>Leave this blank and the binding will use the openHAB userdata folder. Alternatively, a unique path for
format, c:\openhabconf\html\ipcamera\ each camera that ends with a slash and has write permissions can be entered.
</description> </description>
<default>/etc/openhab/html/camera1/</default> <advanced>true</advanced>
</parameter> </parameter>
<parameter name="hlsOutOptions" type="text" required="false" groupName="FFmpeg Setup"> <parameter name="hlsOutOptions" type="text" required="false" groupName="FFmpeg Setup">
@ -1542,10 +1542,10 @@
<parameter name="ffmpegOutput" type="text" required="false" groupName="FFmpeg Setup"> <parameter name="ffmpegOutput" type="text" required="false" groupName="FFmpeg Setup">
<label>FFmpeg Output Folder</label> <label>FFmpeg Output Folder</label>
<description>The full path where FFmpeg has the ability to write files to ending with a slash. For windows use this <description>Leave this blank and the binding will use the openHAB userdata folder. Alternatively, a unique path for
format, c:\openhabconf\html\ipcamera\ each camera that ends with a slash and has write permissions can be entered.
</description> </description>
<default>/etc/openhab/html/camera1/</default> <advanced>true</advanced>
</parameter> </parameter>
<parameter name="hlsOutOptions" type="text" required="false" groupName="FFmpeg Setup"> <parameter name="hlsOutOptions" type="text" required="false" groupName="FFmpeg Setup">
@ -1838,10 +1838,10 @@
<parameter name="ffmpegOutput" type="text" required="false" groupName="FFmpeg Setup"> <parameter name="ffmpegOutput" type="text" required="false" groupName="FFmpeg Setup">
<label>FFmpeg Output Folder</label> <label>FFmpeg Output Folder</label>
<description>The full path where FFmpeg has the ability to write files to ending with a slash. For windows use this <description>Leave this blank and the binding will use the openHAB userdata folder. Alternatively, a unique path for
format, c:\openhabconf\html\ipcamera\ each camera that ends with a slash and has write permissions can be entered.
</description> </description>
<default>/etc/openhab/html/camera1/</default> <advanced>true</advanced>
</parameter> </parameter>
<parameter name="hlsOutOptions" type="text" required="false" groupName="FFmpeg Setup"> <parameter name="hlsOutOptions" type="text" required="false" groupName="FFmpeg Setup">
@ -2121,10 +2121,10 @@
<parameter name="ffmpegOutput" type="text" required="false" groupName="FFmpeg Setup"> <parameter name="ffmpegOutput" type="text" required="false" groupName="FFmpeg Setup">
<label>FFmpeg Output Folder</label> <label>FFmpeg Output Folder</label>
<description>The full path where FFmpeg has the ability to write files to ending with a slash. For windows use this <description>Leave this blank and the binding will use the openHAB userdata folder. Alternatively, a unique path for
format, c:\openhabconf\html\ipcamera\ each camera that ends with a slash and has write permissions can be entered.
</description> </description>
<default>/etc/openhab/html/camera1/</default> <advanced>true</advanced>
</parameter> </parameter>
<parameter name="hlsOutOptions" type="text" required="false" groupName="FFmpeg Setup"> <parameter name="hlsOutOptions" type="text" required="false" groupName="FFmpeg Setup">