Implementing Movie Talk in a Phoenix Application with WebRTC, Hashrocket
Hashrocket
Implementing Movie Talk in a Phoenix Application with WebRTC
by Chad Brading on September 16, two thousand fifteen
In this blog post we’re going to cover how to implement movie talk in a Phoenix application with WebRTC. By the end of this post we will have enabled two remote clients to connect with each other and engage in a movie conversation.
We will use Phoenix channels to communicate messages inbetween our two clients so they can establish a remote peer connection. WebRTC permits clients to establish a direct peer to peer connection with each other, but before they can establish this connection they need to communicate certain information about themselves, and this is what our Phoenix channels will facilitate. For a more in-depth explanation of how WebRTC works, visit https://www.html5rocks.com/en/tutorials/webrtc/basics.
To begin, let’s create a fresh app (Note that we will be using Phoenix version 1.0.Two. For install instructions visit https://www.phoenixframework.org/docs/installation).
Let’s very first create a basic call controller to treat our requests.
Then we’ll need to create a corresponding call view to render our template.
For our template we will just include two movie elements, one for the local stream and another for the remote stream. We will also need some buttons to invoke our deeds.
Next we need to update our router to redirect to our call controller. Switch the root path from PageController to CallController.
Now we can run mix phoenix.server and navigate to localhost:4000 to make sure our template is rendering correctly.
With that in place we are ready to set up our channel. Create a call channel with a join/Three function to permit clients to join the channel, as well as a handle_in/Three function to treat incoming events.
Next we need to define our call channel in our socket handler. Add the following line to web/channels/user_socket.ex.
Now we are just about ready to implement our JavaScript code to enable our clients to establish a connection. Very first add the following line to our application template to enable our WebRTC methods to work across different browsers (Chrome, Firefox, and Opera all presently support WebRTC).
For this example we will put our JavaScript code in app.js. Let’s very first import our socket and then establish a connection with our call channel.
Note that our socket is imported from web/static/js/socket.js. If you take a look at that file you will see that is where our socket is created and connected. You can also comment out or delete the code attempting to join a fresh channel since we have implemented that on our own.
Now we can wire up our buttons.
And then begin to define how our clients will establish their connections.
Here we are using the getUserMedia function to capture our local movie stream and then call the callback function gotStream.
In gotStream we are setting our local stream and then calling setupPeerConnection.
setUpPeerConnection creates a fresh RTCPeerConnection and then sets callbacks for when certain events occur on the connection, such as an ICE candidate is detected or a stream is added. Then we add our local movie stream to the peer connection.
Next we will add our call function to send a message to other clients connected on our channel with a local peer connection.
We are passing the createOffer function the following gotLocalDescription callback.
The createOffer function created a description of the local peer connection and then sent that description to any potential clients. Once a client receives such a description it then calls the following gotRemoteDescription function.
Here it sets the remote description on its local peer connection so it can connect to that remote client. It then replies with an response containing its own description so that remote client can connect back to it as well.
The descriptions being sent back and forward inbetween our clients also contain the rivulets that we added to their peer connections. Once a client receives a remote stream it will call the following function.
Here we are just setting the remote stream we receive to the movie element in our template.
Also, when we create our local description we are also creating a local ICE candidate, which will call the following function.
This sends information about the local ICE candidate over the channel to any potential clients. When a client receives a description about an ICE candidate it will call the following function.
This function will add information about the remote candidate to its local peer connection.
When our channel receives a message from the server it needs to know how to process that message. If the message it receives is a description of the remote peer connection we need to call the gotRemoteDescription function, but if it is a description of the remote ICE candidate we need to call the gotRemoteIceCandidate function. We will implement our channel’s event handler to account for these two screenplays.
Let’s also include a hangup function so a user can close the connection and stop the movie talk session.
And eventually add our handleError function.
Now if you navigate back to the browser, open up two tabs, and click the connect button in each tab you should see that each one has created a local peer connection and added its local movie stream. If you click the call button from one of the tabs then it will send a description of its local peer connection to the other peer connection, and after they exchange the necessary information they will establish their remote connection. Now you can see their movie talk session. You can view the sample repository at https://github.com/chadbrading/phoenix-webrtc.
Was this post helpful? Share it with others.