scottlamb / moonfire-nvr

Moonfire NVR, a security camera network video recorder
Other
1.19k stars 138 forks source link

Best practice for non-rtsp-cameras + unstable stream to rtsp-simple-server #234

Closed hn closed 1 year ago

hn commented 1 year ago

Sometimes it is not possible to run Moonfire NVR with RTSP cameras only. I describe here how I connected a MJPEG camera:

  1. Install rtsp-simple-server, which is conveniently available as a Docker container. But since a format change of the video stream is necessary, FFMPEG must be added as described here.

  2. Edit rtsp-simple-server.yml and add something similiar to this at the end of the file (line breaks within the ffmpeg command included here for better readability, you have to remove them):

~^(garagedoor)_main:
  runOnDemand: ffmpeg -re -f mjpeg -use_wallclock_as_timestamps 1
    -i http://user:pass@10.0.0.123:8080/?action=stream -vsync passthrough
    -filter_complex '[0:v]split=2[inM][inS];[inM]setpts=PTS-STARTPTS[outM];[inS]setpts=PTS-STARTPTS,scale=640:-1[outS]'
    -map '[outM]' -pix_fmt yuv420p -vcodec h264_v4l2m2m -b:v 5M -num_output_buffers 32 -num_capture_buffers 16 -f rtsp rtsp://localhost:$RTSP_PORT/$G1_main
    -map '[outS]' -pix_fmt yuv420p -vcodec h264_v4l2m2m -b:v 2M -f rtsp rtsp://localhost:$RTSP_PORT/$G1_sub
  runOnDemandRestart: yes
  runOnDemandCloseAfter: 120s

This config is a little bit hacky (you might call it clever) as it publishes the _main and _sub stream from within one FFMPEG invocation.

