This tutorial will show you how to send a video stream as a series of MJPEG frames. The technique used here is:

  • Serve the page as non-cacheable, and indicate content type is multipart/x-mixed-replace
  • Periodically send the content of a different JPEG file that replaces the former

Build and run

  • If you've not already done so, clone the Mongoose Library repo

    $ git clone https://github.com/cesanta/mongoose
  • Build and run the example

    $ cd mongoose/examples/video-stream
    $ make clean all
  • Go to http://localhost:8000 in your browser, you'll see an animation

  • If you have VLC media player installed, you can also get the frames from curl and pipe them to VLC, seeing the animation on a window

    $ curl localhost:8000/api/video1 | cvlc -

How it works

We'll concentrate here on those aspects related to sending the video stream, for the details of initializing and setting up an HTTP server please check the HTTP server tutorial.

  • When we get an HTTP request for the /api/video1 URI, we mark that connection and serve a header instructing the browser to avoid caching that content, and indicating that our response content type will be multipart/x-mixed-replace, then we set a fancy boundary marker that will serve to separate the frames
  • Then, periodically, we traverse all marked connections and send the boundary marker and a new image

Note the timer event handler gets a pointer to the event manager as its argument, we need it to traverse all connections and we configure that in the initialization section:

int main(void) {
  struct mg_mgr mgr;

  mg_timer_add(&mgr, 500, MG_TIMER_REPEAT, timer_callback, &mgr);

The more frequently you update images, the more realistic the animation will look; set the timer and event manager poll time accordingly. Take a look at the timers tutorial for more details on how to initialize and use a timer.

Browse latest code