Node-Webkit, WebRTC and Angularjs – A Video Chat Client

This post is part 7 of 7 in the series Node Webkit Apps
Tweet about this on TwitterShare on LinkedIn1Share on Google+5Share on Reddit0Buffer this pageFlattr the authorEmail this to someonePrint this page

Couple of days ago Saurav Panda requested a tutorial on building a video chat application using Node-webkit and WebRTC. So, here it goes.

Smooth and easy right!

As mentioned in the video, this client is built using Node-webkit, WebRTC and Peerjs. We will leverage the power of Peer.js & WebRTC to enable the connection between 2 node webkit clients. We will host our own peer-server on Heroku (with one click deploy) and use this server for creating the initial connection.

We will be using Angularjs via Lumx (an Angularjs Material Design implementation) as our client side framework.

First we will understand how the application is designed and then we will build the node-webkit client from scratch.

You can find the completed code here.

So, lets get started?

Application Design

The application we are building leverages Peerjs to implement WebRTC.

nwk-webrtcAs you can see from the above diagram, the client 1 & client 2 are our node-webkit clients. When the client is launched for the first time, it would establish a connection with the peer server. Then the peer server would provide a random ID or a unique ID for that client. And when the second client is launched, it acquires its own unique ID.

Now, when the two clients want to talk to each other, we will use the Peer API to establish the initial connection between the two clients and then using WebRTC, they continue talking to each other without the server.

Since we are using Angular.js, we will be building our own custom directive for managing the client and interacting with the Peer API. We would create a new tag called  nwk-video-chat and this tag will take care managing the chat UI for us.

If you are new to WebRTC, refer What Is WebRTC and How Does It Work?

Setup Project

Now that we have an understanding of the application design, we will get started with the development.

Create a new folder named nwk-videochat. Open a new terminal/prompt here. We will be using a slush generator, named slush-wean to quickly scaffold a node-Webkit, Express, Angular and Node application. The scaffolded project has everything you need to develop a node webkit app as well as distribute it.

First let us install bower, gulp, slush and slush-wean globally.

npm install -g bower gulp slush slush-wean

This will take a couple of minutes. Once that is done, we will scaffold a new WEAN app. Run

slush wean

It would prompt you for a project name. You can call it anything or use nwk-videochat. Then it would take a couple of minutes to scaffold the project and setup dependencies.

The project structure would look like

The app folder consists of the HTML, CSS and JS to develop the app. And the assets outside are used for project management.

Now, let us launch the app and test it out. You can do it in 2 ways

  1. using  gulp run
  2. using sublime text node-webkit plugin

I would recommend the second approach for saving some time, but either of them would do.

Once you launch the application, you should see a sample splash screen and then see this

Screen Shot 2015-02-23 at 11.19.13

For development purposes, we will enable the toolbar, so you can debug using the developer tools. For that, open package.json and set toolbar property value to true. Then launch the app again and you should see a URL bar and a settings icon next to it.

When you click on the settings icon, you should see

Screen Shot 2015-02-23 at 11.22.54

You can use this to debug your applications as you would do with any browser based app. The updated package.json would be

Begin Development

We will modify the splash screen first. Open app/index.html and updated it as

Next, we will install Lumx. This would be our UI Framework. Run

bower install lumx --save

Now, we will wire up the dependencies. Open app/views/index.ejs and update it as below

We have referred all the required assets in the head section and in the body, we have added a custom directive/tag named  nwk-video-chat.

Next, open app/public/js/app.js and update it as below

On line 3, we add lumx as a dependency to our module. On line 11, we set a window menu for the app. Without this, text selections, copy & paste would not work in the node-webkit app.

Next, we will fix the header for the app. Open app/public/partials/head.html and update it as below

I would highly recommend going through all the Lumx components and then building your app. The above head.html consists of a stripped down version of the toolbar component.

Finally we will be focusing on the  nwk-video-chat directive. We will create a template for this directive to work with the UI. For that, create a new file named nwk-videochat.directive.html inside the app/public/partials folder. Open this file in your favorite editor and update it as

Refer to Lumx for the CSS classes and the components used above.

User Interface Flow

