WebRTC Live Video Stream Broadcasting from One-to-Many
We recommend checking out our updated WebRTC video chat tutorial.
In this tutorial, we’re going to build a WebRTC live stream broadcasting application for one-to-many video communication. In other words, we’ll build Periscope or Meerkat using WebRTC, enabling one-way video streaming from a single broadcaster to any number of viewers, all in the browser!
We’ll cover how to use the PubNub WebRTC SDK with a wrapper class to easily create live embeddable streaming content, and implement PubNub Presence to get a real-time count of stream viewers.
Check out the live broadcast video streaming demo here, open up a couple windows, and watch it in action!
And if you want to check out the project code for the tutorial series, it’s available here.
If you haven’t yet checked out the previous posts, we built a WebRTC video chat app with a number of different features:
That’s right! Let’s get to it.
A Note on Testing and Debugging
If you try to open file://<your-webrtc-project>
in your browser, you will likely run into Cross-Origin Resource Sharing (CORS) errors since the browser will block your requests to use video and microphone features. To test your code you have a few options. You can upload your files to a web server, like Github Pages if you prefer. However, to keep development local, I recommend you setup a simple server using Python.
To do this, open your terminal and change directories into your current project and depending on your version of Python, run one of the following modules.
For example, I run Python2.7 and the command I use is python -m SimpleHTTPServer 8001
. Now I can go to http://localhost:8001/index.html
to debug my app! Try making an index.html
with anything in it and serve it on localhost before you continue.
Step 1: The HTML5 Backbone
I am going to try to keep the HTML simple for the sake of the demo. Create a file called stream.html
, and in it put the following code.
This will give you some inputs and options, as well as a video holder where you can place your local stream, to see what you are streaming to the world.
I added a icon of a person to indicate the number of people watching your stream.
You will notice there are a few functions that we will need to create in the JavaScript:
– stream(form)
: Begin streaming video on channel in form.
– watch(form)
: Join the steam channel provided by the form.
– end()
: Stop streaming.
– genEmbed(width,height)
: Generate an embeddable code for the stream.
Step 2: The JavaScript Imports
There are three libraries that you will need to include to make WebRTC operations much easier:
- Include jQuery to make modifying DOM elements a breeze.
- Include the PubNub JavaScript SDK to facilitate the WebRTC signaling.
- Include the PubNub WebRTC SDK, and SDK Wrapper libraries which makes placing phone calls as simple as calling the
dial(number)
function.
Now we are ready to write our broadcasting functions for stream
and watch
!
Step 3: Broadcasting Your Stream
In order to start broadcasting your streams, you will need a publish and subscribe key. To get your pub/sub keys, you’ll first need to sign up for a PubNub account. Once you sign up, you can find your unique PubNub keys in the PubNub Developer Dashboard. The free Sandbox tier should give you all the bandwidth you need to build and test your WebRTC Application.
3.1 Prepare to Broadcast
First, let’s locate our video holder for our local stream, embed code holder, and here-now holder for presence updates. Also, let’s create a global variable that will hold our current stream name.
3.2 Broadcast & Configurations
Now, time to implement our stream
function that will setup the WebRTC connection for broadcasting.
You are now streaming your video on channel streamName
. If you remember instantiating the phone
object in the past, you will notice that we added some new configurations, oneway
and broadcast
. The oneway
configuration simply sets the WebRTC SDK up for the possibility one-way streaming.
Then, broadcast
is set to true to indicate that your phone
will be the one broadcasting, not receiving the stream. Indicating oneway
will allow a user to watch your stream without ever having to grant mic and video permissions.
The ctrl.ready
function takes a callback to execute when it is ready to stream. First, we simply change the input to green to indicate success, and hide the submit button. Then, we use ctrl.addLocalStream(video_out)
to place our local stream in the video_out div. Finally, a call to ctrl.stream
subscribes us to a stream channel to begin broadcasting.
The last thing we do in our stream
function is make a ctrl.streamPresence(function(m){...})
handler. This subscribes you to presence events on your stream, then hands all presence events to the callback function. I simply pull off the current occupancy and display it in our here_now
div.
To spark your creativity, see the documentation on Presence.
Step 4: Join a Stream
Now that we have a user streaming (our broadcaster), we need to enable other users to join and view that stream. The watch
function takes the value from the HTML input and joins that stream.
The initial setup looks very similar, but you will notice we only specify oneway
this time. This user is only receiving the stream, not broadcasting as well.
When the controller is ready to connect, it uses ctrl.isStreaming(number, function(isStrm){})
to make sure that the user they want to watch is currently streaming. This function takes a number and a callback. It checks if the number is streaming and passes a boolean value isStrm
to the callback function. If the user is streaming, we use ctrl.joinStream
to join the stream. No need to grant access to mic and video because we are only watching the stream.
Then, we use ctrl.streamPresence
again to update the amount of users currently watching the stream via Presence.
And just like that, we’ve built a real-time live broadcast video app with WebRTC. The coolest part is yet to come though. Next we will set up an embeddable live streaming video.
Step 5: Embeddable Live Streams
Lastly, we want to make the live stream embeddable in any browser. Creating an embeddable live stream is as simple as making an iframe
whose contents automatically joins your live stream.
5.1 Generate the Embed Code
Before we get to coding the HTML file that will load your video in the iframe, let’s write the function that will create the embeddable code.
You can see that our code will open an iframe
that displays the contents of a file on your website called embed.html
, and passes the parameter stream=streamName
. For debugging, you can use http://localhost:[your-port]/embed.html
.
5.2 Create the Embed HTML & CSS
In the same directory as your stream.html
, create a file called embed.html
. The HTML portion of your embed file is extremely basic:
Just a box to place the stream in and a presence counter. I will leave most of the styling to your personal preference, but in order to make sure the video takes up as much of the iframe
as it can, I recommend some of the following stylings:
This will ensure that vid-box
and the video
element that will be placed inside of it take up as much of the screen as possible.
5.3 The Embeddable Content’s JavaScript
This embeddable HTML will need to include some of the JavaScript imports as well, that way you can embed it on any page. Below your HTML, put the following JavaScript imports:
All that is left to do now is create a final script tag that gets the stream name from the URL parameters, and then does the exact same thing as our watch
function from part three.
First, set some global variables and make sure that there is a parameter stream
in the URL query string.
Notice that we wrap the entire function in an anonymous function call (function(){ ... }())
. This is to preserve the scope of these variables, so they won’t interfere with the JavaScript on their embedded page. (It is called anonymous because it has no name and it calls itself!)
The function urlparams
can be copied exactly. It simply chops everything off the URL after ?
and then creates a map
of type string->string
for the query string key-value pairs. We create this map in urlargs
and then check if it contains a key stream
. If it doesn’t, handleNoStream
is called.
This function is also called if there was no user streaming to the channel you tried joining, or when the streaming user ends broadcast. It is essentially an error handler, and this implementation hides the presence counter and displays some text.
Now, in the same anonymous function, right below handleNoStream
, we will place the following code, which looks almost identical to watch
.
The only real differences between this block of code and watch
from Part 3, is that we now catch ctrl.unable
which is called if the browser is not WebRTC compatible, and session.ended
which is called when the broadcaster stops streaming. Both callbacks invoke handleNoStream
and display the “No Stream” message.
5.4 Try It Out
Start broadcasting a stream and then visit the page /embed.html?stream=myStreamName
. If all goes well, you will see your stream load automatically! When you are ready to take your site live, remember to change the url from 4.1 genEmbed
to your website’s name.
What Now?
This guide has only provided simple suggestions for your video streaming app. Get creative! These are very open callbacks. You can customize the way your embed page looks by styling the HTML, if you want the video smaller or larger, it is just a plain video
HTML element and it can be modified with CSS. Make something cool!