kerberos-io / machinery

(DEPRECATED) An open source image processing framework, which uses your USB-, IP- or RPi-camera to recognize events (e.g. motion).
https://www.kerberos.io
490 stars 104 forks source link

Can't open IP camera url (probably because of audio codec?) nor set custom ffmpeg flags #189

Open lahdekorpi opened 5 years ago

lahdekorpi commented 5 years ago

Running a couple of Docker images (Machinery 2.6.2). The others work fine, but one of my IP cameras does not. It does, however, work just fine with VLC on my local machine, ffprobe outputs (from inside the container):

ffprobe version n2.8.14-1-g26755a8 Copyright (c) 2007-2018 the FFmpeg developers
  built with gcc 4.8 (Ubuntu 4.8.4-2ubuntu1~14.04.4)
  configuration: --enable-gpl --enable-libx264
  libavutil      54. 31.100 / 54. 31.100
  libavcodec     56. 60.100 / 56. 60.100
  libavformat    56. 40.101 / 56. 40.101
  libavdevice    56.  4.100 / 56.  4.100
  libavfilter     5. 40.101 /  5. 40.101
  libswscale      3.  1.101 /  3.  1.101
  libswresample   1.  2.101 /  1.  2.101
  libpostproc    53.  3.100 / 53.  3.100
Input #0, rtsp, from 'rtsp://admin:mycoolpassword@mycamera.cameras.mysecretdomain.fi/onvif1':
  Metadata:
    title           : H.264 Video, RtspServer_0.0.0.2
  Duration: N/A, start: 0.000000, bitrate: N/A
    Stream #0:0: Video: h264 (Main), yuv420p, 1280x960, 15 fps, 15.15 tbr, 90k tbn, 30 tbc
    Stream #0:1: Audio: pcm_alaw, 8000 Hz, 1 channels, s16, 64 kb/s

While running (in the container):

ffmpeg -i rtsp://admin:mycoolpassword@mycamera.cameras.mysecretdomain.fi/onvif1 capture-test.mp4 FAILs with the output:

[aac @ 0x1f8e960] The encoder 'aac' is experimental but experimental codecs are not enabled, add '-strict -2' if you want to use it.

Running with -strict -2 works just fine and writes to the test mp4 file.

If I understood correctly, ffmpeg is executed from src/kerberos/machinery/io/IoVideo.cpp:846 in master where the flags are passed in, but I could not find any lines where any user selected options would be passed to the command. Is this possible?
Guessing by the aac error that passing the -strict -2 would also solve the problem with this camera but generally speaking; having the ability to set ffmpeg flags would be a nice addition.

lahdekorpi commented 5 years ago

Oh, the IoVideo is just for the output and not the actual capture. The capture is not happening via the ffmpeg binary at all but instead the cv::VideoCapture of OpenCV?

Just tried replacing the binary with a simple bash script to inject the -strict -2 without any effect as the ffmpeg binary is not even called.

Just in case anyone is interested:

#!/bin/bash
args=( "$@" )
ffmpeg-original ${args[@]::${#args[@]}-1} -strict -2 ${args[$(expr ${#args[@]} - 1)]}
lahdekorpi commented 5 years ago

Are there any options to debug the OpenCV capture?

14/02/2019 16:39:29.377 ERROR [trivial] OpenCV : can't open url of ip camera

isn't all that helpful...

lahdekorpi commented 5 years ago

Looking at OpenCV directly, I wrote an isolated test script that simply calls the cv:VideoCapture with the same URL but am getting this:

[rtsp @ 0x7ffcf8006800] Nonmatching transport in server reply

Setting OPENCV_FFMPEG_CAPTURE_OPTIONS to "rtsp_transport;udp" however solves this and the video works just fine on the test script.

lahdekorpi commented 5 years ago

This is most likely related to #186 We may have the same camera. It is only UDP and has the RTSP path of onvif.

Adding an option to set the RTSP transport or alternatively do as ffmpeg (cli) does it (tried TCP first) would probably be a good addition. This should be fairly easy to add.

setenv("OPENCV_FFMPEG_CAPTURE_OPTIONS", "rtsp_transport;udp", 1);

This should probably work?

lahdekorpi commented 5 years ago

After compiling with the setenv (and trying it out just by setting as os env variable), I'm still getting:

[rtsp @ 0x3599540] Nonmatching transport in server reply
cedricve commented 5 years ago

hey @lahdekorpi, sorry for the ignorance any chance you found out ?

lahdekorpi commented 5 years ago

I still have no idea what is causing this since testing with just a simple Python script and rtsp_transport;udp, it works perfectly.

I switched to using live555 RTSP proxy between machninery and the camera.

cedricve commented 5 years ago

hey @lahdekorpi cool and it's working now? how does that looks like from an architecture point of view?

lahdekorpi commented 5 years ago

From an architecture point of view, integrating this to machinery wouldn't probably make much sense, given the fact that there is no actual reason why OpenCV shouldn't and couldn't be able to handle streams if it is configured properly. The original issue here seems to be that we need an option to switch between TCP and UDP. I think adding this would just add additional overhead to the container. Maybe an optional "enable RTSP proxy layer" option, that starts a live555 RTSP proxy daemon on the same container and binds to localhost would be ok(?)

That being said, a separate container is a good option in my opinion. Like in my case; it is connecting to all the different cameras and then providing one stream server (with multiple streams) that can be consumed by multiple Kerberos containers.

In my case, this adds one more isolation level to the network. My crappy IP cameras are on their own network without access to the outside world, and the container with the RTSP is the only thing accessing said network, not even the Kerberos containers.