skip to Main Content

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


  1. 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.

    Login or Signup to reply.
  2. 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

    1280×720 == 720×405

    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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search