Posts

Streaming mjpeg video with a web2py and python server

Recently I investigated whether I could implement software streaming of mjpeg video on a camera that uses web2py and python as its HTTP interface. Web2py makes most common operations quite straightforward and streaming is no exception, although I had to go digging for some details, this post along with SergeyPo’s answer to this question were of immense help.

mjpeg or Motion JPEG streaming over HTTP is a popular way of streaming video from IP cameras. If your camera has already gone to the effort of jpeg’ing its frames then it is reasonably cheap to stream them out via software over HTTP as an mjpeg video stream (as opposed to encoding to h264 etc.).

Mjpeg can be viewed natively by most browsers (except Internet Explorer) and can also be viewed on video viewers like VLC etc. An mjpeg stream is quite simple, it really just contains the individual jpeg frames’ data separated by a defined frame boundary marker.

Web2py takes care of chunked streaming via the stream() function, we just have to write a file object that we pass to stream(), this will take care of loading the jpeg frames and providing the data back to stream(), which in turn will stream this down the line to the client.

So to create an mjpeg stream we:

1.) Add a web2py handler for the stream, for example /mjpeg

2.) Add the following to the response headers: “multipart/x-mixed-replace; boundary=the_answer_is_42”
“the_answer_is_42” is just a made-up boundary marker which we hope won’t appear in the jpeg frame data, it can be changed to something else.

3.) Call stream() passing an instance of our MJPEGStreamer file object (see #4!), and a fairly arbitrary chunk size.

4.) Define a file compatible object that will loop ‘forever’ and provide the data to stream(), it will provide the data for the individual jpeg frames as well as insert the frame boundaries (–the_answer_is_42) between frames, it also inserts the headers for the individual frames (Content-Type: image/jpeg).

The following provides an overview of a stream implementation. Here we imagine that the latest jpeg frame is to be found in a ram-disk file called image.jpg, we load this data so that we can stream it to the client.

So in our web2py controller we have something like:

To view the mjpeg stream, open VLC viewer and choose Media / Open Network Stream and provide the stream URL (e.g. http://my_streaming_host/mjpeg) and hit play…

I found that it was important to set the chunk size to be (a good bit?) less than the data size of the smallest frame to be sent or else the stream will stall…

web2py – External connections to your Web App from the network on port 80

If you don’t want to use apache or the like to publish your web2py app then you can use web2py’s own little web server (rocket) by running web2py.py like this:

 

This won’t accept external connections however, and it also listens on port 8000 rather than port 80.

 

So, to allow external connections from web clients on port 80, run web2py.py as follows:

I keep forgetting this, so it’s getting written down for once and for all!

 

Web2py – Make your app the default web application.

There are multiple ways of making your app the default web2py application, they are detailed here in the section called ‘Application Init’. When an app is the default web2py app, you don’t have to specify its name in its url when you visit it in your browser.

 

Here is a summary of the method that I prefer.

 

First create a file in your web2py directory called routes.py, you can rename routes.example.py to routes.py but if you do, remember to delete any example code that it may contain.

 

Add the following code to routes.py:

Replace your_app_name_here with the name of your web application, and the restart web2py. How you restart web2py depends on how you run it, for example in my case I restarted apache.

 

When web2py has restarted you should now be able to access your app via a naked url.

 

Web2py and python – Change to model definition may break web site

In Web2py if you want to change a model’s definition, you can first of all change the model’s software definition via its python code and then, (depending on your migration settings), the next time you launch your web app, web2py will attempt to alter your database structure to match your updated model.

 

If this works, then it works and your database will reflect your new model, however sometimes web2py can’t make the necessary changes and your app may not subsequently load any more at all. If this happens then I have found the best way to fix the app is to delete all of the files in the app’s database directory – the next time you launch your app web2py will recreate your DB from scratch and it should launch again.

 

Now this is fine assuming that your database didn’t have loads of important data in it that you didn’t want to loose. So, to get around this problem, before trying to change a model’s definition I export all of the data in the database to a file (using a tool like this) so that if the problem happens and I have to get web2py to recreate the database ‘in its own image’ I can later reimport the previously saved data…

 

Web2py – You don’t have permission to access /admin on this server.

If you try to access the web2py admin pages and get an error like the following:
[code]
You don’t have permission to access /admin on this server.
[/code]
Then don’t panic immediately, by default the admin stuff is only available on HTTPS, so make sure that your URL starts with https: and try again, if this doesn’t work than feel free to panic… I keep forgetting this and it wrecks my head, software development can be trying!

 

Web2py / Apache – admin disabled because no admin password

If you are running Web2py on Apache and get this error message when you try to log into the admin interface (/admin):

 

admin disabled because no admin password

 

Then you may have forgotten to provide a password during set-up and will have to provide one now to proceed to the admin screens.

 

To do this you need to can do the following:

 

Stop Apache:

cd to the web2py directory and run web2py.py specifying a new password (greater than 4 characters long?) like this:

Then kill the web2py, e.g. via ctrl-c, and then copy parameters_8000.py to parameters_443.py, like this:

Restart the apache server:

After doing all of this when you visit /admin you should be asked to provide your password and you should be able to login – well it worked for me anyway! ;-)

 

Web2py and Apache running on Raspberry Pi

As part of my smart-cam simulation project I have installed web2py and Apache on a Raspberry Pi, the idea here is to simulate the ARM platform on which the smart-cam web UI software will eventually run by using the Pi until the real hardware is sorted out and available. This will allow me to do some proof-of-concept software development sooner rather than later.

 

I was expecting a difficult enough install but it turned out to be very easy, I just executed the automated set-up script that is documented here, under the section called ‘One step production deployment’ (ubuntu).

 

To summarise the steps, with the Pi connected to the network, open a terminal window and execute the following:

 

[code]
wget http://web2py.googlecode.com/hg/scripts/setup-web2py-ubuntu.sh
chmod +x setup-web2py-ubuntu.sh
sudo ./setup-web2py-ubuntu.sh
[/code]

 

Running setup-web2py-ubuntu.sh took a good while (15 mins?), but when it was complete I was immediately able to view the web2py welcome page from another computer on the network!