How to convert rtsp stream to mjpeg (http) using ffmpeg

Viewed 4863

I wish to capture an rtsp stream and convert it to an mjpeg (over http) stream using ffmpeg. I am running Ubuntu 20. I have searched and searched for the solution, and mostly find:

a) solutions requiring ffserver (deprecated)

b) solutions converting from mjpeg to rtsp

c) solutions converting from rtsp to hls (nginx, wowza, etc...) which doesn't work in my application. I need http output as mjpeg.

d) vlc - which does work but requires way too much of my available processor (80%)

e) rtsp2mjpg - github project which I installed, but could not get to work and can't get any support.

I am not an ffmpeg expert, so if someone could step me through an ffmpeg solution to this, if it exists, I'd really appreciate it.

2 Answers

I've very recently solved this myself, after finding the exact same things as you. The two parts are you need are (1) ffmpeg conversion in a script, and (2) something like lighttpd+cgibin or nginix+fastcgi to serve it over http/https. I don't expect you'll be able to do much better in terms of CPU use than vlc, though.

This bash script will do the ffmpeg conversion to MJPEG, and send the output to stdout. Put this in lighttpd's cgi-bin folder (/var/www/cgi-bin for me). Call it something like "webcamstream", and adjust the rtsp:// URL to suit your camera:

#!/bin/bash

echo "Content-Type: multipart/x-mixed-replace;boundary=ffmpeg"
echo "Cache-Control: no-cache"
echo ""
ffmpeg -i "rtsp://192.168.60.13:554/user=admin&password=SECRET&channel=1&stream=0.sdp" -c:v mjpeg -q:v 1 -f mpjpeg -an -

Enable cgi-bin for lighttpd:

ln -s /etc/lighttpd/conf-available/10-cgi.conf /etc/lighttpd/conf-enabled/10-cgi.conf

..and then adjust lighttp's cgi-bin configuration (/etc/lighttpd/conf-enabled/10-cgi.conf) as shown below. The stream-response-body setting is important, as it'll both stop the stream when the client disconnects, and also avoid having lighttpd try to buffer the entire infinite stream before sending anything to the client.

server.modules += ( "mod_cgi" )

$HTTP["url"] =~ "^/cgi-bin/" {
        server.stream-response-body = 2
        cgi.assign = ( "" => "" )
        alias.url += ( "/cgi-bin/" => "/var/www/cgi-bin/" )
}

Make the cgi-bin script executable and restart lighttpd:

chmod +x /var/www/cgi-bin/webcamstream
systemctl restart lighttpd

...and that should be it. You can then access the MJPEG stream at a URL like this, where the last part is your script's name:

http://serveraddress/cgi-bin/webcamstream

I've written it up in more detail here: Converting RTSP to HTTP on demand

As far as I can tell, you can't avoid taking the CPU hit of the conversion -- the format/encoding of RTSP vs. MJPEG frames are different. I reduced my CPU load by configuring the camera to reduce the source's framerate and resolution until it was an acceptable load on ffmpeg. You can change the resolution and framerate with ffmpeg arguments as well, but it would still have to decode the full frames first and do the work of resizing.

The paths above are on Debian, so you may need to adjust them to suit your Ubuntu system.

Convert RTSP to MJPEG via FFSERVER

ffmpeg download:

https://ffmpeg.org/releases/

choose old version before 3.4(since this version FFSERVER WAS REMOVED), recommand to use 3.2.16

Compile

./configure --prefix=/u/tool/ffserver
make && make install

FFSERVER

cd /u/tool/ffserver/bin

edit {ffserver.conf}

HTTPPort 8090
HTTPBindAddress 0.0.0.0
MaxHTTPConnections 2000
MaxClients 1000
MaxBandwidth 10000

<Feed feed.ffm>
File /tmp/feed.ffm
FileMaxSize 50M
</Feed>

<Stream live.mjpeg>
Feed feed.ffm
Format mpjpeg
VideoFrameRate 5
VideoIntraOnly
VideoSize 720x405
VideoQMin 5
VideoQMax 20
NoAudio
Strict -1
NoDefaults
</Stream>

<Stream still.jpg>
Feed feed.ffm
Format jpeg
VideoFrameRate 2
VideoSize 720x404
VideoQMin 1
VideoQMax 15
VideoIntraOnly
NoAudio
Strict -1
NoDefaults
</Stream>

Run FFSERVER

./ffserver -f ./ffserver.conf

pixel err

1280x720 == 720x405

if you use VideoSize 720x405,startup error message shows:

ffserver.conf "Image size is not a multiple of 2"

fix 405 to 404.

FEED STREAMING

ffmpeg feed, DO NOT USE SYSTEM BUILD FFMPEG!! CAUSE AFTER VERSION 3.4, IT WAS REMOVED!

use the ffmpeg you just compiled same directory with ffserver.

./ffmpeg -rtsp_transport tcp -i "rtsp://127.0.0.1:8554/000FFC52F1D3" -r 15 -an http://127.0.0.1:8090/feed.ffm

Browse mjpeg:

http://192.168.1.17:8090/live.mjpeg

Browse snap image:

http://192.168.1.17:8090/still.jpg

mjpeg status

http://localhost/tool/mjpeg.htm

Prevent RTSP stopped broke mjpeg image updating,loop update image path in JS every N seconds(ig: 15):

setInterval(function() {
    var myImg = $('#myJpeg').attr('src', "http://192.168.1.17:8090/live.mjpeg?rand=" + Math.random()); 
}, 15000);

run server

ffserver -f /etc/ffserver.conf

run debug mode

ffserver -d -f /etc/ffserver.conf

If your want to run FFMPEG in console background, try to use -nostdin to FFMPEG or run in terminal multiplexer like SCREEN or TMUX.

Related