The above snippet is valid for a Raspberry Pi 3B+ and 4 (-vcodec h264_v4l2m2m hardware accelerated codec, you'll need to start the Docker container with --device /dev/video11:/dev/video11). Otherwise you have to use something like this:

    -map '[outM]' -vcodec libx264 -tune zerolatency -preset ultrafast -f rtsp rtsp://localhost:$RTSP_PORT/$G1_main
    -map '[outS]' -vcodec libx264 -tune zerolatency -preset ultrafast -f rtsp rtsp://localhost:$RTSP_PORT/$G1_sub
  1. Configure Moonfire NVR to read camera streams from rtsp://rtsp-ss:8554/garagdoor_main and rtsp://rtsp-ss:8554/garagdoor_sub (provided you started the rtsp-ss Docker container with --name="rtsp-ss" within the same Docker network).

In principle, everything runs as expected, but the stream keeps interrupting:

Describe the bug With rtsp-simple-server as stream source, both streams tear down roughly every 20-50 seconds.

To Reproduce Steps to reproduce the behavior:

  1. See above instructions. Problem does not depend on MJPEG camera stream as source, even with a random static movie file the stream interrupts.

Expected behavior The streams are not interrupted (except for the normal hourly rotation).

Screenshots If applicable, add screenshots to help explain your problem.

With tcpdump src moonfire and dst rtsp-ss one can see that after 20-50 seconds Moonfire issues a SET_PARAMETER which immidiately is followed by a TEARDOWN:

13:57:31.262941 RTSP: DESCRIBE rtsp://rtsp-ss:8554/garagedoor_main RTSP/1.0
13:57:31.265239 RTSP: SETUP rtsp://rtsp-ss:8554/garagedoor_main/trackID=0 RTSP/1.0
13:57:31.267365 RTSP: PLAY rtsp://rtsp-ss:8554/garagedoor_main RTSP/1.0
13:58:01.270315 RTSP: SET_PARAMETER rtsp://rtsp-ss:8554/garagedoor_main/ RTSP/1.0
13:58:01.272617 RTSP: TEARDOWN rtsp://rtsp-ss:8554/garagedoor_main/ RTSP/1.0

I am unsure if the SET_PARAMETER command is the cause or just a accompanying symptom of the TEARDOWN. After teardown, Moonfire automatically reconnects and PLAYs the stream again.

scottlamb commented 1 year ago

Thanks for the rtsp-simple-server instructions. I'm on a family vacation and so may not have a chance to try them out right away.

SET_PARAMETER is Moonfire's way of doing keepalives, every 30 seconds. The code is here:

https://github.com/scottlamb/retina/blob/bb3baf03295c1b74651a1db79ef374b51bab9178/src/client/mod.rs#L1910

Given the timing you observed, I imagine the TEARDOWN happened because something went wrong with the keepalive. I'm not sure exactly what, though. A couple ways to get more information:

hn commented 1 year ago

Based on the rtsp-simple-server logs

06:32:56 INF [RTSP] [conn 172.18.0.2:59514] opened
06:32:57 INF [RTSP] [session 874954654] created by 172.18.0.2:59514
06:32:57 INF [RTSP] [session 874954654] is reading from path 'garagedoor_main', 1 track with UDP
06:33:27 INF [RTSP] [conn 172.18.0.2:59514] closed (unhandled request: SET_PARAMETER rtsp://rtsp-ss:8554/garagedoor_main/)
06:33:27 INF [RTSP] [session 874954654] destroyed (teared down by 172.18.0.2:59522)

it looks as if the request is not handled at all (SET_PARAMETER support is missing within rtsp-simple-server?). I don't know if SET_PARAMETER is a mandatory part of the RTSP protocol, this would be to discuss. Maybe I need to open an issue at @aler9 / rtsp-simple-server.

Update: From the related disussion in https://github.com/aler9/rtsp-simple-server/issues/842 I increased the log level:

08:14:51 DEB [RTSP] [conn 172.18.0.2:32848] [c->s] SET_PARAMETER rtsp://rtsp-ss:8554/garagedoor_main/ RTSP/1.0
CSeq: 4
Session: 3130046022
User-Agent: Moonfire NVR 0.7.4

08:14:51 DEB [RTSP] [conn 172.18.0.2:32848] [s->c] RTSP/1.0 400 Bad Request
CSeq: 4
Server: gortsplib

08:14:51 INF [RTSP] [conn 172.18.0.2:32848] closed (unhandled request: SET_PARAMETER rtsp://rtsp-ss:8554/garagedoor_main/)
08:14:51 INF [RTSP] [conn 172.18.0.2:32854] opened
08:14:51 DEB [RTSP] [conn 172.18.0.2:32854] [c->s] TEARDOWN rtsp://rtsp-ss:8554/garagedoor_main/ RTSP/1.0
CSeq: 1
Session: 3130046022
User-Agent: Moonfire NVR 0.7.4

08:14:51 DEB [RTSP] [conn 172.18.0.2:32854] [s->c] RTSP/1.0 200 OK
CSeq: 1
Server: gortsplib

08:14:51 INF [RTSP] [session 778887791] destroyed (teared down by 172.18.0.2:32854)
08:14:51 INF [RTSP] [conn 172.18.0.2:32854] closed (EOF)

First oberservations:

scottlamb commented 1 year ago

Moonfire doesn't care if the SET_PARAMETER succeeds or fails, just that there is a response. Is the server also closing the RTSP connection? That's more of a problem. If you're using the default TCP transport (a.k.a. RTP/RTCP over RTSP interleaved channels), there's no way to recover from this. If you're using UDP, Moonfire could handle this more gracefully, but doesn't right now.

aler9 commented 1 year ago

Please read here https://github.com/aler9/rtsp-simple-server/issues/1066#issuecomment-1206204490

scottlamb commented 1 year ago

I just committed a change to Retina that makes it work with the latest rtsp-simple-server release (v0.19.3). I haven't made a Retina release yet / updated Moonfire to use it.

scottlamb commented 1 year ago

I just released Retina 0.4.1 and am about to add a Moonfire commit that uses it and marks this issue as fixed, meaning Moonfire built as of that commit should work well with rtsp-simple-server.

As for your instructions on how to use non-RTSP cameras: they'd be quite welcome on the wiki. That's where I put (and encourage others to put) anything broader than instructions for how to use a particular version of Moonfire.