How to Render a JPEG Stream to the Web in < 5 minutes with PubNub

A Quick Post

So I’m working on a small project for fun, and I’m once again using PubNub to transfer data to end users. I wanted to stream a live video feed across all common browsers to include Safari for iOS devices. This means that I can’t use WebRTC, and to keep things simple then, I just wanted to stream JPEG frames at 15 frames per second.

It turned out that this program was so incredibly easy to write that I couldn’t resist just putting together a quick blog post.

Server Side Code

This assumes that you have some sort of JPEG generator in place. If you want to set up a test program, you can just write a quick script that opens a folder filled with jpegs and iterates over them continuously. Otherwise, this code is decoupled from reading from a camera or something (but you can also check out my other post on reading JPEG frames from SLRs here

import base64
import os

from pubnub import Pubnub

from jpeg_streamer import generate_jpegs

PUBNUB_PUBLISH_KEY = os.environ['PUBNUB_PUBLISH_KEY']
PUBNUB_SUBSCRIBE_KEY = os.environ['PUBNUB_SUBSCRIBE_KEY']

PUBLISH_CHANNEL = "jpeg_stream"

if __name__ == "__main__":
    pubnub = Pubnub(publish_key=PUBNUB_PUBLISH_KEY,
                    subscribe_key=PUBNUB_SUBSCRIBE_KEY,
                    cipher_key='',
                    ssl_on=False)
                    
    for jpeg_frame in generate_jpegs():
        message = base64.b64encode(jpeg_frame)
        pubnub.publish(PUBLISH_CHANNEL, message)

Pretty simple, right? Keep in mind that the max packet size accepted by PubNub is 32 KB. In my case I generated JPEGs that are somewhat low quality and are about 200 by 300 pixels.

Client Side Code

And the HTML and javascript to go with it:

<html>
    <head>
        <script src="http://cdn.pubnub.com/pubnub-3.7.12.min.js"></script>

        <script type="text/javascript">

            var pubnub = PUBNUB({
                subscribe_key: subscribeKey,
                publish_key: publishKey
            });
            var channelName = "jpeg_stream";
            pubnub.subscribe({
                channel: channelName,
                message: function(b64Message){
                    var metaData = "data:image/jpeg;base64,";
                    document.getElementById("fillMe").src = metaData + b64Message;
                },
                error: function(error){
                    console.log(JSON.stringify(error));
                }
            });

        </script>
    </head>

    <body>
        <img id="fillMe" style="width: 200px; border: 1px solid black;"/>
    </body>

</html>

That’s It!

If you just write your own jpeg generator function, this is absolutely all you need to set up a broadcasted video feed.

  • Stephen Blum

    Your code is very satisfying to read.