So, this is what would happen when you launch the client

  1. We establish a new connection with our Peer server (which we will get to at the end)
  2. Once we are connected, the server would send an ID. we will present that ID to the end user to share with his “Peers”.
  3. Once User A enters the peer id for User B, we establish a connection between them via the server
  4. Next, we would invoke a call between the 2 clients using the Peerjs API
  5. Finally they are connected and video streaming initiates between them.

Simple right? We are going to put the same logic in our directive.

Create a new file named nwk-videochat.directive.js inside the client/app/public/js folder and update it as below

Things to notice : (This is the app’s business logic)

  • Line 3 : We create a new directive named nwkVideoChat and add LxDialogServiceLxNotificationService and $sce as dependencies.
  • Line 5 : We restrict the directive to a element
  • Line 6 : We point the template URL to the template we have created in the partials folder
  • Line 8-12 : We set the initial state of the application
  • Line 14 : We show a modal to the user while the client is connecting to the server
  • Line 20 : We get the webkitGetUserMedia and assign it to getUserMedia
  • Line 23 : We create a new instance of peerjs by passing in our custom server details. When we setup our own peer server on Heroku, you can update the same here.
  • Line 30 : The peer is connected to the client, we show a couple of status messages and update close the modal we open on app load
  • Line 43 : The event  call would be fired when a peer initiates a call to this client. As you can see from the comments, I wanted to show a answer or reject call modal and then if the user answers it, we show the video else we reject it. But this approach, for some reason, is not displaying the video for the call initiator. Not sure why!
  • Line 85 : Before we connects the two clients, we need to get the video of the current client. Here, we request the stream. And once that is done, we will invoke the callback on line 92.
  • Line 53 : Once we get the current user’s video stream, we will answer the call and invoke a  handleCall().
  • Line 98 : We cancel out all in progress calls. And then we stream the video from the peer to the current client.
  • Line 71 : If the current client wants to connect to another client, we invoke the peer.call()  and pass the call object to the  handleCall() on line 75.
  • Line 80 : End the active call

That is it! With this we complete our app.

Setup Server

We are going to setup our own peer server on Heroku with their one click deploy. All you need to do is naviagate to the below URL in your browser

https://www.heroku.com/deploy/?template=https://github.com/peers/peerjs-server

And if you are logged in to Heroku, you should see

Screen Shot 2015-02-23 at 12.17.19And when you enter your app name and click on Deploy for free, your peer-server will be available on Heroku! To test the server you can go to

https://<<your-app-name>>.herokuapp.com

For instance my server would be  https://nwk-peer-server.herokuapp.com/ and you should see

Screen Shot 2015-02-23 at 12.21.39That is it, your peer-server is ready to go!

Update line 24 in app/public/js/nwk-videochat.directive.js and then launch the client. You should see the Peer ID generated for your client.

Build and Distribute the app

To build and distribute the app, run

gulp build

or

gulp build --win

or

gulp build --mac

or

gulp build --linux32

or

gulp build --linux64

or

gulp build --all

And you should get that environment specific/all installers. And you can distribute that app & get chatting!.

Hope this post gave you an idea on how to work with video chats on node-webkit with WebRTC,


Thanks for reading! Do comment.
@arvindr21

