{"id":21529699,"url":"https://github.com/samsamskies/webrtc-codelab","last_synced_at":"2025-09-15T12:14:38.274Z","repository":{"id":11155114,"uuid":"13525513","full_name":"SamSamskies/webrtc-codelab","owner":"SamSamskies","description":null,"archived":false,"fork":false,"pushed_at":"2013-10-12T21:03:43.000Z","size":5008,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-12T00:16:29.516Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SamSamskies.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-10-12T17:15:03.000Z","updated_at":"2019-03-04T15:12:24.000Z","dependencies_parsed_at":"2022-08-28T15:24:14.241Z","dependency_job_id":null,"html_url":"https://github.com/SamSamskies/webrtc-codelab","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/SamSamskies/webrtc-codelab","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamSamskies%2Fwebrtc-codelab","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamSamskies%2Fwebrtc-codelab/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamSamskies%2Fwebrtc-codelab/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamSamskies%2Fwebrtc-codelab/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SamSamskies","download_url":"https://codeload.github.com/SamSamskies/webrtc-codelab/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamSamskies%2Fwebrtc-codelab/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275254669,"owners_count":25432298,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-15T02:00:09.272Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-24T01:58:45.080Z","updated_at":"2025-09-15T12:14:38.220Z","avatar_url":"https://github.com/SamSamskies.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WebRTC codelab\n\n##Overview\n\nWebRTC enables real-time communication in the browser.\n\nThis tutorial explains how to build a simple video and text chat application.\n\nFor more information about WebRTC, see [Getting started with WebRTC](http://www.html5rocks.com/en/tutorials/webrtc/basics) on HTML5 Rocks.\n\n## Prerequisites\n\nBasic knowledge:\n\n1. HTML, CSS and JavaScript\n2. [git](http://git-scm.com/)\n3. [Chrome DevTools](https://developers.google.com/chrome-developer-tools/)\n\nExperience of [Node.js](http://nodejs.org/) and [socket.io](http://socket.io/) would also be useful.\n\nInstalled on your development machine:\n\n1. Google Chrome.\n2. Code editor.\n3. Web server such as [MAMP](http://mamp.info/en/downloads) or [XAMPP](http://apachefriends.org/en/xampp.html) -- or just run `python -m SimpleHTTPServer` in your application directory (or better start a [secure HTTPS server](http://www.piware.de/2011/01/creating-an-https-server-in-python/) to avoid having to 'allow' the camera every time you reload the page in the browser).\n4. Web cam.\n5. git, in order to get the source code.\n6. The [source code](https://bitbucket.org/webrtc/codelab/src).\n7. Node.js with socket.io and node-static. (Node.js hosting would also be an advantage -- see below for some options.)\n\n*The instructions in this codelab assume you are using Mac OS, Linux or Windows. Unless you know what you're doing, it's probably easier not to attempt this codelab from a Chromebook!*\n\nIt would also be useful to have an Android device with Google Chrome installed in order to try out the examples on mobile. To run WebRTC APIs on Chrome for Android, you must enable WebRTC from the chrome://flags page.\n\n## Step 0: Get the code\n\nUsing git, clone the codelab repository onto your development computer. If you haven't used git before, there are several tutorials and reference guides available from the [git website](http://git-scm.com/).\n\n## Step 1: Create a blank HTML5 document\n\nComplete example: [complete/step1.html](https://bitbucket.org/webrtc/codelab/src/master/complete/step1.html).\n\n1. Create a bare-bones HTML document.\n2. Open that from localhost (see server suggestions above).\n\n## Step 2: Get video from your webcam\n\nComplete example: [complete/step2.html](https://bitbucket.org/webrtc/codelab/src/master/complete/step2.html).\n\n1. Add a video element to your page.\n2. Add the following JavaScript to the script element on your page, to enable getUserMedia() to set the source of the video from the web cam:\n\n        navigator.getUserMedia = navigator.getUserMedia ||\n          navigator.webkitGetUserMedia || navigator.mozGetUserMedia;\n\n        var constraints = {video: true};\n\n        function successCallback(localMediaStream) {\n          window.stream = localMediaStream; // stream available to console\n          var video = document.querySelector(\"video\");\n          video.src = window.URL.createObjectURL(localMediaStream);\n          video.play();\n        }\n\n        function errorCallback(error){\n          console.log(\"navigator.getUserMedia error: \", error);\n        }\n\n        navigator.getUserMedia(constraints, successCallback, errorCallback);\n\n3. View your page from _localhost_.\n\n### Explanation\n\n`getUserMedia` is called like this:\n\n    navigator.getUserMedia(constraints, successCallback, errorCallback);\n\nThe constraints argument allows us to specify the media to get, in this case video only:\n\n    var constraints = {\"video\": true}\n\nIf successful, the video stream from the webcam is set as the source of the video element:\n\n    function successCallback(localMediaStream) {\n      window.stream = localMediaStream; // stream available to console\n      var video = document.querySelector(\"video\");\n      video.src = window.URL.createObjectURL(localMediaStream);\n      video.play();\n    }\n\n### Bonus points\n\n1. Inspect the stream object from the console.\n2. Try calling `stream.stop()`.\n3. What does `stream.getVideoTracks()` return?\n4. Look at the constraints object: what happens when you change it to `{audio: true, video: true}`?\n5. What size is the video element?  How can you get the video's natural size from JavaScript? Use the Chrome Dev Tools to check. Use CSS to make the video full width. How would you ensure the video is no higher than the viewport?\n6. Try adding CSS filters to the video element (more ideas [here](http://html5-demos.appspot.com/static/css/filters/index.html)).\n7. Try changing constraints: see the sample at [simpl.info/getusermedia/constraints](https://simpl.info/getusermedia/constraints/).\n\nFor example:\n\n    video {\n      filter: hue-rotate(180deg) saturate(200%);\n      -moz-filter: hue-rotate(180deg) saturate(200%);\n      -webkit-filter: hue-rotate(180deg) saturate(200%);\n    }\n\n## Step 3: Stream video with RTCPeerConnection\n\nComplete example: [complete/step3.html](https://bitbucket.org/webrtc/codelab/src/master/complete/step3.html).\n\nRTCPeerConnection is the WebRTC API for video and audio calling.\n\nThis example sets up a connection between two peers on the same page. Not much use, but good for understanding how RTCPeerConnection works!\n\n1. Get rid of the JavaScript you've entered so far -- we're going to do something different!\n\n2. Edit the HTML so there are two video elements and three buttons: Start, Call and Hang Up:\n\n\n        \u003cvideo id=\"localVideo\" autoplay\u003e\u003c/video\u003e\n        \u003cvideo id=\"remoteVideo\" autoplay\u003e\u003c/video\u003e\n\n        \u003cdiv\u003e\n          \u003cbutton id=\"startButton\"\u003eStart\u003c/button\u003e\n          \u003cbutton id=\"callButton\"\u003eCall\u003c/button\u003e\n          \u003cbutton id=\"hangupButton\"\u003eHang Up\u003c/button\u003e\n        \u003c/div\u003e\n\n3. Add the JavaScript from [complete/step3.html](https://bitbucket.org/webrtc/codelab/raw/master/complete/step3.html).\n\n### Explanation\n\nThis code does a lot!\n\n* Get and share local and remote descriptions: metadata about local media in SDP[^SDP] format.\n* Get and share ICE[^ICE] candidates: network information.\n* Pass the local stream to the remote _RTCPeerConnection_.\n\n[^SDP]: [Session Description Protocol](http://en.wikipedia.org/wiki/Session_Description_Protocol)\n[^ICE]: [Interactive Connectivity Establishment Protocol](http://en.wikipedia.org/wiki/Interactive_Connectivity_Establishment)\n\n### Bonus points\n\n1. Take a look at _chrome://webrtc-internals_. (There is a full list of Chrome URLs at _chrome://about_.)\n2. Style the page with CSS:\n    - Put the videos side by side.\n    - Make the buttons the same width, with bigger text.\n    - Make sure it works on mobile.\n3. From the Chrome Dev Tools console, inspect _localStream_, _localPeerConnection_ and _remotePeerConnection_.\n4. Take a look at _localPeerConnection.localDescription_. What does SDP format look like?\n\n## Step 4: Stream arbitrary data with RTCDataChannel\n\nComplete example: [complete/step4.html](https://bitbucket.org/webrtc/codelab/src/master/complete/step4.html).\n\nFor this step, we'll use RTCDataChannel to send text between two textareas on the same page. Not very useful, except to demonstrate how the API works.\n\n1. Create a new document and add the following HTML:\n\n        \u003ctextarea id=\"dataChannelSend\" disabled\u003e\u003c/textarea\u003e\n        \u003ctextarea id=\"dataChannelReceive\" disabled\u003e\u003c/textarea\u003e\n\n        \u003cdiv id=\"buttons\"\u003e\n          \u003cbutton id=\"startButton\"\u003eStart\u003c/button\u003e\n          \u003cbutton id=\"sendButton\"\u003eSend\u003c/button\u003e\n          \u003cbutton id=\"closeButton\"\u003eStop\u003c/button\u003e\n        \u003c/div\u003e\n\n3. Add the JavaScript from [complete/step4.html](https://bitbucket.org/webrtc/codelab/raw/master/complete/step4.html).\n\n### Explanation\n\nThis code uses RTCPeerConnection and RTCDataChannel to enable exchange of text messages.\n\nMost of the code in this section is the same as for the RTCPeerConnection example. Additional code is as follows:\n\n    function sendData(){\n      var data = document.getElementById(\"dataChannelSend\").value;\n      sendChannel.send(data);\n    }\n    ...\n    localPeerConnection = new webkitRTCPeerConnection(servers,\n      {optional: [{RtpDataChannels: true}]});\n    sendChannel = localPeerConnection.createDataChannel(\"sendDataChannel\",\n      {reliable: false});\n    sendChannel.onopen = handleSendChannelStateChange;\n    sendChannel.onclose = handleSendChannelStateChange;\n    ...\n    remotePeerConnection = new webkitRTCPeerConnection(servers,\n      {optional: [{RtpDataChannels: true}]});\n    function gotReceiveChannel(event) {\n      receiveChannel = event.channel;\n      receiveChannel.onmessage = gotMessage;\n    }\n    ...\n    remotePeerConnection.ondatachannel = gotReceiveChannel;\n    function gotMessage(event) {\n      document.getElementById(\"dataChannelReceive\").value = event.data;\n    }\n\nThe syntax of RTCDataChannel is deliberately similar to WebSocket, with a `send()` method and a `message` event.\n\nNotice the use of constraints.\n\n### Bonus points\n\n1. Try out RTCDataChannel file sharing with [Sharefest](http://www.sharefest.me/). When would RTCDataChannel need to provide reliable delivery of data, and when might performance be more important -- even if that means losing some data?\n2. Use CSS to improve page layout, and add a placeholder attribute to the _dataChannelReceive_ textarea.\n4. Test the page on a mobile device.\n\n## Step 5: Set up a signaling server and exchange messages\n\nComplete example: [complete/step5](https://bitbucket.org/webrtc/codelab/src/master/complete/step5).\n\nRTCPeerConnection instances need to exchange metadata in order to set up and maintain a WebRTC 'call':\n\n* Candidate (network) information.\n* _Offer_ and _answer_ messages providing information about media such as resolution and codecs.\n\nIn other words, an exchange of metadata is required before peer-to-peer audio, video or data streaming can take place. This process is called _signaling_.\n\nIn the examples already completed, the 'sender' and 'receiver' RTCPeerConnection objects are on the same page, so signaling is simply a matter of passing objects between methods.\n\nIn a real world application, the sender and receiver RTCPeerConnections are not on the same page, and we need a way for them to communicate metadata.\n\nFor this, we use a signaling server: a server that can exchange messages between a WebRTC app (client) running in one browser and a client in another browser. The actual messages are stringified JavaScript objects.\n\n**To reiterate: metadata exchange between WebRTC clients (via a signaling server) is required for RTCPeerConnection to to do audio, video and data streaming (peer to peer).**\n\nIn this step we'll build a simple Node.js signaling server, using the socket.io Node module and JavaScript library for messaging. Experience of [Node.js](http://nodejs.org/) and [socket.io](http://socket.io/) will be useful, but not crucial -- the messaging components are very simple. In this example, the server (the Node app) is _server.js_ and the client (the web app) is _index.html_.\n\nThe Node server application in this step has two tasks.\n\nTo act as a messaging intermediary:\n\n    socket.on('message', function (message) {\n      log('Got message: ', message);\n      socket.broadcast.emit('message', message);\n    });\n\nTo manage WebRTC video chat 'rooms':\n\n    if (numClients == 0){\n      socket.join(room);\n      socket.emit('created', room);\n    } else if (numClients == 1) {\n      io.sockets.in(room).emit('join', room);\n      socket.join(room);\n      socket.emit('joined', room);\n    } else { // max two clients\n      socket.emit('full', room);\n    }\n\nOur simple WebRTC application will only permit a maximum of two peers to share a room.\n\n1. Ensure you have Node, socket.io and [node-static](https://github.com/cloudhead/node-static) installed. Node can be downloaded from [nodejs.org](http://nodejs.org/); installation is straightforward and quick. To install socket.io and node-static, run Node Package Manager from a terminal in your application directory:\n\n\n        npm install socket.io\n        npm install node-static\n\n\n  (You don't need to learn about node-static for this exercise: it just makes the server simpler.)\n\n2. Using the code from the [step 5](complete/step5) directory, run the server (_server.js_). To start the server, run the following command from a terminal in your application directory:\n\n        node server.js\n\n3. From your browser, open _localhost:2013_. Open a new tab page or window in any browser and open _localhost:2013_ again, then repeat.\n\n4. To see what's happening, check the Chrome DevTools console (Command-Option-J, or Ctrl-Shift-J).\n\n### Bonus points\n\n1. Try deploying your messaging server so you can access it via a public URL. (Free trials and easy deployment options for Node are available on several hosting sites including [nodejitsu](http://www.nodejitsu.com), [heroku](http://www.heroku.com) and [nodester](http://www.nodester.com).)\n\n2. What alternative messaging mechanisms are available? (Take a look at [apprtc.appspot.com](http://apprtc.appspot.com).) What problems might we encounter using 'pure' WebSocket? (Take a look at Arnout Kazemier's presentation, [WebSuckets](https://speakerdeck.com/3rdeden/websuckets).)\n\n3. What issues might be involved with scaling this application? Can you develop a method for testing thousands or millions of simultaneous room requests.\n\n4. Try out Remy Sharp's tool [nodemon](https://github.com/remy/nodemon). This monitors any changes in your Node.js application and automatically restarts the server when changes are saved.\n\n5. This app uses a JavaScript prompt to get a room name. Work out a way to get the room name from the URL, for example _localhost:2013/foo_ would give the room name _foo_.\n\n## Step 6: RTCPeerConnection with messaging\n\nComplete example: [complete/step6](https://bitbucket.org/webrtc/codelab/src/master/complete/step6).\n\nIn this step, we build a video chat client, using the signaling server we created in Step 5 and the RTCPeerConnection code from Step 3.\n\n**This step users [adapter.js](https://bitbucket.org/webrtc/codelab/src/master/complete/step6/js/lib/adapter.js). This is a [JavaScript shim](http://stackoverflow.com/questions/6599815/what-is-the-difference-between-a-shim-and-a-polyfill), maintained by Google, that abstracts away browser differences and spec changes.**\n\n1. Ensure you have Node, socket.io and [node-static](https://github.com/cloudhead/node-static) installed and working. If in doubt, try the code in Step 5.\n\n2. Using the code from the _step 6_ directory, run the server (_server.js_). To start the server, run the following from your application directory:\n\n        node server.js\n\n3. From your browser, open [localhost:2013](http://localhost:2013). Open a new tab page or window and open [localhost:2013](http://localhost:2013) again.\n\n4. View logging from the Chrome DevTools console and WebRTC debug information from chrome://webrtc-internals.\n\n### Bonus points\n\n1. This application only supports one-to-one video chat. How might you change the design to enable more than one person to share the same video chat room? (Look at [talky.io](http://talky.io) for an example of this in action.)\n\n2. The example has the room name _foo_ hard coded. What would be the best way to enable other room names?\n\n3. Does the app work on mobile? Try it out on a phone, on a 7\" and a 10\" tablet. What layout, UI and UX changes would be required to ensure a good mobile experience?\n\n4. Deploy your app at a public URL (see above for hosting options). Try different network configurations, for example with one user on wifi and another on 3G. Any problems?\n\n5. How would users share the room name? Try to build an alternative to sharing room names.\n\n## Step 7: Putting it all together: RTCPeerConnection + RTCDataChannel + signaling\n\nThis is a DIY step!\n\n1. Take a look at the app you built in step 4.\n\n2. Add the RTCDataChannel code to your Step 6 app to create a complete application.\n\n\n### Bonus points\n\n1. The app hasn't had any work done on layout. Sort it out! Make sure your app works well on different devices.\n\n\n\n\n## Step 8: Use a WebRTC library: SimpleWebRTC\n\nComplete example: [complete/step8.html](https://bitbucket.org/webrtc/codelab/src/master/complete/step8.html).\n\nAbstraction libraries such as SimpleWebRTC make it simple to create WebRTC applications.\n\n1. Create a new document using the code from [complete/step8.html](https://bitbucket.org/webrtc/codelab/src/master/complete/step8.html).\n2. Open the document in multiple windows or tab.\n\n### Bonus points\n\n1. Find a WebRTC library for RTCDataChannel. (Hint: there's one named PeerJS!)\n2. Set up your own signaling server using the SimpleWebRTC server [signalmaster](https://github.com/andyet/signalmaster).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamsamskies%2Fwebrtc-codelab","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsamsamskies%2Fwebrtc-codelab","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamsamskies%2Fwebrtc-codelab/lists"}