Series Navigation<< Node Webkit, Firebase and Ionic Framework – A one to one chat client
Tweet about this on TwitterShare on LinkedIn1Share on Google+5Share on Reddit0Buffer this pageFlattr the authorEmail this to someonePrint this page
  • Hira Shamim

    i m very confused dont understant what to do please help me out i want sample code for webrtc first setp by step then iwant to save the time duration of video confrencing please code provide kerain

  • Hira Shamim

    hi

  • cbenjemia

    good job !

    but there is a pb with “node_remote” >>>> Invalid value for ‘app.urls[0]: Missing schema separator… :(

    is there a fix ?

    thanks

  • http://www.casafuturatech.com/ Thomas David Kehoe

    When I run “gulp run” it says “Launching App” and throws an error message: “Invalid value for ‘app.urls[0]': Missing schema separator.” See attached screenshot. Any suggestions? I followed the tutorial and ran gulp, slush, wean, etc.

    • cbenjemia

      hi Thomas, did you find a solution for this pb ?

  • chris1712

    Please Arvind, How can I implement or a group chat using your example. I was able to complete this one, I now need to create a room for group video discussions. Thanks a lot.

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Hello Chris, you have to build an application around this poc. You need to probably take the peerjs server as base and create features like login, register and then ability for a user to create a chat room and invite friends and then you can implement peerjs video calls there.

      Let me know how it works out.

  • steven

    Hi Arvind,

    This video chat client is nice !!! I tried it few days ago and it works!

    Have you tried running this video chat client on raspberry pi ? im trying to run it on raspberry pi but its giving me some error that i dont know what to do

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Hello Steven. Thanks! No, I have not run this on the pi yet. What error are you facing?

      • steven

        Hi Arvind,

        Thanks for getting back to me and sorry for the late reply. It couldnt find the path the build and it says error code 2 and enoent.

        I am still very new with Node JS and i looked up online for what it means but i don’t really get it.

        https://www.dropbox.com/s/o50a5uhkdt03gyr/Photo%202015-04-04%2C%203%2007%2047%20PM.jpg?dl=0

        Here is a picture of it.It’s the one on the middle. Do you know what to do with this by any chance ?

        • http://thejackalofjavascript.com/ Arvind Ravulavaru

          Hello Steven, I recommend building a Linux installer on your desktop and then running the generated installer on the pi.

          Thanks.

  • looky

    Big MERCI , that will help me a lot for my project!

  • Imtiyaz

    Hi Arvind, couple years ago I worked on similar project using WebRTC. Its hosted on github for those who are interested. https://github.com/imomin/videoChat

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Hey Imtiyaz. A very comprehensive example! Thanks for sharing.

  • Saurav Panda

    Many thanks man for the tutorial. I was continuously checking your website and finally got it now. You rock !!

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Not an issue. Thanks!

      • Saurav Panda

        I have one more doubt. Can we customize the randomly created unique id by peer.js? Can I have an scenario where I can fix the id of a user and which will be permanent till the time the application is installed in a system?

        • http://thejackalofjavascript.com/ Arvind Ravulavaru

          Yes, you can. That is why I have shown you how to deploy your own peer-server. You can read more here : peer-server.

          • Saurav Panda

            Hi,
            I will definitely try , once I finish up with this tutorial. I have installed all with slush wean but while trying to run the default app with sublime, I am getting this error.
            ” Invalid package. There is no package.json in the package.Please make sure that the package.json is in the root of the package.”
            Any idea why i am getting this? do I need to install some more package ??

          • http://thejackalofjavascript.com/ Arvind Ravulavaru

            When you are using Sublime text, you need to build the app from root folder. That is from either package.json or bower.json and it should launch fine.

          • Saurav Panda

            Sorry for bothering you again. I am trying to build this way but I am again getting an error.
            ” Uncought Nodejs error.
            Reference error: angular is not defined at http://localhost:3000/js/app.js:3:1

            Do I need to do a ‘npm install’ inside nwk-videochat to install all dependencies before trying build it?

          • http://thejackalofjavascript.com/ Arvind Ravulavaru

            When you scaffold the app, it takes care of installing node and bower dependencies. Sometimes it may crash, just to be sure, you can run npm i && bower i. You should see a libs folder created inside app/public. This will have the bower dependencies.

          • Saurav Panda

            This is the output from the above mentioned command.
            npm WARN unmet dependency /Users/sauravpanda/Desktop/node_webkit_projects/nwk-videochat/node_modules/node-webkit-builder/node_modules/decompress-zip/node_modules/touch requires nopt@’~1.0.10′ but will load
            npm WARN unmet dependency /Users/sauravpanda/Desktop/node_webkit_projects/nwk-videochat/node_modules/node-webkit-builder/node_modules/decompress-zip/node_modules/nopt,
            npm WARN unmet dependency which is version 2.2.1
            -bash: bower: command not found

            I am confused with the last line ‘bower not found’ but I have already installed bower at global level. Now what to do?

          • http://thejackalofjavascript.com/ Arvind Ravulavaru

            You can ignore the npm warnings. To check if bower is installed at a global level, run bower and it should not return command not found. If you still get that error, run npm install bower -g.

          • Saurav Panda

            I did the bower i and it produces the below result,

            bower not-cached git://github.com/angular/bower-angular.git#^1.3.13
            bower resolve git://github.com/angular/bower-angular.git#^1.3.13
            bower not-cached git://github.com/twbs/bootstrap.git#*
            bower resolve git://github.com/twbs/bootstrap.git#*

            but still i am getting the same error.

            ” Uncought Nodejs error.
            Reference error: angular is not defined at http://localhost:3000/js/app.js:3:1

            I am very new to scaffolding process, so I am sure that I am doing something wrong but I am not able to figure it out. :( .
            any idea what possibly may have been wrong !!

          • http://thejackalofjavascript.com/ Arvind Ravulavaru

            Can you check if line 15 in index.ejs is pointing to the Angularjs file inside app/public/libs folder? This is where you should find all the files.

            If you are still facing issues, download the code from github, run npm and bower install and launch the app.

          • Saurav Panda

            Many thanks. finally solved the problem!!
            The problem was that I didn’t have bower installed before creating a wean app.
            Can you please add one line to the tutorial that everyone should make sure that bower is installed before scaffolding a wean app.
            Many thanks for your patient responses for my silly questions. :) .

          • http://thejackalofjavascript.com/ Arvind Ravulavaru

            Great! That line is already present, where you install gulp, slush and slush-wean. Thanks.

          • Saurav Panda

            One more small typo(I think so!!), Please correct me if i am wrong !!
            ‘ Now, we will wire up the dependencies. Open app/views/index.js and update it as below’
            here you mean ‘ app/views/index.js’ or should it be ‘Open app/views/index.ejs’ ?

          • http://thejackalofjavascript.com/ Arvind Ravulavaru

            Thanks! Fixed it.

          • Saurav Panda

            how to launch a second instance to test the app?
            I tried to build twice but it is showing the same interface !!
            Sorry for such a silly question.

          • http://thejackalofjavascript.com/ Arvind Ravulavaru

            Add "single-instance" : false to your package.json

          • Saurav Panda

            After doing the above and trying to start a new build while one window is open ,I am getting the below error in the console.
            1172:0223/190447:ERROR:tcp_listen_socket.cc(69)] Could not bind socket to 127.0.0.1:9222
            [1172:0223/190447:INFO:CONSOLE(82)] “Uncaught Error: listen EADDRINUSE”, source: events.js (82)
            [1172:0223/190455:ERROR:nw_shell.cc(334)] Unable to load URL:

            any idea what went wrong ?

          • http://thejackalofjavascript.com/ Arvind Ravulavaru

            The second client should start on a different port. 3000 is used by the first express server. Copy the same client code, create a new client and update port to 2000 in app.js and index.html.

          • Saurav Panda

            If I understood you correctly, I copied the whole folder itself and created a copy named nwk-videochat-copy. Here I changed the port to 2000, but whenever i am trying to open the second, it is overlapping the previous one. I am not able to open two windows at the same time.
            what am I doing wrong ?

          • http://thejackalofjavascript.com/ Arvind Ravulavaru

            Did you try moving the windows around using the window bar on top?

          • Saurav Panda

            Yes. I found the error but don’t know how to resolve it. I have successfully opened one instance at localhost:3000 but I am getting the below error after opening the second instance. Also after 2-3 seconds the 1st instance get closed automatically.

            I am not able to understand why ?

            [1749:0224/104934:ERROR:tcp_listen_socket.cc(69)] Could not bind socket to 127.0.0.1:9222

          • Saurav Panda

            My second instance runs on port 2000. Below is the output of sublime console.

            [1749:0224/104934:ERROR:tcp_listen_socket.cc(69)] Could not bind socket to 127.0.0.1:9222
            [1749:0224/104941:INFO:CONSOLE(1476)] “”PeerJS: ” “Socket open””, source: http://cdn.peerjs.com/0.3/peer.js (1476)
            [1751:0224/105030:ERROR:rtc_data_channel_handler.cc(125)] WebRTCDataChannelHandlerClient not set.
            [1751:0224/105030:ERROR:rtc_data_channel_handler.cc(125)] WebRTCDataChannelHandlerClient not set.
            [1751:0224/105030:ERROR:rtc_data_channel_handler.cc(125)] WebRTCDataChannelHandlerClient not set.
            [1751:0224/105030:ERROR:rtc_data_channel_handler.cc(125)] WebRTCDataChannelHandlerClient not set.

          • http://thejackalofjavascript.com/ Arvind Ravulavaru

            Can you use gulp run to lauch the clients?

          • Saurav Panda

            With gulp it is running fine with both the instances. I tested with 2 instances and it is working fine now.
            Thanks for this great tutorial.
            I successfully created one executable for my friend’s linux 64 os and he is able to execute it.
            but the only problem is that his webcam is not streaming video to me though I can hear his voice and he can see as well as hear me. Somehow his webcam is not starting up with getusermedia(). He is running Ubuntu 12.04LTS. Is there any os specific code need to be written or anything else?
            I am trying to install nw in his machine and trying to write a simple application to access getusermedia() to find out the reason behind the bug. Is there a better way of doing it?
            I will find out and update you regrading the problem.
            Have a great day ahead.

          • http://thejackalofjavascript.com/ Arvind Ravulavaru

            Great! Good to hear that all is working fine. Not sure about the getusermedia(), but do keep me updated on what happens. Thanks!

          • Saurav Panda

            I found the problem but it is more related to os rather than nw. In linux it is asking for a suid to be attached to the Linux sandbox where nw is running. Below is the exact error.
            [15464:0224/125017:ERROR:
            browser_main_loop.cc(162)] Running without the SUID sandbox! See https://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment for more information on developing with the sandbox on.
            ATTENTION: default value of option force_s3tc_enable overridden by environment.
            I have posted it on the nwjs github page and waiting for a reply from them. Do let me know your thoughts on what possibly may have gone wrong.

          • Saurav Panda

            The windows distribution is not working. The app.exe file in windows only shows a blank nw welcome page. I am trying manually to create a package for windows, will update you.

          • http://thejackalofjavascript.com/ Arvind Ravulavaru

            Try nodebob for windows : https://github.com/geo8bit/nodebob

          • dkvbabu

            arvind,

            I am working with saurav on this video chat. can you please let me know how to integrate mongodb with this webkit chat application.
            I need to get peerid from this mongodb to use it as

            var peer = new Peer(‘id as fetched from local mongodb’,{ 
            host: ‘absimpl-viscom.herokuapp.com’,

            Thanks

          • http://thejackalofjavascript.com/ Arvind Ravulavaru

            This should be done from Expressjs. Checkout routes folder.

          • dkvbabu

            arvind,

            i checked routes folder .

            it has the following

            exports.index = function(req, res){
            res.render(‘index’);
            };

            it does not have reference to mongodb connection and retreival.

            basically I have to modify this line in app/public/partials/nwk-videochat.directive.html

            Your ID : {{id}}

            {{id}} field should be fetched and populated from local mongodb database.

            i have already installed mongodb in my machine.

            regards

            thanks
            dk venkatesh babu

          • http://thejackalofjavascript.com/ Arvind Ravulavaru

            So here is the thing Venkatesh,

            1. This is a stand alone desktop app, expecting this app to install MongoDB on user’s machine may not be the right approach
            2. Use Mongolab or AWS to host your mongodb and get the data at runtime from the nwk app.
            3. If the nwk app is not connected to the server, you need to gracefully fallback.
            4. Use expressjs as your server layer to fetch the data from remotely hosted MongoDB as how you would normally in a web app. You can use mongojs for interacting with the remote DB and expose a route in the nwk express app so that your client can interact with it.

            Let me know if you still have questions.

            Thanks,
            Arvind.

          • Saurav Panda

            Hi Arvind,
            Is there any problem if we try to install mongodb on the user’s local machine? We need a database in the users local machine to collect some info and do some analytics based upon that data locally. We don’t want to store on the cloud due to the nature of data.
            We are working on a slightly different approach which is not exactly same as regular cloud model.
            Can mongo not work on desktop app or is there a better alternative to mongo for local storage and local analytics?
            You have your own diskdb. how will it be for local storage and analytics ?
            Please share your views on best practices to follow for the above situation .

          • http://thejackalofjavascript.com/ Arvind Ravulavaru

            Hello Saurav,

            Diskdb is not production ready yet. It can be used for prototyping.

            I would recommend looking at indexeddb or websql. You can find more info here : https://github.com/nwjs/nw.js/wiki/Save-persistent-data-in-app

            Thanks.

          • Saurav Panda

            Also I am not able to find the angular and bootstrap files any where in my app folder. So the problem is that they were not at all downloaded. Should I manually download them ?

      • Ankur
        • http://thejackalofjavascript.com/ Arvind Ravulavaru

          Sure, let me give that a try. I will try to write a post on it soon.