487

WebRTC Cookbook

  • Upload
    dokhue

  • View
    325

  • Download
    15

Embed Size (px)

Citation preview

Page 1: WebRTC Cookbook
Page 2: WebRTC Cookbook
Page 3: WebRTC Cookbook

WebRTCCookbook

Page 4: WebRTC Cookbook

TableofContents

WebRTCCookbook

Credits

AbouttheAuthor

AbouttheReviewers

www.PacktPub.com

Supportfiles,eBooks,discountoffers,andmore

WhySubscribe?

FreeAccessforPacktaccountholders

Preface

Whatthisbookcovers

Whatyouneedforthisbook

Whothisbookisfor

Conventions

Readerfeedback

Customersupport

Downloadingtheexamplecode

Downloadingthecolorimagesofthisbook

Errata

Piracy

Questions

1.PeerConnections

Introduction

BuildingasignalingserverinErlang

Gettingready

Howtodoit…

Howitworks…

There’smore…

Seealso

BuildingasignalingserverinJava

Page 5: WebRTC Cookbook

Gettingready

Howtodoit…

Howitworks…

There’smore…

Seealso

DetectingWebRTCfunctionssupportedbyabrowser

Gettingready

Howtodoit…

Howitworks…

There’smore…

Seealso

Makingandansweringcalls

Gettingready

Howtodoit…

Makingacall

Answeringacall

Howitworks…

There’smore…

Seealso

Implementingachatusingdatachannels

Gettingready

Howtodoit…

CreatingthemainHTMLpageoftheapplication

CreatingtheJavaScripthelperlibrary

Howitworks…

There’smore…

Seealso

Implementingachatusingasignalingserver

Howtodoit…

Howitworks…

There’smore…

Page 6: WebRTC Cookbook

Seealso

ConfiguringandusingSTUN

Gettingready

Howtodoit…

Howitworks…

There’smore…

Seealso

ConfiguringandusingTURN

Gettingready

Howtodoit…

InstallingtheTURNserver

UsingTURNinWebRTCapplication

Howitworks…

There’smore…

Seealso

2.SupportingSecurity

Introduction

Generatingaself-signedcertificate

Gettingready

Howtodoit…

Howitworks…

There’smore…

Seealso

ConfiguringaTURNserverwithauthentication

Gettingready

Howtodoit…

Implementingtheclient-sidecode

Implementingtheserver-sidecode

Howitworks…

There’smore…

Seealso

Page 7: WebRTC Cookbook

ConfiguringawebservertoworkoverHTTPS

Gettingready

Howtodoit…

ConfiguringNginx

ConfiguringApache

ConfiguringIIS

There’smore…

Seealso

ConfiguringaWebSocketsproxyonthewebserver

Gettingready

Howtodoit…

ConfiguringNginx

ConfiguringApache

ConfiguringIIS

Howitworks…

There’smore…

Seealso

Configuringafirewall

Gettingready

Howtodoit…

Configuringafirewallonaserver

Configuringafirewallonaclient

Seealso

3.IntegratingWebRTC

Introduction

IntegratingWebRTCwithAsterisk

Gettingready

Howtodoit…

InstallinglibSRTP

InstallingAsterisk

Howitworks…

Page 8: WebRTC Cookbook

There’smore…

Seealso

IntegratingWebRTCwithFreeSWITCH

Gettingready

Howtodoit…

InstallingFreeSWITCH

EnablingWebRTC

StartingFreeSWITCH

Howitworks…

There’smore…

Seealso

Makingcallsfromawebpage

Gettingready

Howtodoit…

InstallingsipML5

Howitworks…

There’smore…

Seealso

IntegrationofWebRTCwithwebcameras

Gettingready

Howtodoit…

Configuringthewebcam

InstallingWebRTCmediaserver

Timeformagic

Howitworks…

There’smore…

4.DebuggingaWebRTCApplication

Introduction

WorkingwithaWebRTCstatisticsAPI

Gettingready

Howtodoit…

Page 9: WebRTC Cookbook

Checkingestimatedbandwidth

Checkingpacketloss

Howitworks…

There’smore…

Seealso

DebuggingwithChrome

Gettingready

Howtodoit…

Usingwebrtc-internals

UsingChromeloggingmechanism

Howitworks…

There’smore…

Seealso

DebuggingTURN

Gettingready

Howtodoit…

Howitworks…

There’smore…

Seealso

DebuggingusingWireshark

Gettingready

Howtodoit…

Howitworks…

There’smore…

Seealso

5.WorkingwithFilters

Introduction

Workingwithcolorsandgrayscale

Howtodoit…

Howitworks…

Workingwithbrightness

Page 10: WebRTC Cookbook

Howtodoit…

Howitworks…

Workingwithcontrast

Howtodoit…

Howitworks…

Workingwithsaturation

Howtodoit…

Howitworks…

Workingwithhue

Howtodoit…

Howitworks…

Usingthesepiafilter

Howtodoit…

Howitworks…

Usingtheopacityfilter

Howtodoit…

Howitworks…

Invertingcolors

Howtodoit…

Howitworks…

Implementingtheblureffect

Howtodoit…

Howitworks…

Implementingthedroppedshadoweffect

Howtodoit…

Howitworks…

Combiningfilters

Howtodoit…

Howitworks…

Customvideoprocessing

Howtodoit…

Page 11: WebRTC Cookbook

Howitworks…

6.NativeApplications

Introduction

BuildingacustomizedWebRTCdemoforiOS

Gettingready

Howtodoit…

There’smore…

BuildingademoprojectforaiOSsimulator

Seealso

CompilingandrunninganoriginaldemoforiOS

Gettingready

Howtodoit…

BuildingademoprojectforaniOSdevice

BuildingademoprojectforaniOSsimulator

There’smore…

Seealso

CompilingandrunningademoforAndroid

Gettingready

Preparingthesystem

InstallingOracleJDK

GettingtheWebRTCsourcecode

InstallingAndroidDeveloperTools

Howtodoit…

RunningontheAndroidsimulator

FixingabugwithGLSurfaceView

RunningonaphysicalAndroiddevice

There’smore…

Seealso

BuildinganOpenWebRTClibrary

Gettingready

Howtodoit…

Page 12: WebRTC Cookbook

There’smore…

7.Third-partyLibraries

Introduction

BuildingavideoconferenceusingSimpleWebRTC

Gettingready

Howtodoit…

Howitworks…

There’smore…

CreatinganapplicationusingRTCMultiConnection

Gettingready

Howtodoit…

Howitworks…

There’smore…

DevelopingasimpleWebRTCchatusingPeerJS

Gettingready

Howtodoit…

Howitworks…

There’smore…

Makingasimplevideochatwithrtc.io

Gettingready

Howtodoit…

Howitworks…

There’smore…

UsingOpenToktocreateaWebRTCapplication

Gettingready

Howtodoit…

Howitworks…

There’smore…

CreatingamultiuserconferenceusingWebRTCO

Gettingready

Howtodoit…

Page 13: WebRTC Cookbook

Howitworks…

There’smore…

8.AdvancedFunctions

Introduction

Visualizingamicrophone’ssoundlevel

Gettingready

Howtodoit…

Howitworks…

Seealso

Mutingamicrophone

Gettingready

Howtodoit…

Howitworks…

There’smore…

Seealso

Pausingavideo

Gettingready

Howtodoit…

Howitworks…

Seealso

Takingascreenshot

Gettingready

Howtodoit…

Howitworks…

Seealso

Streamingmedia

Gettingready

Howtodoit…

Howitworks…

Seealso

Index

Page 14: WebRTC Cookbook
Page 15: WebRTC Cookbook

WebRTCCookbook

Page 16: WebRTC Cookbook
Page 17: WebRTC Cookbook

WebRTCCookbookCopyright©2015PacktPublishing

Allrightsreserved.Nopartofthisbookmaybereproduced,storedinaretrievalsystem,ortransmittedinanyformorbyanymeans,withoutthepriorwrittenpermissionofthepublisher,exceptinthecaseofbriefquotationsembeddedincriticalarticlesorreviews.

Everyefforthasbeenmadeinthepreparationofthisbooktoensuretheaccuracyoftheinformationpresented.However,theinformationcontainedinthisbookissoldwithoutwarranty,eitherexpressorimplied.Neithertheauthor,norPacktPublishing,anditsdealersanddistributorswillbeheldliableforanydamagescausedorallegedtobecauseddirectlyorindirectlybythisbook.

PacktPublishinghasendeavoredtoprovidetrademarkinformationaboutallofthecompaniesandproductsmentionedinthisbookbytheappropriateuseofcapitals.However,PacktPublishingcannotguaranteetheaccuracyofthisinformation.

Firstpublished:February2015

Productionreference:1200215

PublishedbyPacktPublishingLtd.

LiveryPlace

35LiveryStreet

BirminghamB32PB,UK.

ISBN978-1-78328-445-0

www.packtpub.com

Page 18: WebRTC Cookbook
Page 19: WebRTC Cookbook

CreditsAuthor

AndriiSergiienko

Reviewers

PasqualeBoemio

JoseLópez

MarcosdeVeraPiquero

CommissioningEditor

UshaIyer

AcquisitionEditor

SamWood

ContentDevelopmentEditor

RahulNair

TechnicalEditor

SiddhiRane

CopyEditor

NehaVyas

ProjectCoordinator

JudieJose

Proofreaders

TingBaker

SimranBhogal

MariaGould

PaulHindle

Indexer

HemanginiBari

ProductionCoordinator

MelwynDsa

CoverWork

MelwynDsa

Page 20: WebRTC Cookbook
Page 21: WebRTC Cookbook

AbouttheAuthorAndriiSergiienkoisacomputersoftwaredeveloperfromUkraineandispassionateaboutinformationtechnologies.Fromhisearlychildhood,hewasinterestedincomputerprogrammingandhardware.Hetookhisfirststepintothesefieldsmorethan20yearsago.HehasexperienceofawidesetoflanguagesandtechnologiesincludingC,C++,Java,assemblylanguage,Erlang,JavaScript,PHP,Riak,shellscripting,computernetworks,andsecurity.

Duringhiscareerheworkedforbothsmall,localcompaniessuchasdomesticISPandlarge,worldwidecorporationssuchasHewlettPackard.Healsostartedhisownprojects—someofthemwererelativelysuccessful.

Today,heistheownerandinspirerofOSLIKASOÜ,acomputersoftwarecompanywithheadquartersinEstonia.Thecompany(http://www.oslikas.com)focusesonmodernITtechnologiesandsolutions.

Workingonthisbookwasareallygreatandinterestingexperienceforme.Allthiswouldbeimpossiblewithoutthehelpofcertainpeople.Andnowisthetimeformetosaythankyoutothem.

Firstofall,IwouldliketothankmyparentsOlgaandAlexanderformyhappychildhoodthatestablishedthefoundationformylifeandcareer.

IwouldliketosaythankyoutomywifeInnaforherpatience,encouragement,andsupportduringthisprocess.

IwouldliketothankthePacktPublishingteamaswell.Theseguysaredoingreallygreatworkandmakingtheworldabetterplace.Wecontactedsomeofthemdirectlyduringthework,andothersstayedbehindthescenes.However,Iknowthatalotofpeoplespentpartoftheirlivestomakethisbookpossible.Thankyouall.

Page 22: WebRTC Cookbook
Page 23: WebRTC Cookbook

AbouttheReviewersPasqualeBoemiofellinlovewithLinuxandtheopensourcephilosophyattheageof12.Followingthispassion,hestudiedcomputerengineeringatUniversityofNaplesFedericoIIfromwherehegraduatedwithamaster’sdegree.

Currently,heisworkingasaresearcherintheDepartmentofElectricalEngineeringandInformationTechnology(DIETI)intheUniversityofNaplesFedericoII,contributingtothedevelopmentofreal-timecommunicationtechnologies.HiseffortsinthisfieldareconcretizedbysupportingtheMeetechoproject(www.meetecho.com).

Meetechoisauniversityspin-offandatoolforthecollaborativeworkcurrentlyusedbytheInternetEngineeringTaskForce(IETF)toprovideremoteparticipationtotheworkinggroups.Meetecholeveragessomestate-of-the-arttechnologies(suchasWebRTCandDocker)toimplementacomprehensivearchitecturethatcanbelightweightandportable.Meetecho’sbestprojectistheJanusWebRTCGateway(http://janus.conf.meetecho.com/),mentionedlaterinthisbook,whichallowsausertheabilitytointegratedifferent,real-timetechnologieswithoutanypains.

Inhissparetime,Pasqualeworksonsomepersonalopensourceprojects(https://github.com/helloIAmPau)andhelpsthecommunitybygivinghiscontributionstocoolprojectsfoundontheGitHubplatform.

HehasalreadyworkedwithPacktPublishingbyreviewingWebRTCIntegrator’sGuide,ausefulguideforanyonewhoneedstointegrateWebRTCwitharetrotechnologysuchasSIP.

JoseLópezwasborninGalicia,Spain.Heisatelecommunicationsengineerwithalargeamountofexperienceinsoftwaredevelopment,andisalsofocusedonreal-timeaudio/videocommunications.HestartedworkingforQuobisNetworksin2013,aleadingcompanyinWebRTCsolutions.

MarcosdeVeraPiqueroisasoftwareengineerwhohasmainlyworkedwithPythonandCoffeeScript.Hisareaofdevelopmentisnowfocusedontheserversideofreal-timemultimediaapplicationsatQuobis,hiscurrentemployer.He’salsoafreesoftwareenthusiastandistryingtomakeitarealalternative.

Page 24: WebRTC Cookbook
Page 25: WebRTC Cookbook

www.PacktPub.com

Page 26: WebRTC Cookbook

Supportfiles,eBooks,discountoffers,andmoreForsupportfilesanddownloadsrelatedtoyourbook,pleasevisitwww.PacktPub.com.

DidyouknowthatPacktofferseBookversionsofeverybookpublished,withPDFandePubfilesavailable?YoucanupgradetotheeBookversionatwww.PacktPub.comandasaprintbookcustomer,youareentitledtoadiscountontheeBookcopy.Getintouchwithusat<[email protected]>formoredetails.

Atwww.PacktPub.com,youcanalsoreadacollectionoffreetechnicalarticles,signupforarangeoffreenewslettersandreceiveexclusivediscountsandoffersonPacktbooksandeBooks.

https://www2.packtpub.com/books/subscription/packtlib

DoyouneedinstantsolutionstoyourITquestions?PacktLibisPackt’sonlinedigitalbooklibrary.Here,youcansearch,access,andreadPackt’sentirelibraryofbooks.

Page 27: WebRTC Cookbook

WhySubscribe?FullysearchableacrosseverybookpublishedbyPacktCopyandpaste,print,andbookmarkcontentOndemandandaccessibleviaawebbrowser

Page 28: WebRTC Cookbook

FreeAccessforPacktaccountholdersIfyouhaveanaccountwithPacktatwww.PacktPub.com,youcanusethistoaccessPacktLibtodayandview9entirelyfreebooks.Simplyuseyourlogincredentialsforimmediateaccess.

Page 29: WebRTC Cookbook
Page 30: WebRTC Cookbook

PrefaceWebRTCisarelativelynewandrevolutionarytechnologythatopensnewhorizonsintheareaofinteractiveapplicationsandservices.Mostofthepopularwebbrowserssupportitnatively(suchasChromeandFirefox)orviaextensions(suchasSafari).MobileplatformssuchasAndroidandiOSallowyoutodevelopnativeWebRTCapplications.

ThisbookcoversawidesetoftopicsonhowtodevelopsoftwareusingaWebRTCstack.Usingpracticalrecipes,itconsidersbasicconcepts,security,debugging,integrationwithothertechnologies,andotherimportantthemesofthedevelopmentprocessinafriendlymanner.

YouwillnotonlylearnaboutWebRTC-specificfeatures,butalsoattendanttechnologies(CSS3,HTML5,andWebSockets),andhowtousethemalongwithWebRTC.

Page 31: WebRTC Cookbook

WhatthisbookcoversChapter1,PeerConnections,introducesyoutotheverybasicconceptsofWebRTC.Thisincludespracticalrecipesonpeerconnections.Youwillalsofindsimpledemoapplicationsinthischapter.

Chapter2,SupportingSecurity,leadsyouthroughvarioussecurity-relatedtopicsandcovershowtosecureatypicalWebRTCapplication’sinfrastructurecomponents:SSL/TLScertificates,WebSockets,webservers,STUN/TURN,datachannels,andmore.

Chapter3,IntegratingWebRTC,considersintegratingaWebRTCapplicationwithothertechnologiesandthird-partysoftware.Thischapterdescribespracticalcasesandsolutionsonintegration.

Chapter4,DebuggingaWebRTCApplication,isdedicatedtoapplicationdebugging—animportanttopicofthesoftwaredevelopmentprocess.Inthischapter,youwilllearnaboutthetopicsrelatingtodebugginginthescopeofWebRTC.

Chapter5,WorkingwithFilters,teachesyouhowtouseCSS3filterswithWebRTCapplications.Thischapteralsocoverscustomimageprocessing.

Chapter6,NativeApplications,containspractical,step-by-steprecipesdedicatedtodevelopingnativeWebRTCapplicationsonmobileplatforms.

Chapter7,Third-partyLibraries,describesgeneralusecasesandpracticalsolutionsbasedonthird-partyWebRTCframeworksandservices.

Chapter8,AdvancedFunctions,covershowtouseadvancedWebRTCfeatures.Itcontainspracticalrecipesonfiletransferring,streaming,audio/videocontrolling,andmore.

Page 32: WebRTC Cookbook
Page 33: WebRTC Cookbook

WhatyouneedforthisbookTousetherecipesandcodesprovidedandconsideredinthisbook,youwillneedafewpiecesofsoftwareinstalled:

JavaSE7:NotethatforAndroid-relatedrecipesfromChapter6,NativeApplications,youneedJavaSE6aswell—theinstallationandconfigurationprocessisdescribedindetailinthischapter.ErlangOTP17:Ifyou’refamiliarwiththisprogramminglanguage,youcanusethis.Ifnot,youcanskipit—allErlangexamplesarealsoprovidedinJava.MacOSXandXcode:UsethisforrecipesdedicatedtodevelopingWebRTCapplicationsoniOS.AndroidandiOS:UsethisforChapter6,NativeApplications,whichcovershowtodevelopWebRTCapplicationsformobileplatforms.Linux:Ubuntuisrecommended.ChromeandFirefox:ThesearestillthemostWebRTC-friendlywebbrowsers.

Specificrequirementsandconfigurationsalongwithsuggestedsolutionsareconsideredinparticularchapters.

Page 34: WebRTC Cookbook
Page 35: WebRTC Cookbook

WhothisbookisforThisbookiswrittenasasetofready-to-use,practicalrecipesthatcoveravarietyoftopicsrelatedtodevelopingWebRTCapplicationsandservices.Itisassumedthatyouarefamiliar,ingeneral,withWebRTCanditsbasicconcepts.

MostoftheprovidedrecipesarewritteninJavaScript.However,server-sidepartsofapplicationsareimplementedinErlangandJava.So,youareassumedtohaveatleastbasicexperiencewithoneofthesetechnologies.

Workingonsomecasesdescribedinthisbook,youwillhavetodealwithaLinux-basedOS.Allrecipesareprovidedasastep-by-stepguide.Although,ifyouhaveexperienceofworkingwithandconfiguringLinux-basedboxes,itwouldbeuseful.

So,thisbookisforsomeonewhoisfamiliar,ingeneral,withtheWebRTCstack,andwhohasatleastbasicskillsinsoftwaredevelopment.

Page 36: WebRTC Cookbook
Page 37: WebRTC Cookbook

ConventionsInthisbook,youwillfindanumberofstylesoftextthatdistinguishbetweendifferentkindsofinformation.Herearesomeexamplesofthesestyles,andanexplanationoftheirmeaning.

Codewordsintext,databasetablenames,foldernames,filenames,fileextensions,pathnames,dummyURLs,userinput,andTwitterhandlesareshownasfollows:“WecanincludeourcustomJavaScriptlibrarylocatedinthemylib.jsfile.”

Ablockofcodeissetasfollows:

-module(sigserver_app).

-behaviour(application).

-export([start/2,stop/1,start/0]).

start()->

ok=application:start(ranch),

ok=application:start(crypto),

ok=application:start(cowlib),

ok=application:start(cowboy),

Whenwewishtodrawyourattentiontoaparticularpartofacodeblock,therelevantlinesoritemsaresetinbold:

privatestaticMap<Integer,Set<WebSocket>>Rooms=newHashMap<>();

privateintmyroom;

publicMain(){

super(newInetSocketAddress(30001));

}

Anycommand-lineinputoroutputiswrittenasfollows:

rebarcreate-appappid=sigserver

Newtermsandimportantwordsareshowninbold.Wordsthatyouseeonthescreen,inmenusordialogboxesforexample,appearinthetextlikethis:“WhenthecustomerentersamessageandclicksontheSubmitquerybutton,wewillwrapthemessageintoaJSONobjectandsenditviathedatachannel.”

NoteWarningsorimportantnotesappearinaboxlikethis.

TipTipsandtricksappearlikethis.

Page 38: WebRTC Cookbook
Page 39: WebRTC Cookbook

ReaderfeedbackFeedbackfromourreadersisalwayswelcome.Letusknowwhatyouthinkaboutthisbook—whatyoulikedordisliked.Readerfeedbackisimportantforusasithelpsusdeveloptitlesthatyouwillreallygetthemostoutof.

Tosendusgeneralfeedback,simplye-mail<[email protected]>,andmentionthebook’stitleinthesubjectofyourmessage.

Ifthereisatopicthatyouhaveexpertiseinandyouareinterestedineitherwritingorcontributingtoabook,seeourauthorguideatwww.packtpub.com/authors.

Page 40: WebRTC Cookbook
Page 41: WebRTC Cookbook

CustomersupportNowthatyouaretheproudownerofaPacktbook,wehaveanumberofthingstohelpyoutogetthemostfromyourpurchase.

Page 42: WebRTC Cookbook

DownloadingtheexamplecodeYoucandownloadtheexamplecodefilesfromyouraccountathttp://www.packtpub.comforallthePacktPublishingbooksyouhavepurchased.Ifyoupurchasedthisbookelsewhere,youcanvisithttp://www.packtpub.com/supportandregistertohavethefilese-maileddirectlytoyou.

Page 43: WebRTC Cookbook

DownloadingthecolorimagesofthisbookWealsoprovideyouwithaPDFfilethathascolorimagesofthescreenshots/diagramsusedinthisbook.Thecolorimageswillhelpyoubetterunderstandthechangesintheoutput.Youcandownloadthisfilefrom:https://www.packtpub.com/sites/default/files/downloads/4450OS_ColoredImages.pdf.

Page 44: WebRTC Cookbook

ErrataAlthoughwehavetakeneverycaretoensuretheaccuracyofourcontent,mistakesdohappen.Ifyoufindamistakeinoneofourbooks—maybeamistakeinthetextorthecode—wewouldbegratefulifyoucouldreportthistous.Bydoingso,youcansaveotherreadersfromfrustrationandhelpusimprovesubsequentversionsofthisbook.Ifyoufindanyerrata,pleasereportthembyvisitinghttp://www.packtpub.com/submit-errata,selectingyourbook,clickingontheErrataSubmissionFormlink,andenteringthedetailsofyourerrata.Onceyourerrataareverified,yoursubmissionwillbeacceptedandtheerratawillbeuploadedtoourwebsiteoraddedtoanylistofexistingerrataundertheErratasectionofthattitle.

Toviewthepreviouslysubmittederrata,gotohttps://www.packtpub.com/books/content/supportandenterthenameofthebookinthesearchfield.TherequiredinformationwillappearundertheErratasection.

Page 45: WebRTC Cookbook

PiracyPiracyofcopyrightedmaterialontheInternetisanongoingproblemacrossallmedia.AtPackt,wetaketheprotectionofourcopyrightandlicensesveryseriously.IfyoucomeacrossanyillegalcopiesofourworksinanyformontheInternet,pleaseprovideuswiththelocationaddressorwebsitenameimmediatelysothatwecanpursuearemedy.

Pleasecontactusat<[email protected]>withalinktothesuspectedpiratedmaterial.

Weappreciateyourhelpinprotectingourauthorsandourabilitytobringyouvaluablecontent.

Page 46: WebRTC Cookbook

QuestionsIfyouhaveaproblemwithanyaspectofthisbook,youcancontactusat<[email protected]>,andwewilldoourbesttoaddresstheproblem.

Page 47: WebRTC Cookbook
Page 48: WebRTC Cookbook

Chapter1.PeerConnectionsInthischapter,wewillcoverthefollowingtopics:

BuildingasignalingserverinErlangBuildingasignalingserverinJavaDetectingWebRTCfunctionssupportedbyabrowserMakingandansweringcallsImplementingachatusingdatachannelsImplementingachatusingasignalingserverConfiguringandusingSTUNConfiguringandusingTURN

Page 49: WebRTC Cookbook

IntroductionThischaptercoversthebasicconceptsofhowtouseWebRTCwhendevelopingrichmediawebapplicationsandservices.

Withsimpleandshortrecipes,youwilllearnhowtocreateyourownsignalingserver.Thekeydatathatneedstobeexchangedbypeersbeforetheyestablishadirectconnectioniscalledthesessiondescription—itspecifiesthepeers’configuration.Signalingserverisacomponentinanapplication’sinfrastructurethatisaccessiblebyallpeersandservestoexchangemultimedia’ssessiondescription.ThewaypeersshouldexchangedataisnotdescribedbyWebRTCstandards,soyoushouldmakethedecisiononyourownregardingtheprotocolandmechanismyouwilluseforthistask.

Youcanbuildasignalingserverusinganyprogramminglanguageandtechnologyyoulike.Ingeneral,thesignalingprotocolcanbenon-technicalandispossibletoimplementinawaywherethepeerswouldusejustasheetofpapertoexchangenecessarydatabetweeneachother.Inthischapter,weuseWebSockettoimplementsignaling,althoughyoucanuseanyotherprotocol.

Thesignalingstageisrepresentedintheschemathatisshowninthefollowingdiagram:

Inthischapter,youwillfindtworecipesthatarededicatedtosignalingserverdevelopment:BuildingasignalingserverinErlangandBuildingasignalingserverinJava.Javaisprobablythemostpopularandknowntechnology,anditwouldbeeasytogetintothistopicusingJava,evenifyoudon’thaveprogrammingexperiencewiththistechnology.Erlangisnotwidelyknownyet.Nonetheless,thisisaverymaturetechnology,verysuitableforwritinglightweightandextremelyfastserverapplicationswithperfect

Page 50: WebRTC Cookbook

scalability.So,bylearningsignalingserver,youwillfindsimplesolutionsinErlangaswell.

ThischapteralsocoversthebasicusecaseofhowtouseWebRTCdatachannels:filetransferringandpeer-to-peerchat.

YouwillalsolearnhowtoconfigureanduseSessionTraversalUtilitiesforNAT(STUN)andTraversalUsingRelaysaroundNAT(TURN)services,andofcourse,thischaptercoversmakingpeer-to-peercallsusingWebRTC.

Notethatinthischapter,wewillcovertheprocessofmakingcomputer-to-computercalls.IfyouwanttoknowmoreabouthowtouseWebRTCwithVoIPandSIP,andhowtomakephonecallsfromawebpage,refertotheChapter3,IntegratingWebRTC.

Page 51: WebRTC Cookbook
Page 52: WebRTC Cookbook

BuildingasignalingserverinErlangThefollowingrecipeshowshowtobuildsignalingserverusingErlangprogramminglanguageandWebSocketsfortransportprotocol.WewillnotintroduceErlangprogramminginthisrecipe,soyoushouldhaveatleastbasicknowledgeofthisprogramminglanguageanditsrelevanttechnologies.

Page 53: WebRTC Cookbook

GettingreadyTousethissolution,youshouldhaveErlanginstalledonyoursystemtostartwith.YoucandownloadtheErlangdistributionrelevanttoyoursystemfromitshomepagehttp://www.erlang.org/download.html.Theinstallationprocessmightneedspecificactionsrelevanttospecificplatforms/OSes,sofollowtheofficialinstallationinstructionsathttp://www.erlang.org/doc/installation_guide/INSTALL.html.

TipForthisexample,I’veusedErlang17.YoumightneedtoaddsomeminorchangestothecodetomakeitworkunderfutureversionsofErlang.

WewillalsousetheGitversioningsystemtodownloadadditionalpacketsandcomponentsnecessaryforoursolution,soyoushoulddownloadandinstallGitdistributionrelevanttoyoursystem.Youcandownloadthisfromhttp://www.git-scm.com.Asabuildtoolfortheproject,wewilluseRebar;youshouldalsodownloadandinstallitfromhttps://github.com/basho/rebar.

Page 54: WebRTC Cookbook

Howtodoit…ThefollowingstepswillleadyouthroughtheprocessofbuildingasignalingserverusingErlang:

1. Createanewfolderforthesignalingserverapplicationandnavigatetoit.2. UsingtheRebartool,createabasicErlangapplication:

rebarcreate-appappid=sigserver

Thiscommandwillcreateansrcfolderandrelevantapplicationfilesinit.

3. Createtherebar.configfile,andputthefollowingRebarconfigurationinit:

{erl_opts,[warnings_as_errors]}.

{deps,

[

{'gproc',".*",{

git,"git://github.com/esl/gproc.git",{tag,"0.2.16"}

}},

{'jsonerl',".*",{

git,"git://github.com/fycth/jsonerl.git","master"

}},

{'cowboy',".*",{

git,"https://github.com/extend/cowboy.git","0.9.0"

}}

]}.

4. Openthesrc/sigserver.app.srcfileandaddthefollowingcomponentstotheapplication’ssectionlist:cowlib,cowboy,compiler,andgproc.

5. Openthesrc/sigserver_app.erlfileandaddthefollowingcode:

-module(sigserver_app).

-behaviour(application).

-export([start/2,stop/1,start/0]).

start()->

ok=application:start(ranch),

ok=application:start(crypto),

ok=application:start(cowlib),

ok=application:start(cowboy),

ok=application:start(gproc),

ok=application:start(compiler),

ok=application:start(sigserver).

start(_StartType,_StartArgs)->

Dispatch=cowboy_router:compile([

{'_',[

{"/",handler_websocket,[]}

]}

]),

{ok,_}=cowboy:start_http(websocket,100,[{ip,{127,0,0,1}},

{port,30001}],[

{env,[{dispatch,Dispatch}]},

{max_keepalive,50},

{timeout,500}]),

Page 55: WebRTC Cookbook

sigserver_sup:start_link().

stop(_State)->ok.

6. Createthesrc/handler_websocket.erlfileandputthefollowingcodeinit:

-module(handler_websocket).

-behaviour(cowboy_websocket_handler).

-export([init/3]).

-export([websocket_init/3,websocket_handle/3,

websocket_info/3,websocket_terminate/3]).

-record(state,{

client=undefined::undefined|binary(),

state=undefined::undefined|connected|running,

room=undefined::undefined|integer()

}).

init(_Any,_Req,_Opt)->

{upgrade,protocol,cowboy_websocket}.

websocket_init(_TransportName,Req,_Opt)->

{Client,Req1}=cowboy_req:header(<<"x-forwarded-for">>,Req),

State=#state{client=Client,state=connected},

{ok,Req1,State,hibernate}.

websocket_handle({text,Data},Req,State)->

StateNew=case(State#state.state)of

started->

State#state{state=running};

_->

State

end,

JSON=jsonerl:decode(Data),

{M,Type}=element(1,JSON),

caseMof

<<"type">>->

caseTypeof

<<"GETROOM">>->

Room=generate_room(),

R=iolist_to_binary(jsonerl:encode({{type,

<<"GETROOM">>},{value,Room}})),

gproc:reg({p,l,Room}),

S=(StateNew#state{room=Room}),

{reply,{text,<<R/binary>>},Req,S,hibernate};

<<"ENTERROOM">>->

{<<"value">>,Room}=element(2,JSON),

Participants=gproc:lookup_pids({p,l,Room}),

caselength(Participants)of

1->

gproc:reg({p,l,Room}),

S=(StateNew#state{room=Room}),

{ok,Req,S,hibernate};

_->

R=iolist_to_binary(jsonerl:encode({{type,

<<"WRONGROOM">>}})),

Page 56: WebRTC Cookbook

{reply,{text,<<R/binary>>},Req,

StateNew,hibernate}

end;

_->

reply2peer(Data,StateNew#state.room),

{ok,Req,StateNew,hibernate}

end;

_->

reply2peer(Data,State#state.room),

{ok,Req,StateNew,hibernate}

end;

websocket_handle(_Any,Req,State)->{ok,Req,State,hibernate}.

websocket_info(_Info,Req,State)->{reply,{text,_Info},Req,State,

hibernate}.

websocket_terminate(_Reason,_Req,_State)->ok.

reply2peer(R,Room)->

[P!<<R/binary>>||P<-gproc:lookup_pids({p,l,Room})—[self()]].

generate_room()->

random:seed(now()),

random:uniform(999999).

7. NowwecancompilethesolutionusingtheRebartool:

rebarget-deps

rebarcompile

Ifeverythingwassuccessful,youshouldnotseeanyerrors(warningsarenotcritical).

8. Afterwebuildoursignalingserver,wecanstartitusingthefollowingcommand:

erl-padeps/*/ebinebin-saslerrlog_typeerror-ssigserver_app

TipWindows-basedsystemscan’tuseastarsymbolinsuchconstructions,soifyou’reworkingunderWindows,youshouldusethefullpathnameasshowninthefollowingcommand:

erl-padeps/cowboy/ebindeps/cowlib/ebindeps/gproc/ebin

deps/jsonerl/ebindeps/ranch/ebinebin-saslerrlog_typeerror-s

sigserver_app

Nowyoursignalingservershouldberunning,andyouneedtolistenforincomingWebSocketconnectionsonport30001.

Notethatfullsourcecodesaresuppliedwiththisbook.

TipDownloadingtheexamplecode

Page 57: WebRTC Cookbook

Youcandownloadtheexamplecodefilesfromyouraccountathttp://www.packtpub.comforallthePacktPublishingbooksyouhavepurchased.Ifyoupurchasedthisbookelsewhere,youcanvisithttp://www.packtpub.com/supportandregistertohavethefilese-maileddirectlytoyou.

Page 58: WebRTC Cookbook

Howitworks…Inthisrecipe,weimplementedtheWebRTCsignalingserverinErlang.Theapplicationlistensonport30001forincomingWebSocketconnectionsfromthebrowserclients.

Thefirstpeerwillberegisteredbytheserverinavirtualroomandwillgettheroomnumber.Thesecondpeerafterthatcanusetheroomnumberinordertoconnecttothefirstpeer.Thesignalingserverwillcheckwhetherthevirtualroomexistsandifso,itwillroutecall/answerrequestsandanswersbetweenthepeersinordertomakethemestablishadirectpeer-to-peerWebRTCconnection.

Page 59: WebRTC Cookbook

There’smore…Basically,thisisaverysimplesignalingserver.Itdoesn’thaveanyadvancedfeatures,andthemaingoalofitistohelppeersestablishdirectconnectionbetweeneachother.Nevertheless,asignalingservercanserveadditionaltasks.Forexample,itcanserveforwebchats,filetransfers,servicedataexchanges,andotherfeaturesspecificforcertainsituations.Therearenocertainrequirementsforasignalingserver;youcanimplementitusingyourfavoriteprogramminglanguageandtechnology.

Page 60: WebRTC Cookbook

SeealsoFortipsonimplementingasignalingserverinJava,refertotheBuildingasignalingserverinJavarecipeYoucanalsorefertotheMakingandansweringcallsrecipeonhowtouseasignalingserverfromabrowserapplicationusingJavaScript

Page 61: WebRTC Cookbook
Page 62: WebRTC Cookbook

BuildingasignalingserverinJavaInthisrecipe,wewillcovertheimplementationofasignalingserverinJava.

Page 63: WebRTC Cookbook

GettingreadyThisrecipeusesJava,soyoushouldhaveJavaDeveloperKit(JDK)installedonyourmachine.YoucandownloadtheappropriateversionofJDKforyourplatformfromitswebpageathttp://www.java.com.

Java7hasitsownAPItoimplementaWebSocketapplication.PreviousversionsofJavadon’thavethenativesupportofWebSockets.Inthisrecipe,wewillcovertheuniversalsolutionthatworksindifferentJavaversionsandisbasedonthethird-partycomponent,whichyoucanfindonitshomepageathttp://java-websocket.org.ThisprojectisalsopresentonGitHubathttps://github.com/TooTallNate/Java-WebSocket.

YouneedtodownloadandinstalltheJava-WebSocketlibrary;itshouldthenbelinkedtoyourproject.

Inthisrecipe,wepacksignalingmessagesintotheJSONformatbeforesending,soweneedaJavalibrarytoworkwithJSONstructures.Forthispurpose,wewilluseJavaclassesfromJSON’shomepage,http://www.json.org/java/.

Downloadtheseclassesandlinkthemtoyourproject,oryoucanjustputtheseclassesintoyourproject’sfolderstructureandcompileitalltogether.

ItisassumedthatyouhaveexperienceofprogramminginJava,sowewillnotcoverthebasicquestionslikehowtostartaJavaapplicationandsoon.

Page 64: WebRTC Cookbook

Howtodoit…CreateanewprojectinyourJavaIDEandlinktheJSONlibrariesalongwiththeJava-WebSocketlibrary.

Thefollowingcoderepresentsasimplesignalingserver.CompileitandstartaJavaconsoleapplicationasusual:

packagecom.webrtcexample.signaler;

importorg.java_websocket.WebSocket;

importorg.java_websocket.handshake.ClientHandshake;

importorg.java_websocket.server.WebSocketServer;

importorg.json.JSONException;

importorg.json.JSONObject;

importjava.net.InetSocketAddress;

importjava.util.*;

publicclassMainextendsWebSocketServer{

privatestaticMap<Integer,Set<WebSocket>>Rooms=newHashMap<>();

privateintmyroom;

publicMain(){

super(newInetSocketAddress(30001));

}

@Override

publicvoidonOpen(WebSocketconn,ClientHandshakehandshake){

System.out.println("Newclientconnected:"+

conn.getRemoteSocketAddress()+"hash"+

conn.getRemoteSocketAddress().hashCode());

}

@Override

publicvoidonMessage(WebSocketconn,Stringmessage){

Set<WebSocket>s;

try{

JSONObjectobj=newJSONObject(message);

Stringmsgtype=obj.getString("type");

switch(msgtype){

case"GETROOM":

myroom=generateRoomNumber();

s=newHashSet<>();

s.add(conn);

Rooms.put(myroom,s);

System.out.println("Generatednewroom:"+myroom);

conn.send("{\"type\":\"GETROOM\",\"value\":"+myroom+

"}");

break;

case"ENTERROOM":

myroom=obj.getInt("value");

System.out.println("Newcliententeredroom"+

Page 65: WebRTC Cookbook

myroom);

s=Rooms.get(myroom);

s.add(conn);

Rooms.put(myroom,s);

break;

default:

sendToAll(conn,message);

break;

}

}catch(JSONExceptione){

sendToAll(conn,message);

}

System.out.println();

}

@Override

publicvoidonClose(WebSocketconn,intcode,Stringreason,boolean

remote){

System.out.println("Clientdisconnected:"+reason);

}

@Override

publicvoidonError(WebSocketconn,Exceptionexc){

System.out.println("Errorhappened:"+exc);

}

privateintgenerateRoomNumber(){

returnnewRandom(System.currentTimeMillis()).nextInt();

}

privatevoidsendToAll(WebSocketconn,Stringmessage){

Iteratorit=Rooms.get(myroom).iterator();

while(it.hasNext()){

WebSocketc=(WebSocket)it.next();

if(c!=conn)c.send(message);

}

}

publicstaticvoidmain(String[]args){

Mainserver=newMain();

server.start();

}

}

Oncetheapplicationstarts,itwilllistenontheTCPport30001forWebSocketmessagesfromclients.Youcanwritesimpleclientapplicationstotestthesignalingserver—refertotheMakingandansweringcallsrecipe.

NotethatyoucanfindaMaven-basedprojectforthisexamplesuppliedwiththisbook.

Page 66: WebRTC Cookbook

Howitworks…Firstofall,theclientsendsaGETROOMmessagetothesignalingserverthatislisteningonTCPport30001.Theservergeneratesanewvirtualroomnumber,storesit,andsendsitbacktotheclient.

TheclientconstructsanewaccessURLusingthevirtualroomnumberreceivedfromtheserver.Then,thesecondclientusesthisURLtoenterthevirtualroomandestablishacalltothefirstclient.

ThesecondclientsendstheroomnumberitgotfromtheURLtothesignalingserver.Theserverassociatestheclientwiththevirtualroomnumber.Then,theclientmakesacall,usingsignalingserver,whichforwardsitsmessagestothefirstclientthatispresentintheroomalready.Thefirstclientanswersthecall,alsousingthesignalingserverasthemiddlepoint.

Sobothclientsexchangethenecessarydata(includingnetworkdetails)andthenestablishdirectpeer-to-peerconnection.Aftertheconnectionisestablished,peersdon’tusetheserveranymore.

Page 67: WebRTC Cookbook

There’smore…TheWebSocketsignalingserverinJavacanbeimplementedusingaJavaEEstack.Formoredetails,takealookatthehomepageofJSR356athttp://www.oracle.com/technetwork/articles/java/jsr356-1937161.html.

Youcanalsofindanexampleathttps://github.com/hsilomedus/web-sockets-samples/tree/master/eesockets.

AnothersolutionistouseSpring4.IthasWebSocketsupportoutofthebox.Fordetailsonthissolution,takealookattheexampleonGitHubathttps://github.com/hsilomedus/web-sockets-samples/tree/master/springsockets.

Page 68: WebRTC Cookbook

SeealsoForanalternativesolution,youcanrefertotheBuildingasignalingserverinErlangrecipe

Page 69: WebRTC Cookbook
Page 70: WebRTC Cookbook

DetectingWebRTCfunctionssupportedbyabrowserWebRTCisnotfullysupportedbyallavailablewebbrowsersatthistime.Moreover,thereisachancethatyourapplicationwillberunningundersomekindofexoticenvironmentorwebbrowserthatdoesnotsupportWebRTC.SoyouneedtohavesomemechanismthatwouldenableyoutodetectwhethertheenvironmentinwhichyourwebapplicationisrunningsupportsthenecessaryWebRTCfeaturestheapplicationisgoingtouse.Inthisrecipe,wewillcoverthebasicmethodofdoingthat.

Page 71: WebRTC Cookbook

GettingreadyThistaskisrelevantfortheclientsideonly,soallthecodewillbewritteninJavaScript.Thus,nospecificpreparationisneeded.

Page 72: WebRTC Cookbook

Howtodoit…YoucanwriteaJavaScriptlibrarythatcanbeusedtodetectwhichWebRTCmethodsareavailableundertheenvironmentandbywhatnamestheyareknownforyourapplication.

Thefollowingcoderepresentsabasicbutproductiveexampleofsuchakindoflibrary:

varwebrtcDetectedVersion=null;

varwebrtcDetectedBrowser=null;

window.requestFileSystem=window.requestFileSystem||

window.webkitRequestFileSystem;

functioninitWebRTCAdapter(){

if(navigator.mozGetUserMedia){

webrtcDetectedBrowser="firefox";

webrtcDetectedVersion=

parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1],10);

RTCPeerConnection=mozRTCPeerConnection;

RTCSessionDescription=mozRTCSessionDescription;

RTCIceCandidate=mozRTCIceCandidate;

getUserMedia=navigator.mozGetUserMedia.bind(navigator);

attachMediaStream=

function(element,stream){

element.mozSrcObject=stream;

element.play();

};

reattachMediaStream=

function(to,from){

to.mozSrcObject=from.mozSrcObject;

to.play();

};

MediaStream.prototype.getVideoTracks=

function(){

return[];

};

MediaStream.prototype.getAudioTracks=

function(){

return[];

};

returntrue;

}elseif(navigator.webkitGetUserMedia){

webrtcDetectedBrowser="chrome";

webrtcDetectedVersion=

parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2],10);

RTCPeerConnection=webkitRTCPeerConnection;

getUserMedia=navigator.webkitGetUserMedia.bind(navigator);

attachMediaStream=

function(element,stream){

element.src=webkitURL.createObjectURL(stream);

};

Page 73: WebRTC Cookbook

reattachMediaStream=

function(to,from){

to.src=from.src;

};

if(!webkitMediaStream.prototype.getVideoTracks){

webkitMediaStream.prototype.getVideoTracks=

function(){

returnthis.videoTracks;

};

webkitMediaStream.prototype.getAudioTracks=

function(){

returnthis.audioTracks;

};

}

if(!webkitRTCPeerConnection.prototype.getLocalStreams){

webkitRTCPeerConnection.prototype.getLocalStreams=

function(){

returnthis.localStreams;

};

webkitRTCPeerConnection.prototype.getRemoteStreams=

function(){

returnthis.remoteStreams;

};

}

returntrue;

}elsereturnfalse;

};

Page 74: WebRTC Cookbook

Howitworks…ThissolutiontestswhichWebRTCAPImethodsareavailableintheenvironmentandhowtheyarenamed.SoyourapplicationcanusecertainAPIfunctionnamesthatwillberelevantforanywebbrowser,withoutusingbrowser-specificfunctionnames.

Page 75: WebRTC Cookbook

There’smore…Thereisanotherwaytosolvethistask.Youdon’tnecessaryhavetowriteyourownadapter.YoucantaketheadapterpreparedbyGoogle.Itcanbefoundathttp://apprtc.webrtc.org/js/adapter.js.YoujustneedtoincludeitinyourJavaScriptcode.

Youcanalsoconsiderusingabrowser’spluginthatenablestheuseofWebRTCinSafariandInternetExplorer.Youcangettheseathttps://temasys.atlassian.net/wiki/display/TWPP/How+to+integrate+the+plugin+with+your+website

Page 76: WebRTC Cookbook

SeealsoYoucanfindmoreinformationontheadapteratthewebpagehttp://www.webrtc.org/web-apis/interop.

Page 77: WebRTC Cookbook
Page 78: WebRTC Cookbook

MakingandansweringcallsTheverybasicactionofanyWebRTCapplicationismakingandreceivingacall.Thisrecipeshowshowtomakecallstoaremotepeer.

Page 79: WebRTC Cookbook

GettingreadyAtthebeginning,peersdon’tknoweachother,andtheydon’tknowthenecessarynetworkinformationtomakedirectconnectionpossible.Beforeestablishingadirectconnection,peersshouldexchangenecessarydatausingsomemiddlepoint—usually,asignalingserver.Thisisamiddlepointthatisknowntoeachpeer.Soeachpeercanconnecttothesignalingserver,andthenonepeercancallanotherone—byaskingthesignalingservertoexchangespecificdatawithanotherpeerandmakepeersknoweachother.

So,youneedasignalingservertorun.

Page 80: WebRTC Cookbook

Howtodoit…Beforetwopeerscanestablishadirectconnection,theyshouldexchangespecificdata(ICEcandidatesandsessiondescriptions)usingamiddlepoint—thesignalingserver.Afterthat,onepeercancallanotherone,andthedirectpeer-to-peerconnectioncanbeestablished.

InteractiveConnectivityEstablishment(ICE)isatechniqueusedinNetworkAddressTranslator(NAT),whichbypassestheprocessofestablishingpeer-to-peerdirectcommunication.Usually,ICEcandidatesprovideinformationabouttheIPaddressandportofthepeer.Typically,anICEcandidatemessagemightlooklikethefollowing:a=candidate:11UDP4257021352192.168.0.101211typhost

SessionDescriptionProtocol(SDP)isusedbypeersinWebRTCtoconfigureexchanging(networkconfiguration,audio/videocodecsavailable,andsoon).Everypeersendsdetailsregardingitsconfigurationtoanotherpeerandgetsthesamedetailsfromitback.ThefollowingprintdepictsapartofanSDPpacketrepresentingtheaudioconfigurationoptionsofapeer:m=audio53275RTP/SAVPF121918100121029013116

c=INIP416.0.0.1

a=rtcp:53275INIP416.0.0.1

Intheschemarepresentedinthefollowingdiagram,youcanseethegenericflowofacallestablishingprocess:

NotethatTURNisnotshowedintheschema.IfyouusedTURN,itwouldbedepicted

Page 81: WebRTC Cookbook

justaftertheSTUNstage(beforethefirstandsecondstage).

MakingacallTomakeacall,weneedtotakesomestepstoprepare(suchasgettingaccesstothebrowser’smedia):

1. Getaccesstotheuser’smedia:

functiondoGetUserMedia(){

varconstraints={"audio":true,"video":{"mandatory":{},

"optional":[]}};

try{

getUserMedia(constraints,onUserMediaSuccess,

function(e){

console.log("getUserMediaerror"+e.toString());

});

}catch(e){

console.log(e.toString());

}

};

2. Ifyousucceed,createapeerconnectionobjectandmakeacall:

functiononUserMediaSuccess(stream){

attachMediaStream(localVideo,stream);

localStream=stream;

createPeerConnection();

pc.addStream(localStream);

if(initiator)doCall();

};

functioncreatePeerConnection(){

varpc_constraints={"optional":[{"DtlsSrtpKeyAgreement":

true}]};

try{

pc=newRTCPeerConnection(pc_config,pc_constraints);

pc.onicecandidate=onIceCandidate;

}catch(e){

console.log(e.toString());

pc=null;

return;

}

pc.onaddstream=onRemoteStreamAdded;

};

functiononIceCandidate(event){

if(event.candidate)

sendMessage({type:'candidate',label:

event.candidate.sdpMLineIndex,id:event.candidate.sdpMid,candidate:

event.candidate.candidate});

};

functiononRemoteStreamAdded(event){

attachMediaStream(remoteVideo,event.stream);

remoteStream=event.stream;

};

Page 82: WebRTC Cookbook

functiondoCall(){

varconstraints={"optional":[],"mandatory":

{"MozDontOfferDataChannel":true}};

if(webrtcDetectedBrowser==="chrome")

for(varpropinconstraints.mandatory)if

(prop.indexOf("Moz")!=-1)deleteconstraints.mandatory[prop];

constraints=mergeConstraints(constraints,sdpConstraints);

pc.createOffer(setLocalAndSendMessage,errorCallBack,

constraints);

};

AnsweringacallAssumingthatwewilluseWebSocketsasatransportprotocolforexchangingdatawithsignalingserver,everyclientapplicationshouldhaveafunctiontoprocessmessagescomingfromtheserver.Ingeneral,itlooksasfollows:

functionprocessSignalingMessage(message){

varmsg=JSON.parse(message);

if(msg.type==='offer'){

pc.setRemoteDescription(newRTCSessionDescription(msg));

doAnswer();

}elseif(msg.type==='answer'){

pc.setRemoteDescription(newRTCSessionDescription(msg));

}elseif(msg.type==='candidate'){

varcandidate=newRTCIceCandidate({sdpMLineIndex:msg.label,

candidate:msg.candidate});

pc.addIceCandidate(candidate);

}elseif(msg.type==='GETROOM'){

room=msg.value;

onRoomReceived(room);

}elseif(msg.type==='WRONGROOM'){

window.location.href="/";

}

};

ThisfunctionreceivesmessagesfromthesignalingserverusingtheWebSocketslayerandactsappropriately.Forthisrecipe,weareinterestedintheoffertypeofmessageanddoAnswerfunction.

ThedoAnswerfunctionispresentedinthefollowinglisting:

functiondoAnswer(){

pc.createAnswer(setLocalAndSendMessage,errorCallBack,sdpConstraints);

};

ThesdpConstraintsobjectdescribestheWebRTCconnectionoptionstobeused.Ingeneral,itlooksasfollows:

varsdpConstraints={'mandatory':{'OfferToReceiveAudio':true,

'OfferToReceiveVideo':true}};

Herewecansaythatwewouldliketousebothaudioandvideowhileestablishing

Page 83: WebRTC Cookbook

WebRTCpeer-to-peerconnection.

TheerrorCallbackmethodisacallbackfunctionthatiscalledincaseofanerrorduringthecallingofthecreateAnswerfunction.Inthiscallbackfunction,youcanprintamessagetotheconsolethatmighthelptodebugtheapplication.

ThesetLocalAndSendMessagefunctionsetsthelocalsessiondescriptionandsendsitbacktothesignalingserver.Thisdatawillbesentasananswertypeofmessage,andthenthesignalingserverwillroutethismessagetothecaller:

functionsetLocalAndSendMessage(sessionDescription){

pc.setLocalDescription(sessionDescription);

sendMessage(sessionDescription);

};

Notethatyoucanfindthefullsourcecodeforthisexamplesuppliedwiththisbook.

Page 84: WebRTC Cookbook

Howitworks…Firstly,wewillaskthewebbrowsertogainaccesstotheusermedia(audioandvideo).Thewebbrowserwillasktheuserfortheseaccessrights.Ifwegettheaccess,wecancreateaconnectionpeerentityandsendthecallmessagetothesignalingserver,whichwillroutethismessagetotheremotepeer.

Theworkflowofthecodeisverysimple.TheprocessSignalingMessagefunctionshouldbecalledeverytimewegetamessagefromthesignalingserver.Usually,youshouldsetitasanonmessageeventhandleroftheWebSocketJavaScriptobject.

Afterthemessageisreceived,thisfunctiondetectsthemessagetypeandactsappropriately.Toansweranincomingcall,itcallsthedoAnswerfunctionthatwilldotherestofthemagic—preparethesessiondescriptionandsenditbacktotheserver.

Thesignalingserverwillgetthisreplyasananswermessageandwillrouteittotheremotepeer.Afterthat,peerswillhaveallthenecessarydataoneachothertostartestablishingadirectconnection.

Page 85: WebRTC Cookbook

There’smore…ThisisthebasicfunctionalityofWebRTC.Mostofyourapplicationswillprobablyhavethesamecodeforthistask.Theonlybigdifferencemightbecommunicationwiththesignalingserver—youcanuseanyprotocolyoulike.

Page 86: WebRTC Cookbook

SeealsoRefertotheImplementingachatusingdatachannelsreciperegardingtheprocessofbuildingasimplewebchatapplicationusingWebRTCYoucanfindmoredetailsonICEontheRFC5245websiteathttps://tools.ietf.org/html/rfc5245MoreinformationregardingSDPcanbefoundonRFC4566athttps://tools.ietf.org/html/rfc4566

Page 87: WebRTC Cookbook
Page 88: WebRTC Cookbook

ImplementingachatusingdatachannelsInthisrecipe,wewillimplementapeer-to-peerprivatemessagingserviceusingWebRTCdatachannels.Thismethodallowsustosendmessagesdirectlyfrompeertopeer,usingsecureandsafedatachannelsprovidedbytheWebRTCstack.

Theschemarepresentedinthefollowingdiagramdepictsthegenericfeatureflow:

Page 89: WebRTC Cookbook

GettingreadyWewilldevelopasimpleapplication,soyoudon’tneedanyspecificpreparationsforthisrecipe.Asignalingserverisnecessaryforthisapplication,anditcanbetakenfromtheBuildingasignalingserverinErlangorBuildingasignalingserverinJavarecipe.

Page 90: WebRTC Cookbook

Howtodoit…Forsimplicity,wewillmaketwopartsoftheapplication:anindexwebpageandaJavaScriptlibrary.

CreatingthemainHTMLpageoftheapplication1. First,createanHTMLindex.htmlpage.Inthefollowingcode,youcanfindits

content.Notethatthelessimportantandobviouspartsmightbeskippedhere.

<!DOCTYPEhtml>

<html>

<head>

2. IncludeourJavaScriptlibrarythatisinaseparatefile:

<scripttype="text/javascript"src="myrtclib.js"></script>

3. IncludeGoogle’sWebRTCJavaScriptadapter:

<script

src="https://rawgit.com/GoogleChrome/webrtc/master/samples/web/js/adapt

er.js"></script>

</head>

<body>

4. Createadivtagwherewewillputinformationregardingtheconnection:

<divid="status"></div><br>

5. Createadivtagwherethereceivedmessagesfromaremotepeerwillbeplaced:

<divid="chat"></div>

6. Createaformwithaninputelementandabuttontosendmessagestotheremotepeer:

<formname="chat_form"

onsubmit="onChatSubmit(document.chat_form.msg.value);returnfalse;">

<inputtype="text"class="search-query"placeholder="chathere"

name="msg"id="chat_input">

<inputtype="submit"class="btn"id="chat_submit_btn"/>

</form>

<script>

7. CreateaconnectiontothesignalingserverandinitializetheWebRTCstack.ThefollowingfunctionisdeclaredintheJavaScriptlibrary,whichwewillconsiderfurtherintherecipe:

myrtclibinit("ws://localhost:30001");

Notethatthedomainnameandportmightbedifferentinyourcase;theyshouldbethesameasdeclaredinthesourcecodesofthesignalingsever.Bydefault,thesignalingserverislisteningonlocalhostandonport30001.

Page 91: WebRTC Cookbook

ThefollowingfunctionsendsamessagetotheremotepeerusingthesendDataMessagefunction—wewillwriteitaspartoftheJavaScriptlibrary:

functiononChatSubmit(txt){

varmsg=JSON.stringify({"type":"chatmessage","txt":txt});

sendDataMessage(msg);

};

Wewillalsodeclareacallbackfunctionforacatchingeventwhenanewvirtualroomiscreated:

functiononRoomReceived(room){

varst=document.getElementById("status");

Createalinktosharewiththeremotepeer,putthelinkinthedivstatus.

st.innerHTML="Now,ifsomebodywantstojoinyou,shouldusethis

link:<ahref=\""+window.location.href+"?

room="+room+"\">"+window.location.href+"?room="+room+"</a>";

};

Toshowthemessagesreceivedfromtheremotepeer,wewilldeclareanappropriatecallbackfunction.ThisfunctiongetsthemessageandputsitintheappropriateplaceontheHTMLpage:

functiononPrivateMessageReceived(txt){

vart=document.getElementById('chat').innerHTML;

t+="<br>"+txt;

document.getElementById('chat').innerHTML=t;

}

</script>

</body>

</html>

SavetheHTMLfile.Thiswillbethemainpageoftheapplications.

CreatingtheJavaScripthelperlibraryNow,createanemptymyrtclib.jsfileandputthefollowingcontentintoit.Notethatmanypartsofthefollowingcodemightbeusedinthenextchapters,sotheyshouldbewell-knowntoyoualready.Suchobviouspartsofthecodemightbeskippedinfurther.

varRTCPeerConnection=null;

varroom=null;

varinitiator;

varpc=null;

varsignalingURL;

Thefollowingvariablewillbeusedforhandlingthedatachannelobject:

vardata_channel=null;

varchannelReady;

varchannel;

varpc_config={"iceServers":

[{url:'stun:23.21.150.121'},

{url:'stun:stun.l.google.com:19302'}]};

Page 92: WebRTC Cookbook

functionmyrtclibinit(sURL){

signalingURL=sURL;

openChannel();

};

functionopenChannel(){

channelReady=false;

channel=newWebSocket(signalingURL);

channel.onopen=onChannelOpened;

channel.onmessage=onChannelMessage;

channel.onclose=onChannelClosed;

};

functiononChannelOpened(){

channelReady=true;

createPeerConnection();

if(location.search.substring(1,5)=="room"){

room=location.search.substring(6);

sendMessage({"type":"ENTERROOM","value":room*1});

initiator=true;

doCall();

}else{

sendMessage({"type":"GETROOM","value":""});

initiator=false;

}

};

functiononChannelMessage(message){

processSignalingMessage(message.data);

};

functiononChannelClosed(){

channelReady=false;

};

functionsendMessage(message){

varmsgString=JSON.stringify(message);

channel.send(msgString);

};

functionprocessSignalingMessage(message){

varmsg=JSON.parse(message);

if(msg.type==='offer'){

pc.setRemoteDescription(newRTCSessionDescription(msg));

doAnswer();

}elseif(msg.type==='answer'){

pc.setRemoteDescription(newRTCSessionDescription(msg));

}elseif(msg.type==='candidate'){

varcandidate=newRTCIceCandidate({sdpMLineIndex:msg.label,

candidate:msg.candidate});

pc.addIceCandidate(candidate);

}elseif(msg.type==='GETROOM'){

room=msg.value;

Page 93: WebRTC Cookbook

onRoomReceived(room);

}elseif(msg.type==='WRONGROOM'){

window.location.href="/";

}

};

functioncreatePeerConnection(){

try{

pc=newRTCPeerConnection(pc_config,null);

pc.onicecandidate=onIceCandidate;

Untilnow,thecodeisverysimilartowhatweusedinatypicalWebRTCexampleapplication.Although,nowwewilladdsomethingnew.WewillsetupahandlerfortheondatachanneleventofthePeerConnectionobject.Thiscallbackfunctionwillbecalledwhenthepeerasksustocreateadatachannelandestablishadataconnection:

pc.ondatachannel=onDataChannel;

}catch(e){

console.log(e);

pc=null;

return;

}

};

Thehandlerfunctionisprettysimple.Wewillstorethereferenceinthedatachannelandinitializeit:

functiononDataChannel(evt){

console.log('Receiveddatachannelcreatingrequest');

data_channel=evt.channel;

initDataChannel();

}

Byinitializingthedatachannel,Imeansettingupachannel’seventhandlers:

functioninitDataChannel(){

data_channel.onopen=onChannelStateChange;

data_channel.onclose=onChannelStateChange;

data_channel.onmessage=onReceiveMessageCallback;

}

Inthefollowingfunction,weneedtocreateanewdatachannel—notwhentheremotepeerisaskingus,butwhenwe’retheinitiatorofthepeerconnectionandwanttocreateanewdatachannel.Afterwehavecreatedanewdatachannel,weshouldasktheremotepeertodothesame:

functioncreateDataChannel(role){

try{

Whenwecreateanewdatachannel,wecansetupanameofthechannel.Inthefollowingpieceofcode,wewillusethenumberofthevirtualroomtonamethechannel:

data_channel=pc.createDataChannel("datachannel_"+room+role,

null);

}catch(e){

console.log('errorcreatingdatachannel'+e);

Page 94: WebRTC Cookbook

return;

}

initDataChannel();

}

functiononIceCandidate(event){

if(event.candidate)

sendMessage({type:'candidate',label:

event.candidate.sdpMLineIndex,id:event.candidate.sdpMid,candidate:

event.candidate.candidate});

};

functionfailureCallback(e){

console.log("failurecallback"+e.message);

}

functiondoCall(){

Whenweareplayingtheroleoftheconnectioninitiator(caller),wecreateanewdatachannel.Then,duringtheconnectionestablishment,theremotepeerwillbeaskedtodothesameandthedatachannelconnectionwillbeestablished:

createDataChannel("caller");

pc.createOffer(setLocalAndSendMessage,failureCallback,null);

};

functiondoAnswer(){

pc.createAnswer(setLocalAndSendMessage,failureCallback,null);

};

functionsetLocalAndSendMessage(sessionDescription){

pc.setLocalDescription(sessionDescription);

sendMessage(sessionDescription);

};

Tosendtextmessagesviathedatachannel,weneedtoimplementtheappropriatefunction.Asyoucanseeinthefollowingcode,sendingdatatothedatachannelisprettyeasy:

functionsendDataMessage(data){

data_channel.send(data);

};

Thefollowinghandlerisnecessarytoprintthestateofthedatachannelwhenitischanged:

functiononChannelStateChange(){

console.log('Datachannelstateis:'+data_channel.readyState);

}

Whentheremotepeersendsusamessageviathedatachannel,wewillparseitandcalltheappropriatefunctiontoshowthemessageonthewebpage:

functiononReceiveMessageCallback(event){

console.log(event);

try{

Page 95: WebRTC Cookbook

varmsg=JSON.parse(event.data);

if(msg.type==='chatmessage')

onPrivateMessageReceived(msg.txt);

}

catch(e){}

};

SavetheJavaScriptfile.

Now,startthesignalingserverandopentheHTMLfileinawebbrowser—youshouldseeaninputfieldandabuttononthepage.Atthetopofthepage,youshouldseeaURLtobesharedwiththeremotepeer.

Onanotherbrowser’swindow,openthesharinglink.Inthewebbrowser’sconsole,youshouldseetheDatachannelstateisopenmessage.Now,entersomethingintheinputboxandclickontheSubmitquerybutton.Youshouldseethemessageprintedonanotherbrowser’swindow.

Page 96: WebRTC Cookbook

Howitworks…Whentheapplicationstarts,itestablishesaconnectionwiththesignalingserverandgetsavirtualroomnumber.Then,anotherpeerstartstheapplicationandentersthevirtualroom.Thesecondpeeristhecaller.Whenthepeerconnectionisestablished,thecallercreatesanewdatachannelandanotherpeerreceivesthiseventnotification.So,bothpeersgetadatachannelreferenceandcanuseitfordataexchanging.

Inourexample,whenthecustomerentersamessageandclicksontheSubmitquerybutton,wewillwrapthemessageintoaJSONobjectandsenditviathedatachannel.TheremotepeergetstheJSONobject,parsesittothemessage,anddisplaysitonthepage.

Page 97: WebRTC Cookbook

There’smore…Usingdatachannels,peerscanexchangeanykindofdata.Itcanbeplaintext,forexample,orbinarydata.Moreover,thesamedatachannelcanbeusedtoexchangedifferentsortsofdatabetweenpeers.Inthisrecipe,weusedJSONtoformatmessages,andeverypackethasatypefield.Tosendtextmessages,weusedthechatmessagetype,butyoucanuseyourowncustomtypesystemtodistinguishmessages.YoucanalsousesomethingotherthanJSON.So,datachannelsareagoodtooltoexchangedatabetweenpeers,usingasecureandsafedirectconnection.

Page 98: WebRTC Cookbook

SeealsoPleaserefertotheImplementingachatusingasignalingserverrecipetolearntheotherwaythisfeaturecanbeimplemented

Page 99: WebRTC Cookbook
Page 100: WebRTC Cookbook

ImplementingachatusingasignalingserverInthisrecipe,wewillcovertheprocessofimplementingprivate,peer-to-peerwebchatusingsignalingserverasthemiddlepoint.Peerswillsendchatmessagesviathesignalingserver.Intheschemarepresentedinthefollowingdiagram,youcanseetheflow:

Page 101: WebRTC Cookbook

Howtodoit…Toimplementthechatfeatureviathesignalingserver,weneedtoaddsomemethodstotheclientcodewiththefollowingsteps:

1. Weneedtoaddappropriatecodetothefunctionthatprocessesthemessagesfromthesignalingserver:

functionprocessSignalingMessage(message){

varmsg=JSON.parse(message);

if(msg.type==='CHATMSG'){

onChatMsgReceived(msg.value);

}elseif(msg.type==='offer'){

pc.setRemoteDescription(newRTCSessionDescription(msg));

doAnswer();

}elseif(msg.type==='answer'){

pc.setRemoteDescription(newRTCSessionDescription(msg));

}elseif(msg.type==='candidate'){

varcandidate=new

RTCIceCandidate({sdpMLineIndex:msg.label,candidate:msg.candidate});

pc.addIceCandidate(candidate);

}elseif(msg.type==='GETROOM'){

room=msg.value;

onRoomReceived(room);

}elseif(msg.type==='WRONGROOM'){

window.location.href="/";

}

};

2. WewillcheckwhetherthereceivedmessageisoftheCHATMSGtypeandifso,wewillcalltheonChatMsgReceivedmethodtoprocessit:

functiononChatMsgReceived(txt){

varchatArea=document.getElementById("chat_div");

chatArea.innerHTML=chatArea.innerHTML+txt;

chatArea.scrollTop=chatArea.scrollHeight;

};

Here,wewillgetthechat_divelementbyitsIDandalteritscontentbyaddingthechatmessagereceivedfromtheremotepeerviathesignalingserver.

3. Tosendachatmessage,weshouldimplementamethodlikethefollowing:

functionchatSendMessage(msg){

if(!channelReady)return;

sendMessage({"type":"CHATMSG","value":msg});

};

ThisfunctioncheckswhethertheWebSocketchannelisupandsendsachatmessagetothesignalingserverusingthechannel.Tousethisfunction,wecanusetheHTMLinputtagwiththesubmitbuttonandcallitonthesubmitevent.

Page 102: WebRTC Cookbook

Howitworks…Thebasicprincipleofthissolutionisprettysimple:

Onepeersendsatextmessagetothesignalingserver,markingitastheCHATMSGtypeThesignalingserverretransmitsthemessagetoanotherpeerAnotherpeergetsthemessagefromthesignalingserver,checkswhetheritisoftheCHATMSGtypeandifso,showsittotheuser

TipTodistinguishchatmessagesfromWebRTCmessages,youcanuseanywordtomarkthemessagetype.ItcanbeCHATMSGorwhateveryouprefer.

Page 103: WebRTC Cookbook

There’smore…Thiswayofimplementingwebchatisusuallynotsecurebecausethedatawillgoviathesignalingserverandnotdirectlythroughthepeers.Nevertheless,itissuitableforpublicchatroomswheretherecanbeseveralpeopleatatime.Forprivatepeer-to-peerchats,itisusuallybettertouseWebRTCdatachannels,andthatwayitismoresecure.

Page 104: WebRTC Cookbook

SeealsoToimplementthechatfeatureusingdatachannels,followtheImplementingachatusingdatachannelsrecipe

Page 105: WebRTC Cookbook
Page 106: WebRTC Cookbook

ConfiguringandusingSTUNYourWebRTCapplicationcanworkwithoutSTUNorTURNserversifallthepeersarelocatedinthesameplainnetwork.Ifyourapplicationissupposedtoworkforpeersthatmightbelocatedindifferentnetworks,itwilldefinitelyneedtouseatleasttheSTUNservertowork.

Page 107: WebRTC Cookbook

GettingreadyInthisrecipe,wewillinstallaSTUNserveronaLinuxbox.STUNservercanbeinstalledundertheotherplatformaswell,butforsimplicity,wewillconsideronlytheLinuxcase.So,pleaseprepareaLinuxmachine.

Inthisrecipe,wewilluseaverybasicandsimpleSTUNserverimplementation,soyouprobablywillnotneedtoinstalladditionallibrariesordosomedifficultconfiguration.

STUNneedstwoIPaddressestoworkcorrectly.Thus,whenexperimentingwithyourLinuxbox,takecarethattheLinuxboxshouldhaveatleasttwoIPaddressesthatareavailableforallpossiblepeers(WebRTCclients).

Page 108: WebRTC Cookbook

Howtodoit…ThefollowingsetofstepswillleadyouthroughtheprocessofconfiguringandbuildingaSTUNservice:

1. DownloadtheSTUNserverfromitshomepageathttp://sourceforge.net/projects/stun/.

2. UnpackthearchiveandgointotheSTUNserverfolder:

tar–xzfstund-0.97.tgz

cdstund

3. Builditwiththefollowingcommand:

make

Thelastcommandwillbuildtheserver.Afterthat,youcanstarttheSTUNserverbyusingthefollowingcommand:

./server-hprimary_ip-asecondary_ip

Notethatinsteadofprimary_ipandsecondary_ip,youshoulduseactualIPaddressesthatareavailableonthemachine.Thissoftwarecan’tdetectsuchnetworkparametersautomatically,soyouneedtosetitupexplicitly.

TipIfyouwanttostarttheserverinthebackground,addthe-boptiontotheprecedingcommand.

Now,whentheSTUNserverisconfiguredandrunning,wecanutilizeitintheWebRTCapplication.Whenyourapplicationwantstocreateapeerconnectionobject,itusessomethinglikethefollowingcode:

varpc;

pc=newRTCPeerConnection(configuration);

Here,configurationisanentitythatcontainsdifferentoptionsforcreatingpeerconnectionobject.ToutilizeyourfreshlyinstalledSTUNserver,youshouldusesomethinglikethefollowingcode:

varconfiguration={

'iceServers':[

{

'url':'stun:stun.myserver.com:19302'

}]}

HereweinformthewebbrowserthatitcanusetheSTUNserverifnecessary.NotethatyoushouldusetherealdomainnameorIPaddressoftheSTUNserver.Youcanalsoexplicitlysettheportnumberasshownintheprecedingcode,incaseitisdistinguishedfromthedefaultvalue.

Page 109: WebRTC Cookbook

Howitworks…STUNservercanhelppeersdeterminetheirnetworkparametersandthusestablishadirectcommunicationchannel.IfyourclientsarelocatedbehindNATorfirewall,yourapplicationshoulduseatleasttheSTUNservicetomakethedirectconnectionpossible.Nevertheless,inmanycasesthatmightnotbeenough,andusingTURNmightbenecessary.

ThefollowingdiagrammightbehelpfultoyoutoimaginehowtheSTUNserverislocatedinthewholeinfrastructure,andhowallthecomponentsinteroperatewitheachother:

Page 110: WebRTC Cookbook

There’smore…Asanalternativetothis,youcanuserfc5766-server—itisafreeandopensourceimplementationofbothSTUNandTURNservers.Italsosupportsmanyadditionalfeaturesthatmightbequiteuseful.Youcanfinditathttps://code.google.com/p/rfc5766-turn-server/.

Page 111: WebRTC Cookbook

SeealsoFordetailsonhowSTUNworks,youcanrefertoRFC#3489http://www.ietf.org/rfc/rfc3489.txt.IntheConfiguringandusingTURNrecipe,wewilluseaTURNserverbasedontherfc5766-serversoftware.ThatapplicationcanserveasaSTUNserveraswell.

Page 112: WebRTC Cookbook
Page 113: WebRTC Cookbook

ConfiguringandusingTURNInmostcases,itisenoughtouseaSTUNservertoestablishapeer-to-peerdirectconnection.Nevertheless,youwilloftenneedtoutilizeTURNservers—mostlyforclientslocatedinbigcompanies(becauseoffirewallpolicyandtrickyNAT)andsomespecificcountries(becauseoffirewallsandaccesslimits).

Page 114: WebRTC Cookbook

GettingreadyInthissection,wewilldownload,install,anddothebasicconfigurationofaTURNservice.Then,wewillutilizeitinourWebRTCapplication.ATURNservercanbeinstalledunderdifferentplatforms,althoughwewillcoveraLinuxboxusecaseonly.Thus,forthisrecipe,youwillneedaLinuxboxinstalled.

Forthisrecipe,wewilluserfc5766-turn-server—afreeandopensourceimplementationoftheTURNandSTUNservers.Downloaditssourcecodefromitshomepageathttps://code.google.com/p/rfc5766-turn-server/.

Page 115: WebRTC Cookbook

Howtodoit…First,wewillshortlycovertheinstallationandbasicconfigurationoftheTURNserver.Afterthat,wewilllearnhowtouseitintheapplication.

IfyouhaveTURNserveralreadyinstalled,youcanskipthissectionandgodirectlytothenextone.

InstallingtheTURNserverIassumethatyouhavedownloadedrfc5766-serveralreadyandunpackedit.So,let’sinstallandconfigureyourownTURNserver:

1. Gototherfc5766-serverfolderwiththefollowingcommand:

cd~/turnserver-4.1.2.1

2. Buildtheserver:

./configure

make

sudomakeinstall

TipNotethatrfc5766-serverneedssomelibrariesthatmightbenotinstalledonyoursystem—inparticular,libssl-dev,libevent-dev,andopenssl.Youshouldinstalltheabsentlibrariestocompilethesoftwaresuccessfully.

3. Afterthat,youcanstarttheserver—itwilldetectallthenetworkoptionsautomatically:

turnserver

Youwillseediagnosticmessagesintheconsole:

0:===========Discoveringrelayaddresses:=============

0:Relayaddresstouse:x.x.x.x

0:Relayaddresstouse:y.y.y.y

0:Relayaddresstouse:::1

0:=====================================================

0:Total:3relayaddressesdiscovered

0

0:=====================================================

NoteTostoptheserver,justpressCtrl+C;youwillgetbacktoconsole.

NowitistimetoperformsomeconfigurationstepsandtuneyourfreshTURNserverforyourrequirements.

Bydefault,theTURNserverdoesn’thaveanyconfigurationfile.Weneedtocreatethisconfigurationfilefromthedefaultconfigurationfilesuppliedwiththeserver:

Page 116: WebRTC Cookbook

sudocp/usr/local/etc/turnserver.conf.default

/usr/local/etc/turnserver.conf

Opentheturnserver.conffileandedititaccordingtoyourrequirements.WewillnotcoveralltheTURNoptionshere,butjustbasicconfigurationitemsthatmightbeimportant:

ListeningIP:ThisoptiondeterminestheIPaddressesthatwillbeusedbytheTURNserverwhileoperating.Bydefault,thisoptionwilldoitautomatically.Nevertheless,itisagoodideatosettheobviousIPaddressesyouwouldliketheservertouse:

listening-ip=

TipNotethattheTURNserverneedsatleasttwopublicIPaddressestooperatecorrectly.

RelayIP:Inthisoption,youcanexplicitlysetupIPaddressthatshouldbeusedforrelay.Inotherwords,ifyouhavetwoIPaddresses,oneofthemcanbelistening-ipandthesecondonerelay-ip.

relay-ip=

Verbosity:Inthisoption,youcansetalevelofverbosity.Bydefault,theTURNserverwillnotprintextradetailsonitswork,butfordebugginganddiagnosticpurposes,itmightbeveryusefultosettheverboseleveltonormal.Forthat,youshouldplacethewordverboseintheconfigurationfile.Ifyouwouldliketorefertomoredetails,youshouldwritethewordwithcapitalV—Verbose—sotheserverwillprintasmuchdebuggingdetailsaspossible.Anonymousaccess:Youcanenableanonymousaccessduringthedevelopmentprocess,ifyou’resurethatyourTURNserverisprotectedbynetworkfirewallandnobodycanuseit.Otherwise,youshouldnotenablethisoptionespeciallyonproductionsystems:

no-auth

NoteInthisrecipe,wehaven’tcoveredTURNauthentication—thistopiciscoveredinChapter2,SupportingSecurity.

Atthisstage,youhaveyourownTURNserverwithbasicconfiguration,whichcanbeusedinWebRTCapplications.

UsingTURNinWebRTCapplicationWhenyoucreateapeerconnectionobject,youusuallyusesomeconstructionlikethefollowingone:

varpc;

pc=newRTCPeerConnection(configuration);

Here,configurationisanentitythatcontainsdifferentoptionstocreateapeerconnectionobject.ToutilizeyourTURNserver,youshouldusesomethinglikethe

Page 117: WebRTC Cookbook

following:

varconfiguration={

'iceServers':[

{

'url':'stun:stun.l.google.com:19302'

},

{

'url':'turn:turn1.myserver.com:3478?transport=udp',

},

{

'url':'turn:turn2.myserver.com:3478?transport=tcp',

'credential':'superuser',

'username':'secretpassword'

}

]

}

Here,wewillasktheWebRTCAPI(actually,wewillaskthewebbrowser)touseoneofthreewayswhenestablishingapeerconnection:

PublicSTUNserverprovidedbyGoogle.TURNserverwithanonymousaccess.YouwillusethisnotationtoutilizetheTURNserverinstalledandconfiguredinthisrecipe.TURNserverwithauthentication.InChapter2,SupportingSecurity,wewillcoverthetopicofsecurityandauthenticationwithinthescopeofaTURNserver.Toutilizeaserverthatusesauthentication,youshouldusethisnotation.

TipNotethatyoucanaskthewebbrowsertouseaUDPorTCPprotocolwhileestablishingapeerconnectionthroughtheTURNserver.Todothat,setupthetransportparameterasshownintheprecedingbulletpoints.

Page 118: WebRTC Cookbook

Howitworks…Insomecases,whenclientsuseNATandfirewalls,itisimpossibletoestablishapeerconnectionusingSTUN.Thissituationoftenappearswhenaclientislocatedinacorporativenetworkwithastrictpolicy.Insuchacase,theonlywaytoestablishtheconnectionistousetheTURNserver.

TheTURNserverworksasaproxy—allthedatabetweenpeers(includingaudio,video,andservicedata)goesthroughtheTURNserver.

Thefollowingdiagramshowshowallthecomponentsoperatewitheachother:

Page 119: WebRTC Cookbook

There’smore…Inthisrecipe,wecoveredonlyoneTURNsolution,opensourceandpopular,butthereareothersolutionsintheworldthatcouldalsobesuitableforyou:

TurnServer:Thisisalsofreeandopensource.Formoreinformation,refertohttp://turnserver.sourceforge.net.Numb:Thisisnotsoftwarethatyoucandownloadandinstall,butaservicewhereyoucancreateanaccountandgetaccesstoaconfiguredTURNserver.Formoredetails,refertohttp://numb.viagenie.ca.

Ofcourse,thereareevenmoredifferentsolutionsandservicesavailable.

Page 120: WebRTC Cookbook

SeealsoFordetailsonTURNservers,refertoRFC5766athttp://tools.ietf.org/html/rfc5766FordetailsregardingSTUN(anotherusefultechnologywiththescopeofdevelopingWebRTC-basedservices),youcanalsotakealookattheConfiguringandusingSTUNrecipe

Page 121: WebRTC Cookbook
Page 122: WebRTC Cookbook

Chapter2.SupportingSecurityInthischapter,wewillcoverthefollowingtopics:

Generatingaself-signedcertificateConfiguringaTURNserverwithauthenticationConfiguringawebservertoworkoverHTTPSConfiguringaWebSocketsproxyonthewebserverConfiguringafirewall

Page 123: WebRTC Cookbook

IntroductionAtthetimeofwritingthisbook,theWebRTCstandardwasnotcompleteandthetechnologyanditsstandardwerebothunderactivedevelopment.Nevertheless,securityandsafetyareveryimportantandmandatoryfunctionalrequirementsthatlieatthebasisoftheWebRTCstandard.Basically,yourWebRTCapplicationshoulduseonlyencryptedchannels.

Inthischapter,wewillcoversecurity-relatedquestions.Wewilltalkaboutsecurity,third-partycomponents,andsoftwareyouwillprobablyusewhendevelopingyourWebRTCservice.Wewilltalkaboutconfiguringsecuredchannels(HTTPS)onwebbrowsers.WewillcovertheprocessofcreatingsecurecertificatesandusingtheminwebserversaswellastheTURNservice.WewillalsolearnhowtoimplementauthenticationonaTURNserverusingtheTURNRESTAPI.

WewilltalkabouthowWebRTCcanworkthroughfirewallsandNAT,andlearnhowtoconfigureafirewallonourserverthatisservingauxiliaryservicessuchasTURNorSTUN.

Page 124: WebRTC Cookbook
Page 125: WebRTC Cookbook

Generatingaself-signedcertificateUsingencryptionishighlyrecommended(I’dsayevenmandatory)forWebRTCapplications.Thetechnologyhasgoodsupportforsecurityandencryption,sothereisnoreasontoignorethem.Inthisrecipe,wewillcovertheprocessofcreatingself-signedcertificates.SuchacertificatecanbeusedwithaTURNserverorwithawebserverwhenoperatingwithHTTPSchannels.

Typically,apublickeyinfrastructure(PKI)isadigitalsignaturefromacertificateauthority(CA),whichatteststhataparticularPKIisvalidandcontainscorrectinformation.UsersortheirsoftwarethencheckthattheprivatekeyusedtosignacertificatematchesthepublickeyintheCA’scertificate.SinceCAcertificatesareoftensignedbyother,high-rankingCAs,theremustnecessarilybeahighest-rankingCA,whichprovidestheultimateattestationauthorityinthatparticularPKIscheme.

Thehighest-rankingCA’scertificatesaretermedasrootcertificates.Clearly,thelackofmistakesorcorruptionintheissuanceofsuchcertificatesiscriticaltotheoperationofitsassociatedPKI;theyshouldbe,andgenerallyare,issuedwithgreatcare.

Aself-signedsecuritycertificateisacertificatethatissignedbythesameentitywhoseidentityitcertifies.Suchacertificatecanbeusedfordevelopingpurposesandcanbegeneratedbyanybody.

YoucanfindmoredetailsonPKIathttp://en.wikipedia.org/wiki/Public_key_infrastructure.

TipSelf-signedcertificatescanbeusedfordevelopment,butyoushouldissuetrustedcertificatesforproductionsystems.

AllcommunicationchannelsinaWebRTCapplicationshouldbeusingencryption:client-to-client,client-to-server,oranyotherkindofchannelsyoumightbeusing.SomeWebRTCfeatures(suchasscreensharing)willnotworkwithoutencryption,eveninadevelopmentenvironment.

Page 126: WebRTC Cookbook

GettingreadyInthisrecipe,wewillusetheOpenSSLtoolset.

OpenSSLisanopensourcemultiplatformtoolkitthatimplementsSecureSocketsLayer(SSL)andTransportLayerSecurity(TLS)protocolsandprovidesageneralpurposefull-strengthcryptographylibrary.ManycomputersoftwareuseOpenSSLforsupportingencryptionandsecurity.

Youcanfindmoredetailsonthisproductatitshomepage,https://www.openssl.org.

Often,itisinstalledbydefaultonUnix-likesystems,butitisnotsuppliedwithWindowsinstallations.TocheckwhetheryoursystemhasOpenSSLinstalled,youcanusethefollowingconsolecommand:

opensslversion-a

OnmyMac,itproducesthefollowingmessage:

Ifyouseesomethingsimilar,thenyouhaveOpenSSLinstalledonyoursystem.Ifnot,youneedtoinstallthetool.

NoteFormoreinformationonhowtoinstallOpenSSL,pleaserefertoitsofficialhomepageathttp://www.openssl.org.

Page 127: WebRTC Cookbook

Howtodoit…Inthissection,wewillgeneratepublicandprivatesecuritycertificatekeyswiththefollowingsteps:

1. First,generateatemporaryserverpasswordkey:

opensslgenrsa-des3-passoutpass:x-outserver.pass.key2048

Youwillseesomethinglikethefollowingscreenshot:

2. Usingtheserverpasswordkey,generateaserverprivatekey:

opensslrsa-passinpass:x-inserver.pass.key-outserver.key

Youwillseethefollowingoutput:

writingRSAkey

3. Wedon’tneedtheserverpasswordkey,sowecanremoveit:

rm-rfserver.pass.key

4. Generateacertificatesigningrequest:

opensslreq-new-keyserver.key-outserver.csr

5. Thiswillaskyouadditionalquestionsaboutthecompanythecertificateisbeingcreatedfor—youcanusefictionaldata.Itwillalsopromptyouforapasswordasshowninthefollowingscreenshot—forsimplicity,youcanjustpressreturn:

Page 128: WebRTC Cookbook

6. Generatethecertificate:

opensslx509-req-days365-inserver.csr-signkeyserver.key-out

server.crt

Youwillseethefollowingoutput:

Nowyouhavetwofiles,server.crt(thecertificate)andserver.key(thecertificate’sprivatekey),whichcanbeusedwithyourwebserver(operatingoverHTTPS)orTURNserver.

Page 129: WebRTC Cookbook

Howitworks…ByusinganOpenSSLtool,wegeneratedanewself-signedsecuritycertificatethatcanbeusedwithawebserveroraTURNserverthatisservingourWebRTCapplication.

NoteKindlynotethatwegeneratedthecertificateinPEMformat.Forsomesoftware,itmightbenecessarytoconvertittootherformats.

Thoughthecertificateimplementsfullencryption,yourwebsitevisitorswillseeabrowserwarningindicatingthatThecertificateshouldnotbetrusted!.

Ifaself-signedcertificatehasbeenusedtocreateaWebSocketserver,thenyourwebbrowserwillfailwhentryingtoestablishaconnectiontotheserverandwillnotshowanywarning.Tosolvesuchacase,youcanconfigureawebservertobesecured,butleavetheWebSocketserverunsecured;then,youshouldconfigureaWebSocketproxyonthewebserver.Thus,theclientwillcommunicatewiththeWebSocketservernotdirectly,butthroughthewebserverusingasecuredchannel.PleaserefertotheConfiguringaWebSocketsproxyonthewebserverrecipe.

So,useself-signedcertificatesfordevelopingonly.

Page 130: WebRTC Cookbook

There’smore…Forproductionsystems,youshouldusetrustedcertificatesemittedbysuchtrustedcenterssuchasVerisign,Thawte,orothers.

Youcanalsostartwithafree-of-chargebuttrustedcertificatefromStartSSL.Formoredetails,refertohttp://www.startssl.com.

IfyouhaveaWindowsbox,youcanusetheSelfSSL.exetooltocreateaself-signedcertificate.ThistoolispartofInternetInformationServices(IIS)ResourceKitToolsthatcanbefoundathttp://www.microsoft.com/en-gb/download/details.aspx?id=17275.

Youcanalsouseonlinetoolstocreateaself-signedcertificate,forexample,thisoneathttp://www.selfsignedcertificate.com.

Page 131: WebRTC Cookbook

SeealsoYoucanfindmoredetailsonhowtousecertificatesintheConfiguringaTURNserverwithauthenticationandConfiguringawebservertoworkoverHTTPSrecipes.

Page 132: WebRTC Cookbook
Page 133: WebRTC Cookbook

ConfiguringaTURNserverwithauthenticationSTUNserversdon’tsupportauthentication,butontheotherhand,TURNserversdo.Moreover,ifyoumaintainaTURNserver,ithastosupportauthenticationandprohibitanonymousaccess.WhenusingaTURNservice,allthetrafficfromonepeertoanothergoesthroughtheTURNserver.Ifanyonehadanonymousaccesstosuchaserver,theycouldveryquicklyutilizetheserver’sresourcesandtrafficlimits.

Inthisrecipe,wearegoingtogothroughaTURNauthenticationtask.

Page 134: WebRTC Cookbook

GettingreadyFirstofall,weneedtodownloadandinstallaTURNserver.Thereareseveralimplementations,andinthisrecipe,wewillconsiderusingrfc5766-turn-server.

ThissoftwareismultiplatformandcanbeusedonUnix-likesystemsandonWindowssystemsaswell.Nevertheless,tokeepitsimple,inthisrecipe,wewillcoveraLinux-basedcaseonly.

DownloadthesourcecodefromtheTURNserverhomepageathttps://code.google.com/p/rfc5766-turn-server/.

Toinstallthesoftware,youmightneedotheradditionalpackagestobeinstalledfirst:

mysqlclient-dev

libevent

libmysqlclient-dev

libevent-dev

libssl-dev

Pleaseuseyourpackageinstallationtooltoinstallnecessarypackets.

NoteThepackagelistmightvaryfordifferentLinuxdistributions.

UnpackthedownloadedTURNserverpackageintoanewfolder,gotoit,andthencompileandinstallthesoftwareusingthefollowingcommands:

./configure

make

sudomakeinstall

Ifyoudidn’tchangetheinstallationprefix,theconfigurationfilewillbeplacedat/usr/local/etc/turnserver.conf.

Now,weneedtoeditthisfile,changingthenecessaryoptions.Wewillnotcoveralltheconfigurationoptions,butjusttheonesthatarenecessarytoachieveourgoal:

1. First,ensurethesupportforencryptedtransport:

tls-listening-port=5349

2. Switchtheverbosemodeon:

verbose

TipYoudon’twantverboseenabledonaproductionsystem,butitisveryusefulfordebugpurposes.I’drecommendyoukeepitenabledduringthedeveloping/debuggingprocess,andthendisableitwhenyoudeployyourapplicationtotheproductionsystem.

3. Enablealong-termcredentialmechanism—aRESTAPIcanbeusedwithlong-term

Page 135: WebRTC Cookbook

credentialsonly:

lt-cred-mech

4. Commentouttheshort-termcredentialmechanismoption:

#st-cred-mech

5. EnabletheRESTAPI:

use-auth-secret

6. Determinethestaticauthenticationsecret—theclientwillusethisvaluewhencalculatingthetemporarypasswordforaccessingtheTURNserver:

static-auth-secret=<SuperSecretKey>

7. Setuptherealm(usually,thecompany’swebsitedomainname):

realm=mycompany.org

8. Setupthegeneratedsecuritycertificate:

cert=/usr/local/etc/turn_server_cert.pem

9. Setupthecertificateprivatekey:

pkey=/usr/local/etc/turn_server_pkey.pem

10. Setupthesecuritycertificatekeypassword.Thisoptionisimportantifyouuseacertificateprotectedbyapassword.Ifthekeyispassword-less,thenleavethisoptioncommentedout:

#pkey-pwd=

11. Usingtheenableconsolefeature,youcanconnecttotheTURNserverconsoleandcontroltheserver,orjustgetsomestatistics.Itisveryusefulfordebugging:

cli-ip=127.0.0.1

cli-port=5766

12. Setuptheconsolepassword:

cli-password=<you-cli-password>

Page 136: WebRTC Cookbook

Howtodoit…NowwehaveaTURNserverinstalledandconfigured.Next,weneedtomakeappropriatechangesontheclient-sidecode(thatwillbeexecutedbythewebbrowser)andontheserver-sidecode.

Whatisimportantforthisfeatureisthatyourwebapplicationshouldhaveauserauthenticationmechanismimplemented.Theapplicationshouldhaveaprivateareawhereonlyauthorizeduserscangetaccess.

Thecertainimplementationdependsontheplatform/frameworkyouusefordevelopingtheapplication.

Implementingtheclient-sidecodeThegeneralflowtoimplementtheclient-sidecodeisasfollows:

1. Theapplicationhassomekindofauthorizationformwithaloginandpassword.ThewebpagewiththeWebRTCfeatureshouldbehiddenbehindtheloginpageandaccessshouldberestrictedtoauthorizedusersonly.

2. Aftertheuserenterscorrectcredentialsandhasbeenauthorized,he/shecanhaveaccesstoaprivatearea.

3. Whenauserisauthorized,he/sheshouldbeforwardedtotheprivateareawheretheWebRTCinteractivepageisplaced.

4. TheinteractivepagethatausergetsfromthewebservershouldcontaincorrectcredentialsforaccessingtheTURNserver.Thesecredentialsarecalculatedbythewebserverandarethensenttotheauthorizedclient.

Thefollowingfragmentisanexampleofwhatanauthorizedclientshouldgetfromthewebserver:

variceServers=[

{

'url':'turn:turn1.website.com',

'credential':'dejwjhkuyui4BUHiebdiejbi',

'username':'secretuser'

}

];

Here,thecredentialfieldisthetemporarypasswordcalculatedonthewebserverthatcanbeusedtoaccesstheTURNserver.Onlyauthorizeduserscangetit—usernameisalsousedwhilecalculatingthepassword(refertotheImplementingtheserver-sidecodesectionofthisrecipe).

TheclientshouldusethisdatawhenaccessingtheTURNserver(pseudocode):

pc_config={"iceServers":iceServers};

varpc=RTCPeerConnection(pc_config,pc_constraints);

Implementingtheserver-sidecode

Page 137: WebRTC Cookbook

Server-sidecodecanbeimplementedusinganylanguageandtechnologyyoulike.IfyouareaJavaprogrammer,theeasiestwaywouldbetouseJavaSpringorPlayFramework.

Thewebservershouldprovidethefollowingflowforimplementingserver-sidecode:

1. AuthenticatedusersshouldaccesstheWebRTCinteractivewebpageonly.2. Whenauserisauthenticatedusingtheloginpage,theyshouldbeforwardedtothe

privatearea(theWebRTCinteractivepage).3. Duringtheauthenticationprocess,thewebservershouldstoretheuserlogin.4. ThewebservershouldcalculatetheTURNtemporaryaccesspasswordusingthe

followingformula:

base64(hmac(secretkey,username))

Hereyoucanseethefollowing:

secretkey:Thisisthestatic-auth-keyoptionfromtheTURNserverconfiguration(refertotheGettingreadysectionofthisrecipe)username:Thisistheusernamethewebservergetsfromtheuserduringtheauthenticationhmac:Thisisthehashfunctionofsecretkeyandusernamebase64:Thisfunctionimplementsthebase64encodingalgorithm,andweapplyittotheresultofthehmacfunction

5. Afterthetemporarypasswordiscalculated,itshouldbesenttotheclient.

Page 138: WebRTC Cookbook

Howitworks…Inthisrecipe,wewillutilizetheTURNRESTAPI.ThemaingoalofthisAPIistoprovideamechanismthatwillenabledynamictemporarypasswords,whichcanbeusedwithTURNserverswhenauthenticating.

ThegeneralTURNauthenticationflowisasfollows:

Theclient(awebbrowser)sendsarequesttotheapplication(thatisworkingontheserverside)askingforTURNcredentials.Optionally,therequestcanalsoincludetheusername.TheapplicationrespondswithaTURNURL,username,andpassword.

TheclientthenusesthesecredentialsforfurtherauthenticationontheTURNserver.Theapplicationthenreplieswiththefollowingdata:

Username:ThisistheTURNusernamethattheclienthastousewhenauthenticating.Thisnameisacolon-delimitedcombinationoftheexpirationtimestampandusernameparameterfromtheclient’soriginalrequest.Iftheusernameisnotspecified,theservercanuseanyothervaluehere.Password:ThisistheTURNpasswordthattheclienthastousewhenauthenticating.Thisvalueiscalculatedbytheserverusingthefollowingalgorithm:base64(hmac(secretkey,username)).TheTURNserverandtheserverapplicationbothsharethesamesecretkey.So,theTURNserverwilldothesamecalculationsandwillcomparethemtothecredentialsreceivedfromtheclient.

NoteKindlynotethatcredentialsaretemporary(timelimited).

TTL:Thisvaluerepresentsthetime-to-liveparameter.Itisoptionalandwewon’tusethisfieldonourapplication.URIs:ThisfieldrepresentsanarrayofURLsoftheTURNserver(s)available.Inourcase,wewillsendjustoneURLtoourownTURNserver.

Page 139: WebRTC Cookbook

There’smore…Thisfeatureisnotapartofthefinalstandardyet,sointhefuture,someaspectsofthisrecipemightneedtobeimproved.

Page 140: WebRTC Cookbook

SeealsoRefertotheGeneratingaself-signedcertificaterecipeonhowtocreateself-signedcertificates.TakealookattheTURNserver’sRESTAPIstandarddraftathttp://tools.ietf.org/html/draft-uberti-rtcweb-turn-rest.ThePDFfromtherfc5766-trun-serverdocumentationcanbeuseful.Formoredetails,refertohttps://rfc5766-turn-server.googlecode.com/svn/docs/TURNServerRESTAPI.pdf.

Page 141: WebRTC Cookbook
Page 142: WebRTC Cookbook

ConfiguringawebservertoworkoverHTTPSInthisrecipe,wewillcoverhowtoconfigureasecuredlayer(HTTPS)onawebserver.AsfarasencryptionandsecurityaremandatoryforWebRTC,HTTPSisanimportantpartofthewholeapplication’ssecurityandsafety.

Page 143: WebRTC Cookbook

GettingreadyWewillcoverthethreemostpopularwebservers:Nginx,ApacheHTTPServer,andIISfromMicrosoft.Wewillnotcovertheinstallationprocedure,soyoushouldhavethewebserveryouwishtouseinstalledandproperlyconfigured.

Page 144: WebRTC Cookbook

Howtodoit…Whatweneedtodoistoeditthewebserver’sconfigurationtoswitchonusingHTTPS.Beforewemaketheconfigurationchanges,youneedtohavethegeneratedsecuritycertificate.Usually,itistwofiles:acertificateandcertificatekey.Butitispossibletojointhesetwofilesintojustone.Inthisrecipe,wewillconsiderthefirstoption,withtwofiles.

Thesecertificatefiles(server.crtandserver.key)canbetrustedSSLcertificatesortheycanbeself-signedcertificates.

ConfiguringNginxYoushouldeditthewebsite’sconfigurationfile—usually,itislocatedunder/etc/nginx/sites-enabled/website.com:

1. Thefollowingconfigurationfragmentshowsimportantchangesthatyoushouldmake:

server{

2. Wewillaskthewebservertolistenonport443(defaultportforHTTPS)anduseSSL:

listen443ssl;

3. Youshouldalsosetupthewebsite’sname—asyouwoulddoforanon-securedwebsite:

server_namewww.example.com;

4. Forasecuredwebsite,weneedtosetuptheSSLcertificateandSSLcertificatekey.Technically,they’rejusttwofilesgeneratedinaspecificway:

ssl_certificate/etc/nginx/ssl/certs/server.crt;

ssl_certificate_key/etc/nginx/ssl/private/server.key;

}

NoteAgoodpracticeistokeep.crtand.keyfilesindifferentfolders,asyoucanseeintheprecedingcode.Sodon’tforgettocopybothfilesofyoursecuritycertificatetoproperplaces.Createappropriatefoldersifnecessary.

5. Youwillneedtoreloadthewebserverafterthesechanges.ForUbuntu,thiscanbedoneusingthefollowingcommand:

sudoservicenginxreload

6. Alternatively,youcanrestartthewholewebserverusingthefollowingcommand:

sudoservicenginxrestart

ConfiguringApache

Page 145: WebRTC Cookbook

Youshouldeditthewebsite’sconfigurationfile—usually,itcanbefoundunder/etc/apache2/sites-available/website.conf.

Wewillnotcoveralltheconfigurationfilesbutwillconsiderrelevantchanges:

1. AddtheoptiontomaketheApachewebserverlistenontheHTTPSdefaultportNameVirtualHost*:443.

2. MakenecessarychangesintheappropriateVirtualHostsection:

<VirtualHost*:443>

[email protected]

DocumentRoot/var/www/website.com

ServerNamewww.website.com

DirectoryIndexindex.php

ErrorLog/var/log/apache2/vhost1-error.log

CustomLog/var/log/apache2/vhost1-access.logcombined

SSLEngineOn

SSLCertificateFile/etc/apache2/ssl/server.crt

SSLCertificateKeyFile/etc/apache2/ssl/server.key

<Location/>

SSLRequireSSLOn

SSLVerifyClientoptional

SSLVerifyDepth1

SSLOptions+StdEnvVars+StrictRequire

</Location>

</VirtualHost>

3. Afteryou’vemadethesechanges,youneedtorestarttheApacheHTTPServer.

ConfiguringIISInthissection,wewillcoverhowtoconfigureIIStousetheSSLcertificate:

1. Logontothewebservercomputerasanadministrator.2. ClickonStart,pointtosettings,andthenclickonControlPanel.3. Double-clickonAdministrativeTools,andthendouble-clickonInternetServices

Manager.4. Selectthewebsitefromthelistofdifferentservedsitesintheleftpane.5. Right-clickonthewebsiteonwhichyouwanttoconfigureSSL,andthenclickon

Properties.6. ClickontheDirectorySecuritytab.7. ClickonEditandthenonRequiresecure-channel(SSL).8. ClickonRequire128-bitencryptiontoconfigure128-bit(insteadof40-bit)

encryptionsupport.9. Toallowuserstoconnectwithoutsupplyingtheirowncertificate,clickonIgnore

clientcertificates:

Page 146: WebRTC Cookbook
Page 147: WebRTC Cookbook

There’smore…Theconfigurationprocessmightvarydependingonthecertainwebserverversionyouuse.Pleaserefertotheappropriatevendor’sdocumentationprovidedwiththewebserveryouuseforspecificdetails.

Page 148: WebRTC Cookbook

SeealsoRefertotheGeneratingaself-signedcertificaterecipefordetailsonhowtocreateself-signedcertificates.Thereyoucanalsofindadditionalinformationonwheretostartifyouwouldliketogetatrustedcertificatetouseinproduction.

Page 149: WebRTC Cookbook
Page 150: WebRTC Cookbook

ConfiguringaWebSocketsproxyonthewebserverWebSocketsisanewprotocolthatenablesactivemessagingfromservertoclient.Itissupportedbyallmodernwebbrowsers.ThisprotocolisimplementedontopofHTTPandcanbeeasilyservedbymostpopularwebservers.Itcanalsobeservedoversecuredchannels,suchasHTTPS.BecauseofWebSockets’advantages,peopleoftenchoosethisprotocolfortheirclient-serverprojects.InWebRTC-basedapplications,WebSocketsusuallyservesasatransportprotocolforsignalingserverimplementation.

ConfiguringaWebSocketsproxyonawebservercanbeveryusefulifyouhaveusedWebSocketsasatransportlayerforcommunicatingwiththesignalingserver.Forsomecases,itmightevenbemandatory.

Page 151: WebRTC Cookbook

GettingreadyConfiguringthisfeaturerequiresmakingchangesintheconfigurationfilesofthewebserver.Wewillnotcovertheentirewebserver’sinstallationandconfigurationprocess,soyouneedtohavethewebserverupandrunning.

Page 152: WebRTC Cookbook

Howtodoit…Wewillmakenecessaryconfigurationchangestothewebservertoachievethegoal.

ConfiguringNginxThewebsite’sconfigurationfilesareusuallylocatedunderthe/etc/nginx/sites-enabledfolder:

1. ThefollowingpieceofthewebsiteconfigurationfileshowstheWebSocketsproxysettings:

location/websocket{

2. HerewewillsetthelocalservicethatwillbeservingWebSocketrequestsforthewebserver:

proxy_passhttp://localhost:16384;

3. IndicatethatwewillworkwithHTTPprotocolversion1.1—WebSocketsisnotsupportedonlowerHTTPversions:

proxy_http_version1.1;

proxy_set_headerUpgrade$http_upgrade;

proxy_set_headerConnection"upgrade";

proxy_redirectoff;

4. HerewecansetadditionaloptionsaskingthewebservertosendusefuldetailsaboutconnectedclientsintheHTTPheaders:

proxy_set_headerHost$host;

proxy_set_headerX-Real-IP$remote_addr;

proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;

}

5. YouwillneedtorestartNginxorreloaditsconfigurationafteryou’vemadethesechanges.

TipYouneedaseparatelocationsectionforeveryWebSocketURLthatyouneedtoproxyviathewebserver.

ConfiguringApacheApachedoesn’tsupportthisfeaturefromscratch(atleast,forversions>=2.4).Nevertheless,therearesomethird-partymodulesthatcanhelpuswiththis.Inthisrecipe,wewillusetheapache-websocketmodule,availableathttps://github.com/disconnect/apache-websocket:

1. Thefollowingconfigurationfragmentshowshowtousethemodule:

<IfModulemod_websocket.c>

<Location/websocket>

Page 153: WebRTC Cookbook

SetHandlerwebsocket-handler

WebSocketHandler

/usr/lib/apache2/modules/mod_websocket_tcp_proxy.sotcp_proxy_init

WebSocketTcpProxyBase64on

WebSocketTcpProxyHostlocalhost

WebSocketTcpProxyPort16384

WebSocketTcpProxyProtocolbase64

</Location>

</IfModule>

2. OnadefaultApacheinstallation,youmightwanttochangeyourrequestreadtimeoutoption:

<IfModulereqtimeout_module>

RequestReadTimeoutbody=300,minrate=1

</IfModule>

3. YoucantracknativesupportofthisfeatureinApacheusinghttps://issues.apache.org/bugzilla/show_bug.cgi?id=47485.

ConfiguringIISTheWebSocketproxyfeatureisavailableinIISversion8andisnotsupportedinolderIISversions.

YoushouldinstallApplicationRequestRouting(ARR)3.0oranewerversion.Thisisaproxy-basedroutingmodulethatservestoforwardHTTPrequeststocontentservers.

AccordingtoMicrosoft’srecommendations,ARRshouldbeinstalledusingtheWebPlatformInstaller(WebPI)module.

Page 154: WebRTC Cookbook

ChooseApplicationRequestRouting3.0asdepictedintheprecedingscreenshot,andclickontheAddbuttonandthenclickonInstall.Duringtheinstallationprocess,youwillseethescreenshowninthefollowingscreenshot:

Page 155: WebRTC Cookbook

AfterARRisinstalled,youwillseeanappropriatemessageasshowninthefollowingscreenshot:

Page 156: WebRTC Cookbook

Now,whenARRisinstalledsuccessfully,youshouldinstalltheWebSocketsfeaturesonIISusingtheServerManagercomponentanditsManageandAddRolesandFeaturesmenus,asshowninthefollowingscreenshot:

Page 157: WebRTC Cookbook

Oncetheinstallationiscomplete,ARRwillhandleWebSocketsrequestsappropriately.

Page 158: WebRTC Cookbook

Howitworks…UsingsecurechannelsismandatoryforaWebRTCapplication.Inourrecipes,wehaveusedWebSocketsasatransportprotocoltocommunicatewiththesignalingserver.ThemaingoalofusingaWebSocketsproxyistohidetheWebSocketsservice(signalingserver)behindthewebserver,whichisservingoverHTTPS(securedlayer).Insuchacase,wedon’tneedtoconfigureHTTPSonthesignalingserveritself.

Thefollowingdiagramdepictsthewaythisworks.Whentheclient(webbrowser)makesarequesttothesignalingserverusingWebSockets,itdoesn’tmaketherequesttothesignalingserverdirectly,buttothewebserver(usingasecuredchannel,HTTPS).Then,thewebserverforwardsthisrequesttothesignalingserver(usingtheusual,non-securedlayer),andthenitforwardstheresponsebacktotheclient(thewebbrowser).

Thebenefitsofusingsuchasolutionareasfollows:

Youdon’tneedtoopenalisteningportofthesignalingservertotheexternalworldYouneedtoconfigureasecuredlayerforthewebserveronly,andnoneedtoconfigureitforthesignalingserverOntheclientside,youcanusethesamedomainandport

TipThesebenefitsarerelevantifyouhaveawebserverandsignalingserverbothinstalledonthesamemachine.

Page 159: WebRTC Cookbook

There’smore…Theconfigurationprocessmightvarydependingonthecertainwebserverversionyouuse.WebSocketsisayoungtechnologyandisnotsupportedbyoldwebservers.ThewebservershouldsupportHTTP1.1tobeabletosupportWebSocketsandtheWebSocketsproxy.So,youshouldusethenewestwebserverversion.

You’renotlimitedtousingWebSocketsforthesignalingservertransportprotocol.Thisisjustaparticularcase.Youcanuseanytransportyoulikeforthispurpose.So,ifyouprefertousesomethingdifferentratherthanWebSockets,thisproxyfeaturemightnotberelevantforyou,oryoumighthavetouseothersolutionstomakeyourprotocolofchoicesecureandsafe.

Page 160: WebRTC Cookbook

SeealsoInthisrecipe,webuiltthesignalingserverbehindthewebservertoutilizeitsHTTPS(securedlayer).FormoredetailsonhowtoconfigureHTTPSforwebservers,pleaserefertotheConfiguringawebservertoworkoverHTTPSrecipe.

Page 161: WebRTC Cookbook
Page 162: WebRTC Cookbook

ConfiguringafirewallIfyoudevelopaWebRTCapplicationandmaintainyourowninfrastructure(STUN/TURNservers,webservers),thenaproperlyconfiguredfirewallisveryimportantforyou.Usually,everyserverhasanetworkfirewallconfiguredandrunning.Misconfiguredfirewallscanblockservicesandcausesideeffects.WithWebRTC,amisconfiguredfirewallcanleadtheapplicationtoDoS(denialofservice)ormakesomepartsofitunworkable;forexample,youcanhearaudiobutcan’tseevideo.

Inthisrecipe,wewillcoverbasicinformationthatmighthelpyoutoconfigureanetworkfirewallproperly.

Page 163: WebRTC Cookbook

GettingreadyTherearemanyfirewallimplementations,anditisimpossibletocoverallofthem.Sohere,wewillmostlytalkaboutrecommendationsratherthanpracticalcommandsandcodes.

Findwhichfirewallisusedonyoursystem.OnWindows,itisabuilt-infirewall.OnLinuxsystems,youoftenhaveiptables.OnBSDsystems,itcanbepforipfw.MacsystemsusuallyusetoolsfromtheBSDfamily.Yoursystemmightevenbeusingsomekindofthird-partytool,soyoushouldrefertotherelevantdocumentationofthefirewalltoolthatisusedonyoursystem.

Page 164: WebRTC Cookbook

Howtodoit…Itisworthconsideringhowtoconfigureafirewallinthescopeofserversideandclientsideseparately.

ConfiguringafirewallonaserverIfyouhaveyourownserver(s)forallyourWebRTCapplicationcomponents(STUN,TURN,webserver,anyotherkindofnetworkservices),itisworthknowingwhichportsandprotocolscanbeusedbythesecomponentstocreateanappropriatenetworkingpolicy.Otherwise,yourapplicationmightfailtoaccesstheseservices.

DefaultportnumbersforknownservicesrelevantforWebRTCapplicationsareasfollows:

STUN/TURN:Ports3478and5349,UDPandTCP.ThesecondportisusedforTLS.Web:TCPport80forHTTPandTCPport443forHTTPS.Signalingserver:Thisdependsonthetechnologyandprotocolyouuse.Usingthisisagoodideaifyoucanhidethesignalingserverbehindthewebserversothatthesignalingservercanlistenonlocalhostonly,andnotlistentotheexternalworld.Ifyou’reusingTURN,yourservershouldhavetwoIPaddresses—keepthisfactinmindwhenconfiguringafirewall.Alltheprecedingportsshouldbeopenedandaccessibletotheexternalworld.

ConfiguringafirewallonaclientOfcourse,youcan’tcontrolafirewallontheuser’sside.Nevertheless,thefollowingdetailscouldhelpyouwhiledebuggingorproblemsolving.

WebRTChasgreatbuilt-inmechanismsandfeaturestohandlefirewallsandNetworkAddressTranslation(NAT).ItcanutilizeInteractiveConnectivityEstablishment(ICE),whichitsupportsviaTURNandusingSTUNservices.

Thefollowingscreenshotshowstwocases:

ThecommunicationprocessbetweenclientsandthesignalingserverDirectcommunicationbetweenpeersaftersignalization

Page 165: WebRTC Cookbook

Signalizationisnecessarywhenpeersarelocatedondifferentnetworks.Thesignalingservershouldbeknownandaccessibletoallpeers,andthentheycanexchangedatawitheachothervianetworkdatausingthesignalingserver,andthenestablishdirectconnection.

However,ifapeerislocatedbehindaNAT/firewall,thenthiswillnotwork—peershavenowaytoknowtheirownexternalnetworkaddresses,soestablishingthedirectconnectionisproblematic.

Thefollowingscreenshotshowssuchacase:

Page 166: WebRTC Cookbook

Inthiscase,beforepeerscanestablishadirectconnection,aSTUNserviceshouldbeusedbypeerstodetecttheirnetworkparameters.STUNallowspeerstoknowabouttheirexternalIPaddresses.Nevertheless,inmanycasesitwillnotwork—manyusersarelocatedbehindaNATandfirewall.

IfSTUNdidn’thelp,theonlysolutionthatmightsolvetheissueisaTURNserver.Inthiscase,allthedatabetweenpeerswillgothroughtheTURNserver—itwillproxyallmediaandotherdatathatpeerswilltransfertoeachother.Inotherwords,therewillnotbeadirectpeer-to-peerconnectionestablished,andallcommunicationwillbedoneviatheTURNserverinthemiddle.

ThisiswhyyouwillprobablywanttohaveyourownTURNserver—manybusinessclientshaveverystrongnetworkpoliciesandverycomplexfirewall/NATconfigurations,sosimplesolutionswilljustnotworkintheircases.

TipIfyoudevelopyourwebapplicationorserviceusingWebRTC,considerinstallingyourownSTUNandTURNserversattheverybeginning.

TheschemainthefollowingdiagramdepictsthedataflowwhileusingaTURNserver:

Page 167: WebRTC Cookbook
Page 168: WebRTC Cookbook

SeealsoTakealookattheConfiguringaWebSocketsproxyonthewebserverrecipefordetailsonhowtohidethesignalingserver(thecaseusingWebSocketsasthetransportlayer)behindthewebserver

Page 169: WebRTC Cookbook
Page 170: WebRTC Cookbook

Chapter3.IntegratingWebRTCInthischapter,wewillcoverthefollowingtopics:

IntegratingWebRTCwithAsteriskIntegratingWebRTCwithFreeSWITCHMakingcallsfromawebpageIntegrationofWebRTCwithwebcameras

Page 171: WebRTC Cookbook

IntroductionThischapterisfullydedicatedtothetopicofintegratingWebRTCwiththerestoftheworld—othercomponents,technologies,andservices.

YouwillfindrecipesonintegrationofWebRTCwithVoIPplatforms(AsteriskandFreeSWITCH),andwilllearnhowtoimplementasimplesolutionintheMakingcallsfromawebpagerecipeusingWebRTCandSIP.WewillalsocovertheintegrationofWebRTCwithwebcameras.

Inthischapter,wewillnotwritecode,butwillinstallandconfigurethird-partyapplicationsandlibraries,connectingthemwitheachotherinordertoachievethegoal.Mostofsoftwarethatwehavecoverediscross-platform,buttosimplifythetask,wewillcoverLinux-basedinstallationsonly.So,formostofrecipes,youwillneedtohaveapreparedLinuxmachine.Sincewewillconsidersimplecases,itwillnotneedmanyresources,soifyoudon’thaveaready-to-useLinuxbox,youcanusesomespecialsoftwareforcreatingvirtualLinuxmachinetoworkontherecipes.ItcanbeVMware,VirtualBox,oranyothersolutionyoulike.YoucanuseanyLinuxdistributionforthesepurposes;IpersonallyusedUbuntuwhileworkingonthisbook.

NoteSomecommandsorsystempathsmightbedifferentfordifferentLinuxdistributions.

Therecipesofthischapterdon’tcoverallthecompletedsolutionsfromscratch,andcoverspecificquestionsonly.So,itisassumedthatyouhavebasicknowledgeofusingtheLinuxcommandlineandhavebasicexperienceofinstallingandconfiguringLinuxsoftware.

Page 172: WebRTC Cookbook
Page 173: WebRTC Cookbook

IntegratingWebRTCwithAsteriskInthisrecipe,wewillcovertheintegrationofWebRTCwithAsterisk—anopensourceplatformusedtobuildcommunicationsapplications.Asteriskturnsanordinarycomputerintoacommunicationsserver.AsteriskpowersIPPBXsystems,VoIPgateways,conferenceservers,andothercustomsolutions.Itisusedworldwidebysmallandlargebusinesses,callcenters,carriers,andgovernmentagencies.

Asterisk-basedtelephonysolutionsofferarichandflexiblefeatureset.AsteriskoffersbothclassicPBXfunctionalityandadvancedfeatures,andinteroperateswithtraditionalstandards-basedtelephonysystemsandVoiceoverIPsystems.Asteriskofferstheadvancedfeaturesthatareoftenassociatedwithlarge,high-end(andhighcost)proprietaryPBXs.

Page 174: WebRTC Cookbook

GettingreadyInthisrecipe,wewillworkunderLinux.So,prepareaLinuxbox.WealsowillusetoolssuchasGitandSVN—installthemifthey’renotinstalledyetonyourmachine.

YoumightwishtoinstallFreePBXtomakeyourlifeeasierwhenconfiguringAsterisk.Thissoftwarecanbefoundonitshomepageathttp://www.freepbx.org.

IassumethatyouhavesomeexperiencewithinstallingandconfiguringLinuxsoftware.Ifnot,youcanrefertoahelppageonLinuxbasics,forexample,http://manuals.bioinformatics.ucr.edu/home/linux-basics.

Page 175: WebRTC Cookbook

Howtodoit…Duringthisrecipe,wewillinstallandconfigureasetofapplicationsandbuildaservicebyintegratingtheseapplicationswitheachother.Wewillnotcoveralltheinstallationandconfigurationstepsfromscratch,butwillcoverspecificstepsonlythatmightberelevantintothisrecipe.

InstallinglibSRTPBeforewecompileandinstallAsterisk,weneedtoinstalllibSRTP—asoftwarelibrarythatprovidesanSRTP(SecureReal-timeTransportProtocol)implementation.AsteriskshouldsupportSRTPforintegratingwithaWebRTCapplication.ThesupportofthisprotocolisnecessarybecauseWebRTCusessecuredchannelstobuildcommunicationbetweenpeers.WeinstalllibSRTPwiththefollowingsteps:

1. Createadirectory~/src/libsrtpandgotoit.2. Downloadlibsrtptothefolderfromthelibrary’shomepage,

http://sourceforge.net/projects/srtp/files/.3. Unpackthedownloadedarchiveandgointothesrtpfolder.4. Compilethelibrary:

./configureCFLAGS=-fPIC

make

sudomakeinstall

Atthispoint,wehavecompiledandinstalledthelibSRTPlibrarythatwillbeusedwhenbuildingandinstallingAsterisk.

InstallingAsteriskInthisrecipe,wewillinstallAsterisk11.5;performthefollowingstepstodoso:

1. DownloadAsteriskfromthehomepage,http://www.asterisk.org.2. UnpackthearchiveandgointotheAsterisksourcecodefolder.3. ConfigureAsteriskasfollows:

./configure--with-crypto--with-ssl--with-srtp=/usr/local/lib

contrib/scripts/get_mp3_source.sh

makemenuselect.makeopts

menuselect/menuselect--enableformat_mp3--enableres_config_mysql--

enableapp_mysql--enableapp_saycountpl--enablecdr_mysql--enable

EXTRA-SOUNDS-EN-GSM

TipParticularconfigurationoptionsgivenintheprecedingcodecanvarydependingonyourspecificcase.Forexample,youmightbenotusingMySQLbutsomeotherdatabase.InnewestversionsofAsterisk,app_saycountplisreplacedwithapp_saycounted.

4. BuildAsteriskasfollows:

Page 176: WebRTC Cookbook

make

makeinstall

NowwehavecompiledandinstalledAsterisk,wecanconfigurethesoftwarewiththefollowingsteps:

1. Edit/etc/asterisk/sip.confandchangetheGeneralsection:

udpbindaddr=0.0.0.0:5060

realm=<your_server_IP>

transport=udp,ws

2. Edit/etc/asterisk/rtp.conftoenableSTUNandICE:

icesupport=yes

stunaddr=<IP_of_your_STUN_server>

TipIfyoudidn’tinstallyourownSTUNserveryet,youcanusethepublicSTUNservicefromGoogleatstun.l.google.com:19302.

3. Edit/etc/asterisk/http.confandenableanHTTPservice:

[general]

enabled=yes

bindaddr=0.0.0.0

bindport=8088

4. Edit/etc/asterisk/sip.confandcreateaSIPaccount:

[8000]

secret=SuperS3cret

context=from-internal

host=dynamic

trustrpid=yes

sendrpid=no

type=friend

qualify=yes

qualifyfreq=600

transport=udp,ws

encryption=yes

dial=SIP/8000

callerid=JohnDow<8001>

callcounter=yes

avpf=yes

icesupport=yes

directmedia=no

YoucanfindadditionaldetailsonAsteriskconfigurationoptionsathttp://www.voip-info.org/wiki/.

5. Nowthattheconfigurationisfinished,restartAsterisk.

Page 177: WebRTC Cookbook

Howitworks…Thewholeschemaofinteroperationbetweenallthecomponentscanbefoundinthefollowingdiagram(takenfromthesipML5library’shomepage):

Asyoucansee,HTML5clientcaninteractwithaVoIPplatformusingWebRTCandaSIPmodule(JavaScriptSIPinthediagram).

Page 178: WebRTC Cookbook

There’smore…ThereisanopinionthatAsteriskisnotthebestchoice.Itisperhapstheoldestandmostmaturesolutioninthefield.Nevertheless,manypeoplefounditbuggyandunstableinsomecases.Inparticular,WebRTCwasnotsupportedbymanyuntilthepreviousversions.

So,ifyouarelookingforalternatives,itmightbeagoodideatotryothersolutionssuchasFreeSWITCH.Itshomepagecanbefoundathttp://www.freeswitch.org.

Page 179: WebRTC Cookbook

SeealsoForanalternativesolution,usingotherVoIPsoftware,refertotheIntegratingWebRTCwithFreeSWITCHrecipeIntheMakingcallsfromawebpagerecipe,wewillcoverhowtomakecallsfromwebpagesusingWebRTCandaVoIPplatformintegration

Page 180: WebRTC Cookbook
Page 181: WebRTC Cookbook

IntegratingWebRTCwithFreeSWITCHInthisrecipe,wewillcovertheintegrationofWebRTCwithFreeSWITCH—anopensourceplatformusedtomakeVoIPcommunicationservices.

FreeSWITCHisascalableopensourcecross-platformtelephonyplatformdesignedtorouteandinterconnectpopularcommunicationprotocolsusingaudio,video,text,oranyotherformofmedia.Itwascreatedin2006tofillthevoidleftbyproprietarycommercialsolutions.FreeSWITCHalsoprovidesastabletelephonyplatformonwhichmanytelephonyapplicationscanbedevelopedusingawiderangeoffreetools.

Page 182: WebRTC Cookbook

GettingreadyInthisrecipe,wewillworkunderLinuxaswell.So,youneedaLinuxboxtobeprepared.

ItispossibletoinstallFreeSWITCHunderWindows,butwedon’tcoverthisusecaseintherecipe.IfyouneedaWindowsinstallation,pleaserefertotheofficialdocumentationathttp://wiki.freeswitch.org/wiki/Installation_for_Windows.

Duringthework,wewillalsousetoolssuchasGitandSVN—installthemifthey’renotinstalledyetonyourmachine.IassumethatyouhavesomeexperiencewithinstallingandconfiguringLinuxsoftware.

Page 183: WebRTC Cookbook

Howtodoit…Duringthisrecipe,wewillinstallandconfigureasetofapplicationsandbuildaservicebyintegratingtheseapplicationswitheachother.Wewillnotcoveralltheinstallationandconfigurationstepsfromscratch,butwillonlycoverthespecificstepsthatmightberelevanttothisrecipe.

InstallingFreeSWITCHFreeSWITCHcanbeinstalledfromprecompiledbinarypackagesorfromsourcecode.Thefirstwayiseaser,butthevendorrecommendsthesecondone.WeinstallFreeSWITCHwiththefollowingsteps:

1. Installthenecessarypackagesforyoursystem:

apt-getinstallautoconfautomakedevscriptsgawkg++git-corelibjpeg-

devlibncurses5-devlibtoolmakepython-devgawkpkg-configlibtiff5-

devlibperl-devlibgdbm-devlibdb-devgettextlibssl-devlibcurl4-

openssl-devlibpcre3-devlibspeex-devlibspeexdsp-devlibsqlite3-dev

libedit-devlibldns-devlibpq-dev

2. Gotothe/usr/srcfolderandcompilesourcecode:

cd/usr/src

gitclonehttps://stash.freeswitch.org/scm/fs/freeswitch.git

cd/usr/src/freeswitch

./bootstrap.sh–j

./configure--enable-core-pgsql-support

make&&makeinstall

NoteInthiscase,wewillusethemasterversion.Notethatmasterversionsareusuallyunstable,andforproductionsystems,youshouldusestableversionsonly.Forthisinformation,refertothehomepageandclonetherelevantstableversionathttps://www.freeswitch.org.

3. Installsounds:

makecd-sounds-installcd-moh-install

4. Setpermissionsandthefileowner:

cd/usr/local

adduser--disabled-password--quiet--system--home

/usr/local/freeswitch--gecos"FreeSWITCHVoicePlatform"--ingroup

daemonfreeswitch

chown-Rfreeswitch:daemon/usr/local/freeswitch/

chmod-Rug=rwX,o=/usr/local/freeswitch/

chmod-Ru=rwx,g=rx/usr/local/freeswitch/bin/*

NoteFormoredetails,refertohttps://www.freeswitch.org.

Page 184: WebRTC Cookbook

EnablingWebRTCFreeSWITCHsupportsWebRTCfromversion1.4.WebRTCcanbeenabledordisabledbychangingappropriateoptionsintheconfigurationofFreeSWITCH.Bydefault,configurationoptionsthatenableWebRTCarecommentedout,soWebRTCisdisabled.ToenableWebRTCinFreeSWITCH,youshouldopensip_profiles/internal.xmlconfigurationfileandeditappropriateconfigurationoptionsasshown:

<!--uncommentforsipoverwebsocketsupport-->

<paramname="ws-binding"value=":5066"/>

<!--uncommentforsipoversecurewebsocketsupport-->

<!--Youneedwss.pemin/usr/local/freeswitch/certsforwss-->

<!--<paramname="wss-binding"value=":7443"/>-->

YouwillneedtorestartFreeSWITCHafterthischange.

NoteYouneedtouseSSL/TLScertificatesifyouwanttoutilizetheWebSocketssecuredlayer(WSS).

StartingFreeSWITCHYouneedtoaddanewuserintoFreeSWITCH.Pleaserefertotheappropriatepageonthistopicathttps://wiki.freeswitch.org/wiki/XML_User_Directory_Guide.

Afteryou’vemadealltheconfigurationsteps,starttheFreeSWITCHbyusingthefollowingcommand:

cd/usr/local/freeswitch/bin

./freeswitch

NowwehaveFreeSWITCHinstalledwithenabledwiththesupportofWebRTC.

Page 185: WebRTC Cookbook

Howitworks…It’sbettertouseadiagramtodescribetheworkflow,sohavealookatthefollowingdiagram:

Page 186: WebRTC Cookbook

There’smore…FreeSWITCHisnottheonlyVoIPplatformsolutionexistingintheworld.Oneofthebest-knownalternativesisAsterisk.

Decidingwhichparticularsolutionmightfityourrequirementsisalluptoyou.TheybothhavesupportforWebRTCsincethelastversions(middleof2014).Sotheybothmightcontainsomebugsorfeaturesrelatedtothetechnology.

AsteriskseemstobeolderandmorematurethanFreeSWITCH.Therearemorehacksandthere’smoredocumentationrelatedtoAsteriskthanFreeSWITCH.

SoifyouarelookingforalternativestoFreeSWITCH,itmightbeworthtryingAsterisk.Itshomepageishttp://www.asterisk.org.

Page 187: WebRTC Cookbook

SeealsoForanalternativesolution,usingotherVoIPsoftware,refertotheIntegratingWebRTCwithAsteriskrecipeIntheMakingcallsfromawebpagerecipe,wewillcoverhowtomakecallsfromwebpagesusingWebRTCandaVoIPplatformintegration

Page 188: WebRTC Cookbook
Page 189: WebRTC Cookbook

MakingcallsfromawebpageInthisrecipe,wewillcovertheprocessofmakingcallsfromwebpages.Forthistask,youwillneedtorunaVoIPservice.ItcanbeyourownAsteriskorFreeSWITCHinstallation,oritcanbesomeexternal,cloud,orSaaSVoIPsolution.

Toachieveourgoal,wewilluseanHTML5SIPlibrarytomakecallsfromawebpagetoaphonenumberandviceversa.

Page 190: WebRTC Cookbook

GettingreadyInthisrecipe,wewillworkunderLinux,soprepareaLinuxbox.WewillalsousetoolssuchasGitandSVN—installthemifthey’renotinstalledyetonyourmachine.

Youwillneedawebserverinstalled.ItmightbeNginx,ApacheHTTPServer,oranyotherwebserveryoulikethemost.IassumethatyouhavesomeexperienceofinstallingandconfiguringLinuxsoftware.

Page 191: WebRTC Cookbook

Howtodoit…Duringthisrecipewewillinstallandconfigureasetofapplicationsandbuildaservicebyintegratingtheseapplicationswitheachother.Wewillnotcoveralltheinstallationandconfigurationstepsfromscratch,butwillonlycoverspecificstepsthatmightberelevanttothisrecipe.

InstallingsipML5ThefirstHTML5SIPclientissipML5.Wewillusethislibraryinthisrecipetoachieveourgoal.

1. Gointoyourdefaultwwwfolderofthewebserver.Itmightvaryondifferentsystems.ForUbuntuitcanbe/usr/local/www.

2. DownloadthesipML5sourcecode:

svncheckouthttp://sipml5.googlecode.com/svn/trunk/

3. GiveAsteriskaccessrightstodownloadedtheproject:

chown-Rasterisk:asterisk/usr/local/www/trunk/

4. OpentheChromewebbrowserandnavigatetohttp://<your_IP>/trunk/call.htm.

Here,your_IPistheIPaddressofyourmachinewheresipML5hasbeeninstalled.

5. GotoExpertModeandsettheoptionsasdepictedinthefollowingscreenshot:

Page 192: WebRTC Cookbook

Putyouractualmachine’sIPaddressinsteadofyour_IP.

TipIfyouhaveyourownSTUNserverinstalled,youcanspecifyitsIPornameattheICEServersoption.

6. Savethechanges.7. Nowgetbacktothefirsttabandfillinthefieldsasdepictedinthefollowing

screenshot:

Notethatyoushouldoutyourmachine’sactualIPaddress(whereAsteriskandsipML5areinstalled)insteadoftheyour_IPword.

TipUsethesamepasswordyouconfiguredforAsterisk(SuperS3cretinthisrecipe).

NowclickonLogin—youshouldseeaConnectedstatuslineatthetopoftheRegistrationbox.

NowyoucantrytomakeanoutgoingcallusingtheCallcontrol—callonanynumberthatisservedbytheVoIPplatform(AsteriskorFreeSWITCH)andisregisteredinthesystem.Incomingcallsshouldworkaswell;youcancheckthemusinganySIPsoftphoneclient.Hereareafewofthem:

Bria:Formoreinformation,gotohttp://www.counterpath.com/bria

Telephone:ToknowmoreaboutTelephone,refertohttps://github.com/eofster/Telephone

Page 193: WebRTC Cookbook

Zoiper:Formoredetails,refertohttp://www.zoiper.com/en

ExpressTalk:Refertohttp://www.nch.com.au/talk/formoreinformation

3CXPhone:Formoreinformation,gotohttp://www.3cx.com/voip/softphone/

X-Lite:ToknowmoreaboutX-Lite,refertohttp://www.counterpath.com/x-lite

Page 194: WebRTC Cookbook

Howitworks…Theworkingflowofthisconstructedsoftwaresystemmightbelookingrelativelycomplexforsomeonewhoisnotbuildingsuchsystemseveryday.Although,theworkingflowoftheintegratedsystemisnotthatcomplex:

HTML5SIPclient(sipML5inourcase)isjustaVoIPsoftphoneimplementedtoruninthebrowser.Thein-browsersoftphoneusesWebRTCtechnologytogetaccesstothecomputer’smultimedia(cameraandmicrophone).ThenusingWebRTC,SIPprotocol,andWebSockets,thein-browsersoftphoneestablishescommunicationwiththeVoIPplatform(AsteriskorFreeSWITCHforexample).Then,thesoftphoneregistersinthesystem.Afterthat,thesoftphonebecomesavailabletotheusertomakecalls.Thus,thein-browsersoftphonebecomesabletomakephonecallstootherendpointsoftheVoIPplatform.IftheVoIPplatformhasagatetoanexternalphonenetwork,youcanevenmakeexternalphonecallsusingjustthein-browsersoftphone.

Page 195: WebRTC Cookbook

There’smore…ThesipML5libraryisnottheonlysolutionthatcanbeusedforthistask.Thereareseveralalternativesoftwarepiecesthatcanbeusedinthisscopeaswell.Herearetwoexamplesofthem:

SIP.js:Formoreinformation,refertohttp://sipjs.com/

JsSIP:Refertohttp://jssip.net/formoreinformation

Eachlibraryhasitsownprosandconsandcanbesuitableforyourparticularexpectationsandrequirements.Thecommonintegrationschemaremainsthesame,soyoucantrydifferentsoftwareanddecidewhichoneisbestforyou.

Page 196: WebRTC Cookbook

SeealsoYouwillneedaVoIPplatform(SIPserver)installedtomakecallsfromawebpage.Youcanuseanexistingexternalserveroryoucaninstallyourown.ToinstallyourownVoIPplatform,pleaserefertothefollowingrecipes:

RefertotheIntegratingWebRTCwithAsteriskrecipetolearnhowtointegrateWebRTCwithAsteriskRefertotheIntegratingWebRTCwithFreeSWITCHrecipetolearnhowtointegrateWebRTCwithdifferentVoIPsolutionssuchasFreeSWITCH

TipItwouldprobablybegoodideatouseanexternalorcloudVoIPplatformforsuchpurposesinproduction.Maintainingagood,working,andscalableVoIPplatformcannotbeeasy.

Page 197: WebRTC Cookbook
Page 198: WebRTC Cookbook

IntegrationofWebRTCwithwebcamerasInthisrecipe,wewilldiscusshowtointegrateWebRTCwithwebcameras.WhymightsomeonewanttointegrateawebcamerawithWebRTCtechnology?Herearesomereasonswhytheymightdothis:

AwebcameraneedsaJavaorActiveXenabledontheclientforittobeableseetheimagefromthecamera.ManycomputershaveJavainstalled;neverthelessinsomecases,itmightbeimpossibletoinstall/useJavaorActiveX.RegardingActiveX,thistechnologyissupportedevenonfewerdevicesthanJava.WebRTCcanbecomeauniversalandlightweightwaytoshowmultimediafromawebcamandthatdoesn’tneedyoutoinstallanyadditionalsoftware.Asofnow,WebRTCisfullysupportedonAndroiddevices(mostlytheonesthatuseChromemobile),butinthenearfuture,itissupposedtobesupportedonothermobileplatformsaswell(suchasiOSandWindowsMobile).Atthistime,youusuallyhavetoinstallJVMorFlashPlayerinyourmobileifyouwanttoseeavideofromawebcam.Often,itisbarelypossibleatall.Webcamsusuallyareveryresourcelimiteddevices.Whenseveralclientsaccessthecameraatonetime,itcanshowtimedelaysandcanevengetstuck.SuchanissuecanbesolvedveryeffectivelybyusingofaWebRTCapplicationthatisintegratedintotheconnectionbetweentheuserandthecamera.

Herewecoverpossiblesolutionforsuchatask:capturingavideofromawebcam,transcodingitintoWebRTCflow,anddisplayingitinthewebbrowser.

Page 199: WebRTC Cookbook

GettingreadyTherearemanywaysinwhichwebcamsgiveoutvideos.Usually,itcanbeasetofJPEGimagesorRTSPflow.Inourexperiments,wewillcoverthesecondcaseandwilluseaD-LinkDCS-5220webcamera.

Soforthisrecipe,youneedawebcamthatcandoRTSP.Inmycase,itisD-Linkbutyoucanuseanyotherwebcam—therecipewillstillberelevant,butsomeminorchangesmightbenecessary.Installandconfigurethewebcamandconnectittothenetwork.

Inthisrecipe,wewillalsoinstallandconfiguretheWebRTCmediaserver—thissoftwareiswritteninJava,soyouneedJVMinstalledinyourbox.Onemorethingthatyouwillneedtodoisinstallawebserver.YoucanuseNginx,ApacheHTTPServer,oranyotherwebserverofyourchoice.

Page 200: WebRTC Cookbook

Howtodoit…Wewillconfigurethewebcam.ThenwewillinstallandconfiguretheWebRTCmediaserver,andthenwewillconnectallthecomponentsinthewholesystem.

ConfiguringthewebcamFirstofall,wewilldosomeminorconfigurationswiththewebcamera.Todoso,performthefollowingsteps:

1. Navigatetothewebcam’sadminpageandopentheNETWORKSETUPmenu.WeneedtogototheRTSPsection:

Inthissection,weneedtolookfortheRTSPportparameter—itshouldbe554bydefault.ItisalsoworthtosettheRTSPAuthenticationfieldtotheDisablestate—forthetimebeingwe’reworkingonthetask.

Checkwhetherthewebcamworksasexpected.Forthis,youcanuseVLCmediaplayer—justopenrtsp://cam_IP/live1.sdpintheplayer.

TipNotethatyouneedtoinserttherelevantIPaddressofthewebcamerainsteadofcam_IP.Ifthecameraisconfiguredthecorrectway,youwillseeavideocapturedfromit.

InstallingWebRTCmediaserverAsweknowalready,ourwebcamerastreamsmediaoverRTSP,butwewanttowatchthatstreaminawebbrowserusingWebRTC.SoyouhavetoconvertthemediafromRTSPtotheWebRTCform.Forthispurpose,wewillusetheWebRTCmediaserverfromFlashphoner.

ThissoftwarecancapturemediafromRTSPstreamer,re-encodeit,andstreamitinWebRTC:

1. Downloadthemediaserverfromitshomepageathttp://flashphoner.com/download_webrtcserver/.

Page 201: WebRTC Cookbook

2. Unpackthearchive:

tar-xvzfFlashphonerMediaServerWebRTC.tar.gz

3. Installtheserver:

cdFlashphonerMediaServerWebRTC

./install.sh

TipDuringtheinstallation,youwillbeaskedonthepublicandprivateservers’IPs.Ifyou’reexperimentingonyourlocalmachine,boththeIPsmightbeidentical.

4. Startthemediaserver:

servicewebcallserverstart

5. Checkwhetherthatserverisrunning:

ps-ax|grepFlashphoner

TipYoualsocanlookintoyourmediaserver’slogfilestocheckwhethereverythingisallright:/usr/local/FlashphonerWebCallServer/logs/server_logs/flashphoner.log.

6. Gotoyourwebserver’swwwfolder—inmycaseitis/usr/local/www:

cd/usr/local/www

7. DownloadthewebUIfilesintothefolder:

wget

https://github.com/flashphoner/flashphoner_client/archive/wcs_media_cli

ent.zip

ClientswillaccessthisUIviathewebserverinordertoseethecapturedmediastreamsfromthewebcamera.Inotherwords,thisistheUIforthemediaserver.

8. Unpackthearchive:

unzipwcs_media_client.zip

9. Thereareseveralnestedemptyfoldersinthearchive,soitisworthwhilemovingthenecessaryfilestotheupperlevelandmakinglifeabiteasierwiththefollowingcommands:

mvflashphoner_client-wcs_media_client/client/wcs_media_client./

rm-rfflashphoner_client-wcs_media_client/

10. Editthiswcs_media_client/flashphoner.xmlconfigurationfileandsettheproperIPaddressoftheWebRTCmediaserver:

<flashphoner>

<wcs_server>188.226.144.63</wcs_server>

<ws_port>8080</ws_port>

Page 202: WebRTC Cookbook

<video_width>1280</video_width>

<video_height>720</video_height>

</flashphoner>

Themediaserverisnowinstalledandproperlyconfigured!

TimeformagicNowwheneverythingisconfiguredandrunning,itistimetodothemagic.Fromyourwebbrowser,gotohttp://<server_IP>/wcs_media_client/?id=rtsp://<cam_IP>/live1.sdp.

ThefollowingparametersarementionedintheprecedingURL:

<server_IP>:ThisistheIPaddressofthemachinewheretheWebRTCmediaserverwithitsUIisinstalled<cam_IP>:ThisistheIPaddressofthewebcamera

WhilenavigatingtotheURL,youwillfirstseeanimagefromthemediaserver,asshowninthefollowingscreenshot:

Atthisstage,theWebRTCmediaserverwilltrytoconnecttothecameraandnegotiatewithitregardingthestreamcapturing.Itcantakeseveralseconds.Whenthe

Page 203: WebRTC Cookbook

communicationprocessisdone,theserverbeginscapturingthemediastreamfromthecameraandencodingitintotheWebRTCformat.Afterthat,youwillseetheimagefromthecamera.

Page 204: WebRTC Cookbook

Howitworks…Thefollowingdiagramdepictsthegeneralschemaofwhatwebuiltinthissolution:

Asyoucansee,theWebRTCmediaservercapturesthestreamfromthewebcameraandthentheclientscanseethecapturedstreamintheirwebbrowsersusingWebRTC.Whatisimportanthere,isthatclientsarenotconnectedtothewebcamandtheydon’tgetmediastreamedfromthewebcamdirectly;instead,clientsareconnectedtotheWebRTCmediaserver,andtheygetallmediastreamsfromthemediaserver.

Inthefollowingdiagram,youcanseetheworkflowofhowitworks,stepbystep:

Page 205: WebRTC Cookbook
Page 206: WebRTC Cookbook

There’smore…Youmightwanttotakealookatanothersolution—janus-gateway.Formoreinformationrefertohttps://github.com/meetecho/janus-gateway.

Thissolutionisopensource(whiletheserverfromFlashphonerisnot).Atthetimeofwritingthis,itworksunderLinuxonly,butitsauthorsclaimcross-platformsupportinthefuture.

Anotherpopularmediaserver,Wowza,canalsocapturetheRTSPstreamfromcameras,butitsmainpurposetore-encodemediadataintoFlash,soforWebRTC,thissolutionishardlysuitable.Nevertheless,Wowzacanbeaninterestingsolutionaswell,forexample,ifyouneedyourapplicationtosupportFlashtechnologyalongwithWebRTC.Thissoftwarecanbefoundathttp://www.wowza.com.

ManycamerasstreamtoMotionJPEG,andthisrecipeisirrelevantforsuchdevices.Nevertheless,itispossibletobuildasimilarsolutionforthemaswell,usingsimilarschema.

Page 207: WebRTC Cookbook
Page 208: WebRTC Cookbook

Chapter4.DebuggingaWebRTCApplicationInthischapter,wewillcoverthefollowingtopics:

WorkingwithaWebRTCstatisticsAPIDebuggingwithChromeDebuggingTURNDebuggingusingWireshark

Page 209: WebRTC Cookbook

IntroductionDebuggingisaveryimportantaspectindevelopingacomputersoftware.Evenifyouareanexperienceddeveloperandwriteverycleanandprofessionalcode,youmightfacesomesituationswhentheonlygoodwaytounderstandwhat’sgoingwrongisdebuggingandprofiling.

Inthischapter,wewillcoverdebuggingwithinthescopeofdevelopingWebRTCapplications.WewilltalkaboutspecificusefultoolsbuiltinChromewebbrowser,whichcanbehelpful.Also,wewillcoverbasicquestionsofdebuggingJavaScriptapplicationsinthescopeofthemaintopic.Ofcourse,wewillcovertheserversideaswell.

WebRTChasaveryusefulAPIknownasstatisticsAPI;itcanbeusedformonitoringanddebuggingWebRTCapplications.Wewillcoverthistopicintheappropriaterecipe,consideringreal-worldusecasesandpracticalpossiblesolutions.

AWebRTCapplicationusuallyworksveryintensivelywithnetwork.Therefore,wewilllearnhowtouseWireshark(anetworksniffer)fordebuggingpurposesinthescopeofdevelopingWebRTCapplicationsandservices.

Page 210: WebRTC Cookbook
Page 211: WebRTC Cookbook

WorkingwithaWebRTCstatisticsAPIWebRTC’sstandarddescribesstatisticsAPI—amechanismthatanapplicationcanuseforgettingmanykindsofstatisticaldata.Usingthismechanismcanbehelpfulwhendebuggingapplications,becauseyoucangetaccesstosomehiddendatathatisnotvisibletotheapplicationortoacustomerinanyotherway.

UsingthispartofAPIyoucanbetterunderstandwhatisgoingonunderthehoodofthewebbrowserandyourapplication.Itisveryusefulifyouareabeginnerandwouldliketoknowmoreonhowallthisworks.Itisalsohelpfulifyou’reanexperienceddeveloperandarecreatingsomeadvancedfeatureintheapplication.

Page 212: WebRTC Cookbook

GettingreadyForthisrecipe,wewillnotdomuchconfigurationwork.WewillnotinstallanylibrariesorcompileLinuxsoftwarelikewedoinsomeotherrecipes.Thisrecipeisdedicatedtodebuggingandmostofthetopicisdedicatedtoclientside.Therefore,mostofthematerialisaboutJavaScript,thewebbrowserandbrowser’sconsole.

IwouldrecommendyouuseChromeforthisrecipe,becausethisbrowserstillseemstobemorestableinthescopeofsupportingWebRTC.Moreover,usuallyChromehasbetterandmoreadvancedsupportforthistechnology.

Page 213: WebRTC Cookbook

Howtodoit…Foraccessingthestatisticsdata,youshouldusethegetStatsAPIfunction(amethodofPeerConnectioninstances).Whilecallingthisfunction,youhavetopasstheselector.Inreply,thebrowserwillreturnrelevantstatisticaldata.

SinceWebRTCisstillunderdevelopment,theAPIfunctionsmightstillhavedifferentnamesinthesupportedwebbrowsers.Tosolvethisissue,itisworthwhiletowriteadditionalcodethatcouldserveasawrapperanduniversalAPItothefunction.Thefollowingcodecanbeusedasasimpleexampleofsuchbehavior:

functionmyGetStats(peer,callback){

if(!!navigator.mozGetUserMedia){

peer.getStats(

function(res){

varitems=[];

res.forEach(function(result){

items.push(result);

});

callback(items);

},

callback

);

}else{

peer.getStats(function(res){

varitems=[];

res.result().forEach(function(result){

varitem={};

result.names().forEach(function(name){

item[name]=result.stat(name);

});

item.id=result.id;

item.type=result.type;

item.timestamp=result.timestamp;

items.push(item);

items.push(item);

});

callback(items);

});

}

};

Nowlet’swriteafunctionthatwewillcallfromtheapplicationtogetthestatistics.Thisfunctionwillprintstatisticaldatatothebrowser’sconsoleevery5seconds:

functionprintStats(peer){

myGetStats(peer,function(results){

for(vari=0;i<results.length;++i){

console.log(results[i]);

}

setTimeout(function(){

printStats(peer);

},5000);

});

Page 214: WebRTC Cookbook

}

Next,weshouldputthefunctioncallintheproperplaceintheapplication.Somewhereinyourapplication,youshouldcreateapeerconnectionobjectusingaconstructionsimilartothefollowing:

pc=newRTCPeerConnection(pc_config,pc_constraints);

Afterthat,youshouldsetuptheonaddstreamcallbackofthecreatedobject:

pc.onaddstream=onRemoteStreamAdded;

Here,onRemoteStreamAddedisacallbackfunctionthatiscalledoncewhenpeerconnectionisestablished.Inthefollowingcallbackfunction,youshouldaddsomecodethatcallstheprintStatsfunction,whichwehavejustwrittenintheprecedingcode:

varonRemoteStreamAdded=function(event){

clog("Remotestreamadded.");

attachMediaStream(remoteVideo,event.stream);

remoteStream=event.stream;

printStats(pc);

};

Ihaveprovidedthefulllistofthefunctionsheretoshowthebigpictureandmakeitclear.YoucanseeinthefollowingscreenshotthatafterthemediastreamisattachedtothepropervideoHTMLtag,wecallprintStatssothatitprintsthestatisticaldatatotheconsoleevery5seconds:

Page 215: WebRTC Cookbook

HereyoucanseeascreenshotofanexamplewebpagethatusesthedescribedprintStatsfunction.Thewebbrowserconsoleisopened,andyoucanseethestatisticaldataprintedthere.Thestatisticaldatalooksincomprehensible,butthefollowingscreenshotswillgiveyoumoredetails,makingitclearer.

Thefollowingscreenshotdepictsapartofthebrowser’sconsolewithoneoftheexpandedstatisticdataobjects.Inthescreenshot,youcanseetheObjectstructure,andaccordingtoitsoptionsitisanaudiotrack:itsinputlevelis131,itsusedcodecisOpus,andtherewerearound300kilobytessentthroughthischannel.Youcanalsoseeotherusefulinformationregardingthisobject,suchasechocancellationfeaturedetails.

Anotherscreenshotpresentsonemoreexpandedstatisticobject.Inthefollowingscreenshot,youcanseethatwedealwithvideodata,wehaveadelayof33milliseconds,andtheframesizeis640x480.Moreserviceinformationispresentinthefollowingscreenshot:

Let’sseeonemoreexamplescreenshot.Inthefollowingscreenshot,wecanseethatthe

Page 216: WebRTC Cookbook

usedvideocodecisVP8,thevideoframesizeis640x480,andaround13megabytesofvideodatahavebeensentthroughthismediachannel:

ThegetStatsWebRTCAPIfunctioncanbeveryusefulnotonlyfordebuggingpurposes.Thisfunctioncanbehelpfulformanyusecases,forexample:

Monitoring:Inthisusecase,ifyouhaveyourwebservicerunning,youprobablywanttomonitoritsstatedynamically,toknowhowwelltheresourcesareutilizedandsoonTests:Forthisusecase,ifyou’reworkingonsomefeatureorjustimplementingsomenewfunctionalityinyourapplication,statisticsAPIcanbehelpfulwithA/BtestingTroubleshooting:Inthisusecase,ifyourapplicationdoesn’tworkbysomereasonforacustomer,youcanusethismechanismtotracktheissueandfindtherootcause

CheckingestimatedbandwidthWejustconsideredacommoncaseofusingWebRTCstatisticsAPI.Nowwewillconsiderapracticalexampleofusingthismechanism.Inparticular,wewilltrytoknowourestimatedbandwidthforthevideochannelusedinourapplication.

Thefollowingfunctioncollectsstatisticaldatarelatedtothebandwidthutilizationandprintsasimplereportontheconsole:

functionprintStats(peer){

ThemyGetStatsfunctionisdescribedasfollowsandcanbefoundintheHowtodoit…sectionofthisrecipe:

myGetStats(peer,function(results){

for(vari=0;i<results.length;++i){

varres=results[i];

Checkifwehaveavideoobject:

Page 217: WebRTC Cookbook

if(res.googCodecName=='VP8'){

if(!window.prevBytesSent)window.prevBytesSent=

res.bytesSent;

GetthebytesSentvalueasfollows:

varbytes=res.bytesSent-window.prevBytesSent;

window.prevBytesSent=res.bytesSent;

Nowconvertthevalueintokilobytes:

varkilobytes=bytes/1024;

console.log(kilobytes.toFixed(1)+'kilobytesper

second');

}

}

setTimeout(function(){

printStats(peer);

},1000);

});

}

Wehavesetthetimeoutvalueto1,000milliseconds.ThuseverysecondthisfunctiongetsstatisticsusingWebRTCAPI,extractsthesentbytesvaluefromtheappropriateobject,andcalculatesthebitrate.Thefollowingscreenshotdepictswhatyoushouldseeinthebrowser’sconsole:

ThefollowingsectionrepresentsonemoreusecasethatyoumightfacewhiledevelopinganapplicationoraserviceusingWebRTCfeatures.

CheckingpacketlossInthissection,wewillconsideranotherusecase:checkingpacketloss.ThisisanexampletakenfromtheWebRTCstandarddraft,abitadaptedtoourcodebase.Inthescenario,theuserisexperiencingbadsound,andtheapplicationwantstodeterminewhetherpacketlosscausesthisissuewiththefollowingsteps:

Page 218: WebRTC Cookbook

1. Firstofall,let’sdeclarethevariableswherewewillstorebaselinevaluesandcurrentvalue:

varbaselineReport,currentReport;

2. Next,writeinitializationfunction—itwillmakefirstcalltostatisticsAPIandstorethefirstvalueasbaseline:

functioninitStats(peer){

myGetStats(peer,function(report){

baselineReport=report;

});

3. Now,usingtimer,wewillgetstatisticseveryonesecondandprocessit:

setTimeout(function(){

myGetStats(peer,function(report){

currentReport=report;

processStats();

});

},1000);}

4. Thefollowingfunctiondoesalltheprocessingwork:

functionprocessStats(){

//comparetheelementsfromthecurrentreportwiththebaseline

foreach(varnowincurrentReport){

if(now.type!="outbund-rtp")continue;

//getthecorrespondingstatsfromthebaselinereport

base=baselineReport[now.id];

if(base){

remoteNow=currentReport[now.remoteId];

remoteBase=baselineReport[base.remoteId];

varpacketsSent=now.packetsSent-base.packetsSent;

varpacketsReceived=remoteNow.packetsReceived-

remoteBase.packetsReceived;

//iffractionLostis>0.3,wehaveprobablyfoundthe

culprit

varfractionLost=(packetsSent-packetsReceived)/

packetsSent;

if(fractionLost>0.3){console.log("fractionLostistoo

big:"+fractionLost);}

}

}

}

5. Now,thefollowingcoderepresentshowallthatwejusthavewrittencanbeusedintheapplication:

varonRemoteStreamAdded=function(event){

clog("Remotestreamadded.");

attachMediaStream(remoteVideo,event.stream);

remoteStream=event.stream;

initStats(pc);

};

Page 219: WebRTC Cookbook

Here,wewillcalltheiniStatsfunction.ThisfunctionwillgetthefirstdatafromthestatisticsAPI;storeitinthememory,andsetupatimeforonesecond.Then,everysecondanotherfunctionwillbecalled—itwillgetthenextstatisticssampleanddocalculationstryingtodetermineifsomethingiswrongwiththepacketlossvalue.

Page 220: WebRTC Cookbook

Howitworks…ThewebbrowsercollectsandmaintainsasetofstatisticdatathatcanbeaccessedviaWebRTCAPI.Whenaccessingthisdata,youshoulduseaselector—somethingthatdeterminesthekindofdatayouwanttoretrieve.

Theselectormight,forexample,beaMediaStreamTrackobject.Inthiscase,thevalidselectormustbeamemberofaMediaStreamobjectthatissentorreceivedbythePeerConnectionobject,forwhichstatisticsisrequested.

NoteUsingtheselectorandcallingthegetStatsfunction,youwillgetstatisticsdatapackedinaJavaScriptobject.Thenyouneedtoparseitandgetthenecessaryvalue.MostWebRTCAPIfunctionsallowyoutosetupanerrorfunctioncallback.Thisfunctionwillbecalledifsomethinggoeswrong;usuallysuchcallbackfunctionsservetoprinterrormessagesinaconsole.Usingtheseerrorcallbacksismandatory.Evenifyoudon’tpasstheerrorcallbackandeverythingworkswell,thesituationmightchangewiththenextbrowserupdate,andyourapplicationwillthrowanexception.Thereforedon’tmisstheerrorcallbacks!

Page 221: WebRTC Cookbook

There’smore…Formoredetails,refertoWebRTCstandarddraftathttp://dev.w3.org/2011/webrtc/editor/webrtc.html,whereyoucanfindmoreinformationregardingthispartofAPI.Thestandardisinthedraftstageyet,sosome(ormany)conceptsmightbechanged.

Page 222: WebRTC Cookbook

SeealsoTakealookattheDebuggingwithChromerecipe.Chromehasasetofbuilt-inWebRTC-relatedtoolsthatmightbehelpfulwhendevelopinganddebuggingWebRTCapplications.

Page 223: WebRTC Cookbook
Page 224: WebRTC Cookbook

DebuggingwithChromeChromeisawebbrowserdevelopedbyGoogle—thecompanythatinvestsinWebRTCdevelopmentveryintensively.ChromeusuallyhasthemostadvancedsupportofWebRTCfeaturesthanotherbrowsers,andnewandexperimentalfeaturesusuallyappearfirstinChrome.

Thus,itisnotsurprisingthatChromehasgoodtoolsfordebuggingtheWebRTCstack.Someoftherelevantdetailswillbecoveredinthisrecipe.

Page 225: WebRTC Cookbook

GettingreadyForthisrecipe,youwillneedChromeinstalled.Itisamultiplatform,soyoucandownloadtherelevantinstallationpackfromitshomepageathttps://www.google.com/chrome/browser/.

Page 226: WebRTC Cookbook

Howtodoit…TherearetwoknownChromemechanismsthatcanbeusefulfordebuggingWebRTCapplications:

WebRTC-internalsLogging

Inmostcases,youprobablywillusethefirstone.

Usingwebrtc-internalsWebRTC-internalsisabuilt-inmechanisminChromewiththeuseofwhichyoucangetaccesstoavarietyofWebRTCstack-relatedinformationandstatisticsdata.

OpenaChromewebbrowserandgototheURLchrome://webrtc-internals/.

Ifyouhaven’topenedanyWebRTCapplicationyet,youwillnotseeanythinginteresting.Nowinthenewtab,openawebpageofawebapplicationwhereaWebRTCAPIisutilized,andrefreshthepagethathasopenedweb-internals.Youwillseesomethingsimilartowhatisdepictedinthefollowingscreenshot:

Hereyoucanseethescreenshotofarealapplication;itsURLispresentatthetopofthewindow.Inthebrackets,youcanseethelistofSTUN/TURNserversthatthewebbrowser

Page 227: WebRTC Cookbook

usesforestablishingpeer-to-peerconnection.There,alsoshownaretheoptionalparametersthatarespecifiedwhilecreatingthatpeerconnection,forexample,theDtlsSrtpKeyAgreementoption.

Belowthelistthereareseverallineswithhorizontalarrowsthatcanbeexpanded,andthereyouwillfindadditionaldetailsregardingtheapplicationandWebRTCstack.Thereisnotmuchinformationthatcanbedisplayedbecauseatthisstagethedirectpeer-to-peerconnectionisnotestablishedyet.

Thefollowingscreenshotdepictsthenextstagerightafterestablishingthepeer-to-peerconnection:

Hereyoucanseemorelines;eachofthemrepresentsdatarelatedtosomeobjectorevent.Thefollowingscreenshotshowsanexampleofwhatkindofdatayoucanfindwhileexpandingtheselines:

Page 228: WebRTC Cookbook

YoucanseethatI’veexpandedthesetRemoteDescriptionlistitem,andtherearedetailsthathaveappearedforthisobject:thisisanSDPmessageofthetypeoffer.Youcanalsoseerelevantinformationaboutthecandidates,codecs,andIPaddressesofthisitem.

Inthenextscreenshot,youcanfindevenmoreexamplesofdifferentkindsofitemsthatcanbeaccessibleviathispage:

Page 229: WebRTC Cookbook

Nowherearetheaudioandvideoconnectionobjectsavailableandmanyotherserviceitemsthatarenotobvious.Let’sseewhatisundertheaudioconnectioniteminthefollowingscreenshot:

Page 230: WebRTC Cookbook

HereweexpandedtheConn-audioobjectthatrepresentstheaudioconnection.Youcanseethebytesthatweresentandreceived,IPaddressesofpeers(Iwasrunningthisexampleonmynotebooklocally,sobothIPaddressesareidentical),transportprotocoltype,andotheroptions.

Youwillseethesamekindofinformationwhileexpandingthevideoconnectionitem,soIwillskipthescreenshotforthisone.Insteadofthat,let’sseewhatisonbweforvideo:

Page 231: WebRTC Cookbook

Thisitemrepresentsthebandwidth-relateddetails.Hereyoucanfindthebitrateandbandwidthutilizedbythewebbrowserduringthecommunication.

Inthefollowingscreenshot,youcanfindanotherexamplerelatedtovideodata:

Page 232: WebRTC Cookbook

Whatisgoodwiththistoolisthatitgivesnotonlynumbersandrawdata,butitalsopresentsgreat-lookinggraphics,whereyoucanvisuallyseewhatishappening.Inthefollowingscreenshot,youcanseethegraphsrelatedtoaudioandvideochannelsutilization:

Page 233: WebRTC Cookbook

Nowlet’stakealookatanothergraphicrepresentation—bweforvideo.Itrepresentsvariousnetworkconnectionparametersrelatedtothevideochannel.Ontheleft-handside,youcanfindoptionsthroughwhichyoucanenableordisabletheparametersthatyouwantordon’twanttoseeinthegraphicrepresentation.

Therearemoregraphicrepresentationsavailable—everygraphicrepresentsadynamicalchangeinsomeparameter.

Page 234: WebRTC Cookbook

UsingChromeloggingmechanismThisisnotsomethingspecifictoWebRTC,butcanbehelpfulwhiledevelopinganddebuggingWebRTCapplications.Chromecanbestartedwithenablingtheloggingforcertainmodules.Inthiscase,Chromeduringitsworkwillprintavarietyofusefuldetailsintologfiles.

ThefollowingcommandstartsChromewithenabledlogging:

chrome--enable-logging--v=4--vmodule=*libjingle/source/talk/*=4--

vmodule=*media/audio/*=4

Now,Chromewillputadditionaldetailsintothechrome_debug.logfilethatcanbefoundinChrome’suserdatafolder.Thelogfileisaplaintextfile,soyoucanreaditwithoutusingspecialtools.

TipOnsomesystems,thislogfilemightbedirectlywrittenintotheterminal.

AlthoughweareworkingonthelogfileunderWindows,youcanuseconvenienttoolssuchasSawbuck.Youcanfinditshomepageathttps://code.google.com/p/sawbuck/.

Page 235: WebRTC Cookbook

SawbuckisalogfilesviewerthatcanbeusednotonlyforChromelogs,butalsoforworkingwithlogsofotherapplications(usingplugins).Youcanseewhatthistoollookslikeinthefollowingscreenshot(takenfromthetool’shomepage):

Page 236: WebRTC Cookbook

Howitworks…Welearnedthebuilt-inmechanismavailableinChromethatcanhelpdebuggingandprofilingwhiledevelopingWebRTCapplications.Chromecollectsusefuldata,andusingloggingandthewebrtc-internalstool,youcanaccessthesedata.Moreover,byaccessinggraphs,youcananalyzetheprocessinadynamicmanner.

Tousethistool,youdon’tneedtoinstallanyadditionalsoftware.Thismakesitirreplaceableintheapplicationdevelopmentprocess.

Page 237: WebRTC Cookbook

There’smore…YoucanfindmoredetailsspecifictoChromebyloggingontheappropriatewebpageoftheChromiumprojectathttp://www.chromium.org/for-testers/enable-logging.

Page 238: WebRTC Cookbook

SeealsoForserver-sidedebuggingadvices,pleaserefertotheDebuggingTURNrecipe

Page 239: WebRTC Cookbook
Page 240: WebRTC Cookbook

DebuggingTURNAsyouprobablyknow,yourapplicationwilldefinitelyuseSTUNifyouwantittoworkintherealworld.UsingSTUNwillbeenoughformostcases,althoughyouwillhavetouseTURNinmanysituations—especiallywhenworkingwithenterprisecustomers,becausetheyusuallyhaveverystrictnetworkfirewallpoliciesandcomplexnetworkconfigurations.UsingTURNcanbetheonlyavailablesolutionforcustomerslocatedinsomeplaces,forexample,somecountriesmighthavespecificnetworkaccesslimitationsthatcauseissuesfornetworkapplicationsthatareWebRTC-based.

Sointhisrecipe,wewillcoverhowtodebugTURN.

Page 241: WebRTC Cookbook

GettingreadyForthisrecipe,youneedtohaveyourownTURNserverinstalledandrunning.WhenyouuseaTURNserverasathird-partyservice,youcandebugonlyclientside.However,ifyouuseyourownTURNserver,youhaveaccesstoitandcandomoreinthescopeofdebugging.Sointhisrecipe,wewillconsiderdebuggingaTURNserverthatyouhavedirectaccessto.

Page 242: WebRTC Cookbook

Howtodoit…InChapter3,IntegratingWebRTC,weconsideredtheinstallationandconfigurationofourownTURNserver.TodebugTURN,settheverbosityleveltomaximumandruntheTURNserverinconsole.ThenstartyourWebRTCapplicationusingtheTURNserver—whentheapplicationwillcontacttheserver,youwillseedebugmessagesontheconsoledisplaywheretheserverisrunning.Thefollowingrepresentsthekindsofmessagesyoumightseeintheconsole:

129:session128000000000000001:new,username=<user1:alpha>,lifetime=3600

129:session128000000000000001:user<user1:alpha>:incomingpacket

ALLOCATEprocessed,success

129:handle_udp_packet:NewUDPendpoint:localaddr176.58.121.75:3478,

remoteaddr89.209.127.164:50186

130:session128000000000000007:user<>:incomingpacketBINDING

processed,success

130:session128000000000000009:user<>:incomingpacketmessage

processed,error401

131:session128000000000000009:new,username=<user2:beta>,lifetime=600

131:session128000000000000009:user<user2:beta>:incomingpacket

ALLOCATEprocessed,success

131:handle_udp_packet:NewUDPendpoint:localaddr176.58.121.75:3478,

remoteaddr89.209.127.164:52914

131:session128000000000000010:user<>:incomingpacketmessage

processed,error401

Inthisdump,youwillseeafragmentofTURNauthenticationstagewheretwoclientsaretryingtogetauthenticated.Session129representstheclientuser1withthealphapassword,andsession131representsthecustomeruser2withthebetapassword.Youcanalsoseesession130,whichrepresentsaSTUNclient—itdoesn’tuseTURNfunctionality,soyoudon’tseeanyusernamesorpasswordsfromthisclient.

Nowifyou’veconfiguredtheTURNserverwithdefaultconsoleoptions,youcanconnecttotheTURNconsoleandgetmorespecificdetailsonthecertainsession.ConnecttotheTURNconsole:

telnetlocalhost5766

Afteryou’veconnected,itwillshowyousomethinglikethefollowing:

Connectedtolocalhost.

Escapecharacteris'^]'.

TURNServer

rfc5766-turn-server

Citrix-3.2.2.910'MarshalWest'

Type'?'forhelp

Intheconsoleyouhaveasetofcommands—using?orhelpyoucanaskthesystemtoshowthewholelistofavailablecommandsandoptions.Thecommandwe’reinterestedinisps—itshowsdetailedinformationabouttheavailableTURN/STUNsessions.

>ps

Page 243: WebRTC Cookbook

7)id=128000000000000004,user<user1:alpha>:

started78secsago

expiringin3522secs

clientprotocolUDP,relayprotocolUDP

clientaddrx.x.x.x:58454,serveraddry.y.y.y:3478

relayaddrx.x.x.x:63599

fingerprintsenforced:ON

mobile:OFF

SHA256:OFF

SHAtype:SHA1

usage:rp=2,rb=172,sp=1,sb=120

rate:r=0,s=0,total=0(bytespersec)

8)id=128000000000000010,user<user2:beta>:

started76secsago

expiringin524secs

clientprotocolUDP,relayprotocolUDP

clientaddrx.x.x.x:52914,serveraddry.y.y.y:3478

relayaddrx.x.x.x:50796

fingerprintsenforced:OFF

mobile:OFF

SHA256:OFF

SHAtype:SHA1

usage:rp=2,rb=140,sp=1,sb=120

rate:r=0,s=0,total=0(bytespersec)

Totalsessions:8

Fromthislistingwecanseethatintotalthereareeightsessionsontheserver.Inthisprecedingfragment,weseedetailsoncertaintwosessions.Weknowtheusernames(user1anduser2),passwords,IPaddresses,timeofexpiration,timeofliving,andsomemoredetailsofeachsession.

UsingtheTURNconsole,youcancheckwhethersomeproblematicclienthasconnectedtotheserversuccessfullyorhasanyissues.Youcancheckwhichusernamesorpasswordshavebeenusedforeachsession.Youcanalsoknowabouttheusedprotocolsandencryptiondetails.AnalyzingsuchkindsofinformationcanhelpintroubleshootingtheTURN/STUNcommunicationprocess.

Page 244: WebRTC Cookbook

Howitworks…HavingdirectaccesstotheTURNserver,youcanuseitsconsoletogetmorecertaindataandanalyzewhat’sgoingon.Usingsuchamethod,youcandebugyourapplicationthatisusingTURN.

Page 245: WebRTC Cookbook

There’smore…Inthisrecipe,weconsideredacertainwaytoimplementaTURNserver,usingrfc5766-turn-serversoftware.Ifyouusesomeothersoftware,itmightbesuppliedwithsomeotherspecifictoolsfordebugginganddiagnostic.

Page 246: WebRTC Cookbook

SeealsoWhenyouhavenodirectaccesstotheTURNserver,youcanuseanetworksniffertocapturenetworkpacketsandanalyzethesituationfromthatside.Tolearnthistechnique,pleaserefertotheDebuggingusingWiresharkrecipe.ToconfigureandinstallaTURNserver,refertoChapter3,IntegratingWebRTC.

Page 247: WebRTC Cookbook
Page 248: WebRTC Cookbook

DebuggingusingWiresharkWebRTCapplicationsusenetworksveryintensively.Thussometimesyoumightneedtodebugnotjusttheapplication,butalsoitscommunicationwithothercomponentsofthewholesystem.

Inthissection,wewillcovertheprocessofdebuggingWebRTCapplicationsusingnetworksniffer.

Networksnifferisatoolforcapturingnetworkpackets.Usually,suchtoolscanhelpyoutoanalyzecaptureddata.Usingsniffer,youcanseeandunderstandhowyourapplicationcommunicateswithotherpoints.

Page 249: WebRTC Cookbook

GettingreadyForourrecipe,wewilluseWireshark—whichisafreeandmultiplatformnetworksniffersoftware.Downloaditfromthehomepageathttp://www.wireshark.org.

Thistoolisveryuser-friendlyandworksonmostpopularplatforms,soyoudon’tneedanyspecificpreparations.

YouwillalsoneedsomeWebRTCapplication;youcanuseanysimplehelloworldapplicationforthispurpose.

Page 250: WebRTC Cookbook

Howtodoit…StartWireshark.YouwillseeaUIthatmightlookconfusingatthefirsttime.Thistoolisverypowerfulandhasmanyfeatures,butforthistask,wewillusebasicfunctionality.PerformthefollowingstepstouseWireshark:

1. ClickontheCapturebutton—Wiresharkwillbegincapturingdatanetworkframes.2. StartyourWebRTCapplicationandnavigateChromebrowsertotheapplication’s

mainwebpage.3. Navigatetotheapplication’swebpageusinganotherbrowserandmakeacalltothe

firstpeer.4. WaituntiltheWebRTCsessionbeginsandclickontheStopbuttoninthe

Wireshark’sUI.

Nowlet’sseewhatwecangetfromthecollecteddata.Inthefollowingscreenshots,youcanseetheexamplesfrommymachine.

Inthefirstscreenshot,youcanseeasetofnetworkpacketsthataresentbetweenpeers(mynotebookandanotherworkmachine).TheselectedlinepointstoaSTUNbindingsuccessresponsewithfollowingdecodedfields:

Afterthat,peerstrytoestablishsecuredirectconnection,andyoucanseethisstageinthefollowingscreenshot:

Page 251: WebRTC Cookbook

Anotherexampleofcommunicationthroughsecuredchannelisdepictedinthefollowingscreenshot.Hereyoucanseetheapplication’sdataexchangingstage.

ThefollowingscreenshotdepictstheTURNauthenticationstage.Youcanseethattheserverrepliedwith401unauthorizedrequest;thisisnormalstepatthisstageanditjustmeansthattheserverwillnotserveforanonymousclient.Aftergettingthisserver’s

Page 252: WebRTC Cookbook

response,theclientwillcontinuethecommunicationprocessandwillsendcredentialstotheserver.

Usinganetworksniffer,suchasWireshark,canbeveryusefulandhelpfulinthedebuggingprocess.Youneedtocapturenetworkpacketsduringacertainstageoftheapplication’scommunication,andafterthat,youcananalyzethecommunicationprocesstounderstandwhat’swrong.

Page 253: WebRTC Cookbook

Howitworks…Anetworksnifferallowsyoutocapturenecessarynetworkpacketsthatarebeingsentbetweenpeersandservers.Byanalyzingthesepackets,wecanunderstandwhat’sgoingoninthecommunicationchannelsandfixtheissues.

Page 254: WebRTC Cookbook

There’smore…Thereareothernetwork-relatedtoolsthatmightbehelpfulforsuchkindoftask:

tcpdump:ThisisaconsolenetworksnifferstandardforUNIX-likesystemsmtr:Thisisanetworktoolthatcanbeusefulwhenyouneedtoanalyzeanetworkpathofthedatathatissentbetweenpeers

Page 255: WebRTC Cookbook

SeealsoWhendebuggingnetwork-relatedissues,usingthewebrtc-internalsmechanismmightalsobeuseful.RefertotheDebuggingwithChromerecipeforthedetails.RegardingtheprocessofdebuggingTURNservers,youcanrefertotheDebuggingTURNrecipe.

Page 256: WebRTC Cookbook
Page 257: WebRTC Cookbook

Chapter5.WorkingwithFiltersInthischapter,wewillcoverthefollowingtopics:

WorkingwithcolorsandgrayscaleWorkingwithbrightnessWorkingwithcontrastWorkingwithsaturationWorkingwithhueUsingthesepiafilterUsingtheopacityfilterInvertingcolorsImplementingtheblureffectImplementingthedroppedshadoweffectCombiningfiltersCustomvideoprocessing

Page 258: WebRTC Cookbook

IntroductionWiththeintroductionoftheHTML5standard,wehavegotnewpowerfulfeatures.OneoftheinterestingonesisaCSSfilter.Usingthisfeature,youcancontrolavarietyofanimage’sproperties.Youcanprocessastaticimageorvideoimageonthefly.

InthescopeofWebRTC,usageoffiltersenablesyoutoimplementnewfeaturesinyourapplication;itcancontrolvideoimages,makeitbrighterorlesscontrast,andapplysomespecifickindsoffilters.

Inthissection,wewillcoverusingofimageprocessing,implementingseveralpracticalsolutionsandutilizingvideofilters.Youwillseebeforeandaftercasespresentedinthescreenshots.

TipThisfeatureisnotsupportedbyallwebbrowsers—useChromebrowserwhiletestingtheprovidedexamples.

TheworkonHTML5andWebRTCstandardsisnotfinishedyet,sothereisachancethatcertainplacesinthecodemightneedtobechangedinfuture.Notethatthesefilterscanonlybeappliedlocally.Thismeansthatduringavideoconference,ifyouapplyafiltertothevideofromyourwebcamera,youwillseethechangeslocallyinyourbrowser—butyourpeerwon’tseethesechanges.Itwillseetheoriginalvideotranslatedfromyourwebcamera.Ontheotherside,youcanapplythesefilterstotheremotevideoofyourpeerthatisshowninyourwebbrowser.

Youcanfindthesourcecodesofthedemoapplicationsuppliedwiththisbook.

Page 259: WebRTC Cookbook
Page 260: WebRTC Cookbook

WorkingwithcolorsandgrayscaleThisrecipeshowshowtoworkwithafilterthatdealswiththecolorsoftheprocessedvideo.Wewillmakeavideolesscolorizedandthenmakeitblackandwhite.Thisrecipecanbeusedasakindofsimplespecialeffectforavideo.

Page 261: WebRTC Cookbook

Howtodoit…Performthefollowingsteps:

1. Addthecontrolbuttontothemainwebpageofyourapplication:

<buttononclick="doGrayScale()">dograyscale</button>

2. AddanappropriateJavaScriptfunction:

functiondoGrayScale(){

varv=document.getElementById("localVideo");

v.style.webkitFilter="grayscale(50%)";

};

Here,localVideoistheIDpropertyoftheHTMLvideotagforthelocalvideoplayback.

3. Navigateyourbrowsertothewebpage.Youwillfirstseeanunprocessedvideofromthewebcamera.Thefollowingscreenshotdepictssuchasituation:

4. Nowclickonthedograyscalebutton—youwillseethattheimagehasbecomelesscolorized,asshowninthefollowingscreenshot:

Page 262: WebRTC Cookbook

Thishappenedbecauseweappliedthegrayscalefilterwithavalueof50%.Inotherwords,weremoved50percentofcolorsfromthevideo.

5. Noweditthecodeandput100%intothefilter’svalue,reloadthewebpage,andclickonthedograyscalebuttonagain—youwillseethatvideobecomesblackandwhite.

Page 263: WebRTC Cookbook

Howitworks…Whenyouclickonthedograyscalebutton,theJavaScriptfunctionfromthesecondstepoftheHowtodoit…sectioniscalled.Thisfunctionappliesthegrayscalefilterwiththeappropriatevaluetothevideoobject—usingitsstyleHTMLproperty.Fromnowon,thewebbrowserwillshowthisvideoapplyingthefilteronthefly.

Page 264: WebRTC Cookbook
Page 265: WebRTC Cookbook

WorkingwithbrightnessThisrecipeshowshowtochangethebrightnessofavideousingtheHTML5filter.Ifyoudevelopavideoapplication,it’susuallyagoodideatogivesomecontrolonthevideotocustomers,allowingthemtochangethecontrast,brightness,andotherparametersofthevideo.

Page 266: WebRTC Cookbook

Howtodoit…Followthegivensteps:

1. Addthefollowingcontrolelementtothemainwebpageofyourapplication—usingthisobjectwewillchangethebrightness:

Brightness

<inputtype="range"oninput="changeBrightness(this.valueAsNumber);"

value="0"step="0.1"min="0"max="10">

2. AddtheappropriateJavaScriptfunction:

functionchangeBrightness(val){

varv=document.getElementById("localVideo");

v.style.webkitFilter="brightness("+val+")";

};

3. Here,localVideoistheIDpropertyoftheHTMLvideotagforthelocalvideoplayback.Navigateyourwebbrowsertothewebpage.Youwillfirstseeanunprocessedvideofromthewebcamera.Thefollowingscreenshotdepictssuchasituation:

4. Ontheleft-handsideofthepage,youcanseeacontroldescribedasBrightness.Trytomoveitalittletotheright—youwillseethatthevideoisbecomingbrighter.InthefollowingscreenshotImovedthecontroltoomuchtotherightandtheimagebecametoobright:

Page 267: WebRTC Cookbook

5. Ifyoumoveittoomuchtotheleft,youwilljustseeablackbox.

Page 268: WebRTC Cookbook

Howitworks…Whenyoumovethecontrol,theJavaScriptfunctionfromthesecondstepiscalled.Thisfunctionappliesthebrightnessfilterwiththecontrol’svaluetothevideoobject—usingitsstyleHTMLproperty.Fromnowon,thewebbrowserwillshowthisvideoapplyingthefilteronthefly.

Page 269: WebRTC Cookbook
Page 270: WebRTC Cookbook

WorkingwithcontrastThisrecipeshowshowtocontrolthecontrastfeatureofavideousingtheHTML5filterfeature.Thisisthesecondmostimportantcontrolthatcustomersusuallywanttohavewhenusingvideoapplications.

Page 271: WebRTC Cookbook

Howtodoit…Followthegivensteps:

1. Addacontrolelementtothemainwebpageofyourapplication—usingthisobjectwewillchangethecontrast:

Contrast

<inputtype="range"oninput="changeContrast(this.valueAsNumber);"

value="0"step="0.1"min="0"max="10">

2. AddanappropriateJavaScriptfunction:

functionchangeContrast(val){

varv=document.getElementById("localVideo");

v.style.webkitFilter="contrast("+val+")";

};

Here,localVideoistheIDpropertyoftheHTMLvideotagforthelocalvideoplayback.

3. Navigateyourwebbrowsertothewebpage.Youwillfirstseeanunprocessedvideofromthewebcamera.Thefollowingscreenshotdepictssuchasituation:

4. Ontheleft-handsideofthepage,youcanseeacontroldescribedasContrast.Trytomoveittotherightorleft—youwillseethatthevideohasmoreandlesscontrastrespectively.InthefollowingscreenshotImovedthecontroltotherightandincreasedthecontrast:

Page 272: WebRTC Cookbook

Ifyoumoveittoomuchtotheleft,youwillseejustalight-graybox.Ifyoumovethecontroltotheright,youwillmaketheimagealmostblack(dependsontheamountoflightatyourplace).

Page 273: WebRTC Cookbook

Howitworks…Whenyoumovethecontrol,theJavaScriptfunctionfromthesecondstepiscalled.Thisfunctionappliesthecontrastfilterwiththecontrol’svaluetothevideoobject—usingitsstyleHTMLproperty.Fromnowon,thewebbrowserwillshowthisvideoapplyingthefilteronthefly.

Page 274: WebRTC Cookbook
Page 275: WebRTC Cookbook

WorkingwithsaturationInthisrecipe,wewillcovertheprocessofcontrollingthesaturationofavideobeingcapturedfromthewebcamerausingWebRTC.Saturationisrarelyusedasacontrolavailabletousers.Althoughforsomekindsofapplicationsitmightbeveryuseful.

Page 276: WebRTC Cookbook

Howtodoit…Performthefollowingsteps:

1. Addacontrolelementtoyouapplication’smainwebpage—usingthisobjectwewillchangethesaturation’slevel:

Saturation

<inputtype="range"oninput="changeSaturation(this.valueAsNumber);"

value="0"step="0.1"min="0"max="10">

2. AddanappropriateJavaScriptfunction:

functionchangeSaturation(val){

varv=document.getElementById("localVideo");

v.style.webkitFilter="saturate("+val+")";

};

HerelocalVideoistheIDpropertyoftheHTMLvideotagforthelocalvideoplayback.

3. Navigateyourwebbrowsertothewebpage.Youwillfirstseeanunprocessedvideofromthewebcamerawithnormalsaturation.Thefollowingscreenshotdepictssuchasituation:

4. Ontheleft-handsideofthepage,youcanseeacontroldescribedasSaturation.Trytomoveittotheextremeleft—youwillseethatthevideobecameblackandwhite.Bysmoothlymovingthecontroltotheright,youwilladdsaturation,andthevideowilllookmorenormal.Inthefollowingscreenshot,Imovedthecontroltoomuchto

Page 277: WebRTC Cookbook

theright,makingthevideotoosaturated:

Movingthecontroltotherightboundwillmakethevideooversaturated,anditwillbebarelypossibleforustoseewhat’shappeninginthescene.

Page 278: WebRTC Cookbook

Howitworks…Whenyoumovethecontrol,theJavaScriptfunctionfromthesecondstepiscalled.Thisfunctionappliesthesaturatefilterusingthecontrol’svalueasthefilter’sparameter.Thefunctionusestheobject’sstyleHTMLproperty.Fromnowon,thewebbrowserwillshowthevideoapplyingthechosenfiltertoitonthefly.

Page 279: WebRTC Cookbook
Page 280: WebRTC Cookbook

WorkingwithhueInthisrecipe,wewilllearnhowtocontrolthevideo’shue.Usually,youwillnotusethisfilterinyourapplications,although,sometimesitmightbehelpful;forexamplewhenyou’reusingsomekindofspecificvideoequipmentthatmightneedthiswayofprocessingvideo.

Page 281: WebRTC Cookbook

Howtodoit…Followthegivensteps:

1. Addacontrolelementtotheapplication’smainwebpage—usingthisobjectwewillchangethevideo’shue:

Hue

<inputtype="range"oninput="changeHue(this.valueAsNumber);"value="0"

step="20"min="0"max="360">

Here,youcanseethatwehavesetthemaxvalueas360—thisisbecausethehue’svalueistiedtodegrees.Inthisuniverse,wehave360degrees,sothemaximumvalueforthisfilterissetto360.

2. AddanappropriateJavaScriptfunction:

functionchangeHue(val){

varv=document.getElementById("localVideo");

v.style.webkitFilter="hue-rotate("+val+"deg)";

};

Wehavealsoaddedthedegpostfixtothefilter’svalue—itmeansdegree.Here,localVideoistheIDpropertyoftheHTMLvideotagforthelocalvideoplayback.

3. Navigateyourwebbrowsertothewebpage.Youwillfirstseeanunprocessedvideofromthewebcamera,withnofilterapplied.Thefollowingscreenshotdepictsthisstage:

Page 282: WebRTC Cookbook

4. Ontheleft-handsideofthepage,youcanseeacontroldescribedasHue.Trytomoveittotheleftandright—youwillseethatthevideo’scolorschange.Thisisbecausebymovingthecontrol,youchangetheimage’shue.InthefollowingscreenshotImovedthecontroltotheright,makingtheperson’sfacedarkpink,andtheyellow-blueflagbecamewhite-green:

Youprobablywillusethisfilterrarely.Itcanbeusefulifincaseforsomereasonyouhaveabrokenvideo(fromyourwebcameraorfromthepeer)withabnormalhues.Otherwise,itcanbeappliedjustforfun.

Page 283: WebRTC Cookbook

Howitworks…Whenyoumovethecontrol,theJavaScriptfunctionfromthesecondstepiscalled.Thisfunctionappliesthehue-rotatefilterusingthecontrol’svalueasthefilter’sdegree.Thefunctionusestheobject’sstyleHTMLproperty.Fromnowon,thewebbrowserwillshowthevideoapplyingthechosenfiltertoitonthefly.

Page 284: WebRTC Cookbook
Page 285: WebRTC Cookbook

UsingthesepiafilterThisrecipecoverstheusageofthesepiafiltertoprocessavideocapturedfromaremotepeerorlocalwebcamerausingWebRTC.Thisisapopularfilteroftenusedasaspecialeffectformakingvideoapplicationsmorefriendlyandwarm.

Page 286: WebRTC Cookbook

Howtodoit…Thefollowingstepswillshowyouhowtousethesepiafilter:

1. Addacontrolelementtothemainwebpageoftheapplicationyou’redeveloping—usingthisobjectwewillcontrolthevalueoftheappliedSepiafilter:

Sepia

<inputtype="range"oninput="changeSepia(this.valueAsNumber);"

value="0"step="0.1"min="0"max="1">

2. AddanappropriateJavaScriptfunction:

functionchangeSepia(val){

varv=document.getElementById("localVideo");

v.style.webkitFilter="sepia("+val+")";

};

Here,localVideoistheIDpropertyoftheHTMLvideotagforthelocalvideoplayback.

3. Navigateyourwebbrowsertothewebpage.Youwillfirstseearawvideointhewebcamera,withnofilterapplied.Inthefollowingscreenshot,youcanseeanimagewithoutanyappliedfilter:

4. Ontheleft-handsideofthepage,youcanseeacontroldescribedasSepia.Trytomoveittotheleftandright—youwillseethatthevideo’scolorschange.Theleftmostpositionmakestheimagelooknormal(nofilterisapplied).Therightmostpositionappliesthefiltertothemostavailablevalue.Inthefollowingscreenshot,I

Page 287: WebRTC Cookbook

movedthecontroltotherightmostendandmadethevideolookasifitwastakenfromanoldmovie:

Page 288: WebRTC Cookbook

Howitworks…Whenyoumovethecontrol,theJavaScriptfunctionfromthesecondstepiscalled.Thisfunctionappliesthesepiafiltertothevideoimage.Thefunctionusestheobject’sstyleHTMLproperty.Fromnowon,thewebbrowserwillshowthevideoapplyingthechosenfiltertoitonthefly.

Page 289: WebRTC Cookbook
Page 290: WebRTC Cookbook

UsingtheopacityfilterInthisrecipe,wewillcoverhowtousetheopacityfilter.Youwillprobablyrarelyuseit,butitcanbeusedforimplementinginterestingfeatures,suchaspictureinpicture.

Page 291: WebRTC Cookbook

Howtodoit…Followthesesteps:

1. Addacontrolelementtothemainwebpageofyourapplication—usingthisobjectwewillcontrolthevideo’sopacity:

Opacity

<inputtype="range"oninput="changeOpacity(this.valueAsNumber);"

value="1"step="0.1"min="0"max="1">

2. AddanappropriateJavaScriptfunction:

functionchangeOpacity(val){

varv=document.getElementById("localVideo");

v.style.webkitFilter="opacity("+val+")";

};

HerelocalVideoistheIDpropertyoftheHTMLvideotagforthelocalvideoplayback.

3. Navigateyourwebbrowsertothewebpage.Youwillfirstseeanunprocessedvideofromthewebcamera,withnofilterapplied.Thefollowingscreenshotdepictsthisstage:

4. Ontheleft-handsideofthepage,youcanseeacontroldescribedasOpacity.Trytomoveittotheleftandright—youwillseethatthevideobecomeslessandmoretransparent,respectively.Thetop-rightpositionisthenormalstate,andthetop-leftpositionisthetransparentstate.InthefollowingscreenshotImovedthecontrola

Page 292: WebRTC Cookbook

littletotheleft,andyoucanseethatthepersonintheimageisbarelyvisiblebecauseoftheimage’stransparency:

Thisfiltercanalsobeusefulwhenyouoverlapseveralvideos.Anotherutilityofthisfilteristhat,incaseyou’redevelopingamultiuserconference,byusingthisfilterandchangingausers’videotransparency,youcanmarktheparticipantsascurrentlyspeakingoronholdaccordingly.

Page 293: WebRTC Cookbook

Howitworks…Whenyoumovethecontrol,theJavaScriptfunctionfromthesecondstepiscalled.Thisfunctionappliestheopacityfiltertothevideousingthecontrol’svalue.Thefunctionusestheobject’sstyleHTMLproperty.Fromnowon,thewebbrowserwillshowthevideoapplyingthechosenfiltertoitonthefly.

Page 294: WebRTC Cookbook
Page 295: WebRTC Cookbook

InvertingcolorsThisrecipecoverstheprocessofusingaprettysimplefilter:inversionofcolors.Itwillhardlybeusefulforyouinmostnormalcases,butitmightbehelpfulifforsomereasonyourpeersendsyouabrokenvideowithinvertedcolors,oryougetonefromyourwebcamera.Somecamerasmightworkthatwayduetohardwareincompatibilityorduetotheincorrectinstallationofsoftwaredrivers.

Page 296: WebRTC Cookbook

Howtodoit…Performthefollowingsteps:

1. Addacontrolbuttontoyourapplication’smainwebpage:

Inversion

<inputtype="range"oninput="invertColors(this.valueAsNumber);"

value="0"step="0.1"min="0"max="1">

2. AddanappropriateJavaScriptfunction:

functioninvertColors(val){

varv=document.getElementById("localVideo");

v.style.webkitFilter="invert("+val+")";

};

HerelocalVideoistheIDpropertyoftheHTMLvideotagforthelocalvideoplayback.

3. Navigateyourbrowsertothewebpage.Youwillfirstseeanunprocessedvideofromthewebcamera.Thefollowingscreenshotdepictsthisstage:

4. OnthetopleftofthewebpageyoucanseetheInversioncontrol.Trytomoveittotheleftandright—youwillseethatthevideoimage’scolorschangeasandwhenyoumovethecontroltotheleftandright.InthefollowingscreenshotImovedthecontrolalmosttotherightmostposition,andtheimagetransformedtocolornegativeoftheoriginalimage:

Page 297: WebRTC Cookbook
Page 298: WebRTC Cookbook

Howitworks…WhenyouclickontheInversionbutton,theJavaScriptfunctionfromthesecondstepiscalled.Thisfunctionappliestheinvertfilterwiththeappropriatevaluetothevideoobject—usingitsstyleHTMLproperty.Fromnowon,thewebbrowserwillshowthisvideoapplyingthefilteronline.

Page 299: WebRTC Cookbook
Page 300: WebRTC Cookbook

ImplementingtheblureffectThisrecipedivesintotheimplementationoftheblureffect.Ifyouhaveworkedongraphiceditingcomputersoftware,thenyouarelikelyfamiliarwiththiseffect.

Page 301: WebRTC Cookbook

Howtodoit…Thefollowingstepswillhelpyouunderstandhowtoimplementtheblureffect:

1. Addacontrolelementtotheindexwebpageofyourapplication—usingthisobjectwewillcontroltheblureffect:

Blur

<inputtype="range"oninput="doBlur(this.valueAsNumber);"value="0"

step="1"min="0"max="15">

2. AddanappropriateJavaScriptfunction:

functiondoBlur(val){

varv=document.getElementById("localVideo");

v.style.webkitFilter="blur("+val+"px)";

};

Wehaveaddedapxpostfixforthefilter’svalue—thisisbecauseoftheblur’sintensitythatissettinginpixels.Here,localVideoistheIDpropertyoftheHTMLvideotagforthelocalvideoplayback.

3. Navigateyourwebbrowsertothewebpage.Youwillfirstseetheraw,unprocessedvideofromthewebcamera,withnofilterapplied.Thefollowingscreenshotdepictsthisstage:

4. Intheprecedingscreenshot,ontheleft-handsideofthepage,youcanseeaBlurcontrol.Bymovingthiscontroltotheleftandright,youcansettheintensityoftheblurrinessinanimage.Theleftmostpositionmeansthatthereisnoblurandyou

Page 302: WebRTC Cookbook

shouldseeanormalimage.InthefollowingscreenshotImovedthecontrolalittletotherightfromthemiddle,andyoucanseethattheimagebecameveryblurry—itisbarelypossibletorecognizethepersoninthevideo:

Thisfiltercanbeusedforindicatingthatyouhavemutedsomeoneonthevideoconference,orforindicatingthattheconferencehasnotstarted.

Page 303: WebRTC Cookbook

Howitworks…Whenyoumovethecontrol,theJavaScriptfunctionfromthesecondstepiscalled.Thisfunctionappliestheblurfiltertothevideousingthecontrol’svalue.Thefunctionusestheobject’sstyleHTMLproperty.Fromnowon,thewebbrowserwillshowthevideoapplyingthechosenfilteronthefly.

Page 304: WebRTC Cookbook
Page 305: WebRTC Cookbook

ImplementingthedroppedshadoweffectInthisrecipe,wewillcovertheprocessofimplementingthedroppedshadoweffect.Thisfiltercanbeusedfordecorationpurposes.AlthoughitutilizesCPUresourcesveryactively,don’tputitoneverypage.

Page 306: WebRTC Cookbook

Howtodoit…Followthesesteps:

1. Addacontrolelementtotheappropriatewebpageoftheapplication—usingthisobjectwewillcontrolintensityoftheeffect:

Shadow

<inputtype="range"oninput="doShadow(this.valueAsNumber);"value="0"

step="5"min="0"max="50">

2. AddtheonLoadhandlertoHTML’sbodytagofthewebpage.Byusingthismethod,wewillinitializethedroppedshadoweffect.

<bodyonload="doShadow(0);">

3. AddanappropriateJavaScriptfunction:

functiondoShadow(val){

varv=document.getElementById("localVideo");

v.style.webkitFilter="drop-shadow("+val+"px"+val+"px10px

green)";

};

Wehaveaddedthepxpostfixforthefilter’svalue—thisisbecauseoftheeffect’sintensityissettinginpixels.Also,youcanseethatwehavesettheshadow’swidthto10pixels,andwewanttheshadowtobegreen.

Here,localVideoistheIDpropertyoftheHTMLvideotagforthelocalvideoplayback.

4. Navigateyourwebbrowsertothewebpage.Youshouldseeanormalimagefromyourwebcamera,butthereshouldbeagreenshadowaroundtheimage.Thefollowingscreenshotdepictsthisstage:

Page 307: WebRTC Cookbook

5. Ontheleft-handsideofthepageyoucanseetheShadowcontrol.Bymovingthiscontroltotheleftandright,youcancontroltheshadow’sposition.Theleftmostpositionofthecontrolistheinitialpositionoftheshadow—justaroundtheimagewithawidthof10pixels,aswehavesetit.InthefollowingscreenshotImovedthecontrolalittletotherightfromthemiddle,andyoucanseethatthegreenshadowhasalsomovedtothebottomandright:

Page 308: WebRTC Cookbook

ThisfiltercanbeusedforadditionalUIdecorationwhiledevelopingWebRTCapplications.Youcaneasilycontroltheshadow’ssize,position,andcolor.

Page 309: WebRTC Cookbook

Howitworks…Whenyoumovethecontrol,theJavaScriptfunctionfromthesecondstepiscalled.Thisfunctionappliesthedrop-shadowfiltertothevideousingthecontrol’svalue.Thefunctionusestheobject’sstyleHTMLproperty.Fromnowon,thewebbrowserwillshowthevideoapplyingthechosenfilteronthefly.

Page 310: WebRTC Cookbook
Page 311: WebRTC Cookbook

CombiningfiltersAllthefiltersdescribedinthischaptercanbecombinedandworktogether.Inthisrecipe,wewillcoverthistopicusingasimplepracticalexample—combiningtwofilters:brightnessandcontrast.

Page 312: WebRTC Cookbook

Howtodoit…Followthegivensteps:

1. Addtwocontrolobjectstothepageforeachofthefiltersweplantouse:

Brightness<br>

<inputtype="range"oninput="doFilter('brightness',

this.valueAsNumber);"value="0"step="0.1"min="0"max="10">

<br>

Contrast<br>

<inputtype="range"oninput="doFilter('contrast',this.valueAsNumber);"

value="0"step="0.1"min="0"max="10">

<br>

2. Addaglobalvariablewherewewillstorethevaluesforeachfilter:

varfilters={};

3. AddanappropriateJavaScriptfunctionthatwillbecalledwhenvalueofthecontrols(introducedinthestep1)ischanging:

functiondoFilter(filtername,val){

filters[filtername]=val;

varv=document.getElementById("localVideo");

varf="";

for(varfnameinfilters){

f=""+fname+"("+filters[fname]+")"+f;}

v.style.webkitFilter=f;

};

4. Navigateyourwebbrowsertothewebpage.Youshouldseetheusualimagefromyourwebcameraandtwocontrols:forbrightnessandcontrast.Bymovingthesecontrols,youcanchangethevalueoftheimage’scontrastandbrightness.Changingthevalueofonefilterdoesn’tresetthevalueofanother.Inthefollowingscreenshot,youcanseesuchawebpagewiththedescribedfeature:

Page 313: WebRTC Cookbook
Page 314: WebRTC Cookbook

Howitworks…InthedoFilterfunction,wegetthenameofacertainfilterasthefilternameparameter.Certainfilternameswegettherefromtheappropriatefilter’scontrol(refertothefirststep).Asthesecondparameterofthefunction,wealsogetcertainfiltervalueswehavetouseapplyingthefilter.

Aftergettingthefilternameandfiltervalueinthefunction,wewillstoretheseparameters(refertothesecondstep)inthefiltersarrayvariable(wewilluseitasanassociativearray).Thenwewillgothroughallthearraykeysandvalues(filternamesandtheirvalues)andwillconstructthestringf,combiningnecessaryfilternamesanditsvalues.Wewilldelimitfiltersbythespacesymbol.

Afterthat,wewillgetthefstringassomethinglikethefollowing:brightness(3)contrast(5)

Wewillusetheconstructedstringtochangethestyleoftheappropriatevideotag.Asaresult,wewillapplytwofiltersinparallel.

Youcancombineasmanyfiltersasyoulike,butyoushouldknowthatsomeofthemcouldberesourcehungry.Ifyourapplicationsetstoomanyfiltersatonetime,itmightcauseissues(thewebbrowsermightstack,forexample).

Page 315: WebRTC Cookbook
Page 316: WebRTC Cookbook

CustomvideoprocessingUntilnow,weconsideredstandardfiltersonly.Inthisrecipe,wewillcoverthebasiccaseofcustomvideoprocessing.Usingthatapproach,youcanimplementyourownfiltersandprocessingalgorithms.

Page 317: WebRTC Cookbook

Howtodoit…Asanexample,wewillimplementthepixelizationeffect.

1. Putacanvasobjectsomewhereontheapplication’swebpage.Thiscanvaswillbeusedforgettingframesfromthevideo.Thevisibilityoptionissettohidden—wedon’twanttoshowthiscanvastotheuser,wewilluseitforourinternal,technicalpurposesonly.

<canvasid="canva"width="384px"height="288px"

style="visibility:hidden;"></canvas>

2. Putanothercanvasobjectonthewebpage.Thiscanvaswillbeusedtoshowtheresultofthevideoprocessing:

<canvasid="fcanva"width="384px"height="288px"></canvas>

3. Addabutton,whichwillenabletheprocessing:

<buttononclick="pixelize(10)">Pixelize</button><br>

4. Implementthepixelizefunction.Thisfunctionactuallyperformsallthevideoprocessing:

varpixelsize=10;

varw=384;

varh=288;

functionpixelize(pixelsize){

cnv.drawImage(lv,0,0,w,h);

for(varx=1;x<w;x+=pixelsize)

{

for(vary=1;y<h;y+=pixelsize)

{

varpxl=cnv.getImageData(x,y,1,1);

fcnv.fillStyle=

"rgb("+pxl.data[0]+","+pxl.data[1]+","+pxl.data[2]+")";

fcnv.fillRect(x,y,x+pixelsize-1,y+pixelsize-1);

}

}

setTimeout(function(){

pixelize(pixelsize);

},0);

}

5. Inthefollowingscreenshot,youcanseehowthefilterworks.Ontheleft-handside,theoriginalvideoisshown,ontheright-handside,youcanseethesamevideoafterapplyingthecustomfilter:

Page 318: WebRTC Cookbook
Page 319: WebRTC Cookbook

Howitworks…Weusedtwocanvases:one(whichishidden)wasusedtocopyframesfromthevideostreamandgetpixels;thesecondcanvaswasusedtoshowprocessedvideoframes.

Whenthepixelizefunctioniscalledthefirsttime,itcompletesprocessingofthefirstvideoframeandthensetsupatimertobecalledthenexttime.Thus,thebrowsercallsthisfunctionagainandagain.Witheverycall,itgetsanewvideoframe,processesit,andgetsdisplayedusingthesecondcanvasobject.

Thatway,youcanimplementanyvideoframeprocessingalgorithmanduseitasyourcustomvideofilter.

Page 320: WebRTC Cookbook
Page 321: WebRTC Cookbook

Chapter6.NativeApplicationsInthischapter,wewillcoverthefollowingtopics:

BuildingacustomizedWebRTCdemoforiOSCompilingandrunninganoriginaldemoforiOSCompilingandrunningademoforAndroidBuildinganOpenWebRTClibrary

Page 322: WebRTC Cookbook

IntroductionThischapterisfullydedicatedtousingWebRTCtechnologywhiledevelopingnativeapplicationsformobileplatforms.Here,thetermnativeapplicationreferstothekindofsoftwarethatisbeingdevelopedusingnativetoolsandSDKofacertainmobileplatform.

Firstofall,youwilllearnhowtogetandcompileWebRTClibrariesthatcanbeusedfordevelopingnativeapplications.Thereisnoseparatecodeforeverycertainplatform.Basically,thecodebaseisthesameforallavailablemobileplatforms.

Inotherrecipes,wewillbuildandrunWebRTCdemoapplicationsforAndroidandiOS,todemonstratetheuseofWebRTConmobiledevices.

TheBuildingacustomizedWebRTCdemoforiOSrecipecoverscustomizeddemoapplications.TheproblemisthattheWebRTCcodebaseisunderactivedevelopment,andoriginalexampleapplicationsmightnotdemonstrateallavailablefeaturesofthetechnology.Forexample,theoriginaliOSexampledidn’tsupportvideocallsforalongtimeandsupportedaudiocallsonly.Nevertheless,itispossibletobuildanativeiOSapplicationthatsupportsWebRTCvideocalls,andthecustomdemoapplicationdemonstratesthat.

Softwaredevelopmentformobileplatformsisaveryspecificfield.Itisbarelypossibletocoverdevelopmentofanapplicationinjustonechapter.SoIassumethatyouhaveenoughexperienceofdevelopingsoftwareforcertainmobileplatforms,becausethisissomethingthatisoutofthisbook’stopic.Here,wewillonlycoverWebRTCspecificdetailsandskiptherest.

TheflowofbuildinganativeapplicationusingWebRTCmightseemtrickyandnon-trivial.Thefollowingdiagramrepresentsthegeneralcasewiththebasicstepsoftheflow:

Inthischapter,wewillcoverthisflowwithallitssteps.Wewillalsolearnhowwecanmakethisprocesseasierandsimpler.

Page 323: WebRTC Cookbook
Page 324: WebRTC Cookbook

BuildingacustomizedWebRTCdemoforiOSInthisrecipe,wewilldownloadasimple,preparedWebRTCnativedemoapplicationforiOS,compileit,andrunitonarealdevice.ThisapplicationcanbeusedforvideoconferencecallsviaGoogle’sdemowebsite,https://apprtc.webrtc.org.

Thisdemosoftwareiscustomized,meaningthatWebRTClibrariesareprecompiledandshouldbejustlinkedduringcompilationofthedemoapplication.ItalsocontainssomechangescomparedtotheoriginaldemofromGoogle.

Page 325: WebRTC Cookbook

GettingreadyThedemoapplicationissupposedtorunonadevice,notinasimulator.SoyoushouldbepreparedwithaphysicalAppledevice(iPhone,iPad)toworkonthisrecipe.

YoushouldberegisteredontheiOSDeveloperProgrambyAppletobeabletoinstalltheapplicationonyourdevice.Ifyou’renotparticipatinginthisprogram,itisworthconsideringjoining.Fordetails,pleaserefertotheprogram’sofficialwebpageathttp://developer.apple.com.

Inmycase,Iusedthefollowingtools:

iPhone5swithiOS8.0.2.AnotebookwithWindows7installedastheseconddevicetobuildtheWebRTCcommunicationchannel.Inthenotebook,IusedaChromebrowsertorunaWebRTCapplication.Xcode6tocompiletheiOSdemo.ForXcode,youalsoneedtohaveanOSXmachinethatruns.

Page 326: WebRTC Cookbook

Howtodoit…PerformthefollowingstepstobuildacustomizedWebRTCdemo:

1. Createanewprojectdirectoryandgotoitasfollows:

mkdir~/dev

cd~/dev

2. Getthesourcecodeusingthefollowingcommand:

gitclonehttps://github.com/fycth/webrtc-ios

3. OpenthedemoprojectinXcode:~/dev/webrtc-ios/ios-example/AppRTCDemo.xcodeproj.

4. ChoosethebuildtargetusingtheXcodemenubynavigatingtoProduct|Destination|iPhone.

5. BuildthedemoapplicationbynavigatingtoProduct|Build.6. ConnectyouriPhonetothemachineandrunthedemobynavigatingtoProduct|

Run.

Afterthelastcommandisexecuted,thedemoapplicationwillbeinstalledonthedeviceandwillstartautomatically;itcantakeacoupleofseconds,sodon’trushtoruntheapplicationmanually.

Inthefollowingscreenshot,youcanseeaniconoftheinstalledAppRTCDemoapplication:

Page 327: WebRTC Cookbook
Page 328: WebRTC Cookbook

Aftertheapplicationstarts,youwillseeashortmessageandaprompttoenteraroomnumber.Navigateyourbrowseronanothermachinetohttp://apprtc.webrtc.org;youwillseeanimagefromyourcamera.CopytheroomnumberfromtheURLstringandenteritinthedemoapplication.Thefollowingscreenshotrepresentsthisstage:

Page 329: WebRTC Cookbook
Page 330: WebRTC Cookbook

AfteryouenterthecodeandclickontheApplybutton,theapplicationwilltrytoconnecttothevirtualroom.Itcantakeacoupleofseconds(evenuptooneminuteinmycase),sobepatient.

Whentheconnectionisestablished,youshouldseetheimagefromtheiPhoneinthewebbrowser,andviceversa.ThefollowingscreenshotdepictsascreenshotfrommyiPhoneafterIestablishedaWebRTCconnectionwithanotebook:

Page 331: WebRTC Cookbook
Page 332: WebRTC Cookbook

Inthescreenshot,youcanseeamanwithaniPhone,fromwhichthisscreenshotwastaken.ThevideoontheiPhoneistranslatedfromthenotebook’scamera.Andthefollowingscreenshotrepresentswhatwasvisibleonthenotebook’sdisplay:

Here,inthesmallimageboxyoucanseethevideotakenfromthenotebook’swebcamera.Inthebigimage,youcanseethevideotranslatedfromtheiPhone.

Page 333: WebRTC Cookbook

There’smore…ForthisrecipeIforkedthecodefromanotherprojectonGitHub.Tolearnmore,refertohttps://github.com/gandg/webrtc-ios.

Iintroducedsomechangesintheforkedproject,fixingsomeminorissues.Youcanforkanyoftheseprojectsandtakeitscodeasthebaseofyourownproject.

Youcanalsocheckthisprojectathttps://github.com/pristineio/webrtc-build-scripts.ItisasetofscriptsdevelopedspeciallytofacilitatethecompilationofWebRTClibraries’codeforiOS.IfyoudevelopWebRTC-basedsoftwareforApplemobileOS,thistoolmightbeveryusefulforyou.

BuildingademoprojectforaiOSsimulatorThisdemoprojectusesprecompiledWebRTClibrariesthatarebuilttouseonphysicaldevices.YoushouldrebuildtheselibrariesincaseyouwanttoruntheapplicationunderaniOSsimulator.

1. DownloadandinstallGoogleDeveloperTools:

mkdir~/dev

cd~/dev

gitclone

https://chromium.googlesource.com/chromium/tools/depot_tools.git

exportPATH=`pwd`/depot_tools:"$PATH"

2. Configurethedevelopertools:

gclientconfighttp://webrtc.googlecode.com/svn/trunk

3. InformthetoolsthatwewanttobuildlibrariesforiOS:

echo"target_os=['ios']">>.gclient

4. DownloadtheWebRTCsourcecode.Itcantakeacoupleofminutes;itwilldownloadseveralgigabytesofcode.

gclientsync

5. Configurethebuildtoolasfollows:

exportGYP_DEFINES="build_with_libjingle=1build_with_chromium=0

libjingle_objc=1"

exportGYP_GENERATORS="ninja"

exportGYP_DEFINES="$GYP_DEFINESOS=iostarget_arch=ia32"

exportGYP_GENERATOR_FLAGS="$GYP_GENERATOR_FLAGSoutput_dir=out_sim"

exportGYP_CROSSCOMPILE=1

gclientrunhooks

6. Buildthelibrariesasshowninthefollowingcommandlines:

cd~/dev/trunk

ninja-Cout_sim/DebugiossimAppRTCDemo

Thebuildingprocesscantakesometime.AfterthatyouwillfindcompiledWebRTC

Page 334: WebRTC Cookbook

librariesbynavigatingto~/dev/trunk/out-sim/Debug/.

7. Nowyoushouldcopytheselibrariesintotheproject’sios-example/libsfolder,andthenyouwillbeabletobuildtheprojectforiOSsimulator.

Page 335: WebRTC Cookbook

SeealsoAnotherrecipe,BuildinganOpenWebRTClibrary,alsomightbeusefulforyouinthescopeofdevelopingWebRTCnativeapplicationsforiOSRefertotheCompilingandrunninganoriginaldemoforiOSrecipefordetailsonhowtoworkwiththeoriginaldemofromGoogle

Page 336: WebRTC Cookbook
Page 337: WebRTC Cookbook

CompilingandrunninganoriginaldemoforiOSThisrecipecovershowtobuildanoriginalGoogleWebRTCnativedemoapplicationforiOS.TheoriginaldemofromGoogledoesn’thaveanyXcodeprojectfilesusingwhichyoucouldopentheIDEanddothejobwithcomfort.Unfortunately,youwouldhavetouseasetofconsoletoolsandscriptstocompilethisapplication.

Page 338: WebRTC Cookbook

GettingreadyInthisrecipe,wewillcovertheprocessofbuildinganapplicationforbothaniOSsimulatorandforaphysicaldevice.SoyoushouldhaveaMacOSXmachinetorunthedemoinasimulator,andyoushouldhaveanApplegadgetifyouwouldliketorunitonaphysicaldevice.

YoushouldalsoberegisteredontheAppleiOSDeveloperProgramtobeabletoinstallyourapplicationonyourdevice.Ifyou’renotparticipatinginthisprogram,itisworthconsideringjoining.Fordetails,refertotheprogram’sofficialwebpageathttp://developer.apple.com.

Inmycase,IusedaMacBookProwithMacOSX10.9.5installedonit.

Page 339: WebRTC Cookbook

Howtodoit…Firstofall,weneedtodownloadandbuildtheWebRTCsourcecode.Thedemoapplicationisapartofthiscode,sowewillbuilditwiththerestbyperformingthefollowingsteps:

1. DownloadandinstallGoogleDeveloperTools:

mkdir–p~/dev&&cd~/dev

gitclone

https://chromium.googlesource.com/chromium/tools/depot_tools.git

exportPATH=`pwd`/depot_tools:"$PATH"

2. Configurethedevelopertools:

gclientconfighttp://webrtc.googlecode.com/svn/trunk

3. InformthetoolsthatwewanttobuildlibrariesforiOS:

echo"target_os=['ios','mac']">>.gclient

4. DownloadtheWebRTCsourcecode.Itcantakeacoupleofminutes;itwilldownloadseveralgigabytesofcode:

gclientsync

BuildingademoprojectforaniOSdeviceThefollowingstepsshouldbetakenifyou’rebuildingademotorunonaphysicalAppledevice.IfyouwanttorunthedemoonaniOSsimulator,skipthissectionandcontinuetothenextone:

1. Configurethebuildtoolasfollows:

exportGYP_DEFINES="build_with_libjingle=1build_with_chromium=0

libjingle_objc=1"

exportGYP_GENERATORS="ninja"

exportGYP_DEFINES="$GYP_DEFINESOS=iostarget_arch=armv7"

exportGYP_GENERATOR_FLAGS="$GYP_GENERATOR_FLAGSoutput_dir=out_ios"

exportGYP_CROSSCOMPILE=1

2. Preparethebuildscripts:

gclientrunhooks

3. Buildthedemoapplication:

cd~/dev/trunk

ninja-Cout_ios/Debug-iphoneosAppRTCDemo

BuildingademoprojectforaniOSsimulatorThissectiondescribesthestepsthatshouldbetakenifyouwanttocompiletheapplicationforaniOSsimulator.Ifyouwanttoruntheapplicationonaphysicaldevice,findthe

Page 340: WebRTC Cookbook

relevantstepsprovidedintheprevioussection:

1. Configurethebuildtoolasfollows:

exportGYP_DEFINES="build_with_libjingle=1build_with_chromium=0

libjingle_objc=1"

exportGYP_GENERATORS="ninja"

exportGYP_DEFINES="$GYP_DEFINESOS=iostarget_arch=ia32"

exportGYP_GENERATOR_FLAGS="$GYP_GENERATOR_FLAGSoutput_dir=out_sim"

exportGYP_CROSSCOMPILE=1

2. Preparebuildscripts:

gclientrunhooks

3. Buildademoapplication:

cd~/dev/trunk

ninja-Cout_sim/DebugiossimAppRTCDemo

4. StarttheapplicationinaniOSsimulator:

~/dev/trunk/out_sim/Debug/AppRTCDemo.app

Page 341: WebRTC Cookbook

There’smore…TheoriginalcodefromGoogledoesn’thaveanyIDEprojectfilessoyouhavetodealwithconsolescriptsthroughallthedevelopmentprocess.Thiscanbeeasierifyouusesomethird-partytoolsthatsimplifythebuildingprocess.Suchkindsoftoolscanbefoundathttp://tech.pristine.io/build-ios-apprtc/.

Page 342: WebRTC Cookbook

SeealsoItisalsoworthtakingalookattheBuildingacustomizedWebRTCdemoforiOSrecipe.Inthisrecipewecovertheprocessofusingaready-to-useXcodesimpleprojectwithprecompiledWebRTCbinaries.

Page 343: WebRTC Cookbook
Page 344: WebRTC Cookbook

CompilingandrunningademoforAndroidHere,youwilllearnhowtobuildanativedemoWebRTCapplicationforAndroid.Unfortunately,thesupplieddemoapplicationfromGoogledoesn’tcontainanyIDE-specificprojectfiles,soyouwillhavetodealwithconsolescriptsandcommandsduringallthebuildingprocess.

Page 345: WebRTC Cookbook

GettingreadyWewillneedtocheckwhetherwehaveallthenecessarylibrariesandpackagesinstalledontheworkmachine.Forthisrecipe,IusedaLinuxbox—Ubuntu14.04.1x64.SoallthecommandsthatmightbespecificforOSwillberelevanttoUbuntu.Nevertheless,usingLinuxisnotmandatoryandyoucantakeWindowsorMacOSX.

TipIfyou’reusingLinux,itshouldbe64-bitbased.Otherwise,youmostlikelywon’tbeabletocompileAndroidcode.

PreparingthesystemFirstofall,youneedtoinstallthenecessarysystempackages:

sudoapt-getinstallgitgit-svnsubversiong++pkg-configgtk+-2.0

libnss3-devlibudev-devantgcc-multiliblib32z1lib32stdc++6

InstallingOracleJDKBydefault,UbuntuissuppliedwithOpenJDK,butitishighlyrecommendedthatyouinstallanOracleJDK.Otherwise,youcanfaceissueswhilebuildingWebRTCapplicationsforAndroid.OneanotherthingthatyoushouldkeepinmindisthatyoushouldprobablyuseOracleJDKversion1.6—otherversions(inparticular,1.7and1.8)mightnotbecompatiblewiththeWebRTCcodebase.Thiswillprobablybefixedinthefuture,butinmycase,onlyOracleJDK1.6wasabletobuildthedemosuccessfully.

1. DownloadtheOracleJDKfromitshomepageathttp://www.oracle.com/technetwork/java/javase/downloads/index.html.

IncasethereisnodownloadlinkonsuchanoldJDK,youcantryanotherURL:http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-javase6-419409.html.

TipOraclewillprobablyaskyoutosigninorregisterfirst.Youwillbeabletodownloadanythingfromtheirarchive.

2. InstallthedownloadedJDK:

sudomkdir–p/usr/lib/jvm

cd/usr/lib/jvm&&sudo/bin/sh~/jdk-6u45-linux-x64.bin--noregister

Here,IassumethatyoudownloadedtheJDKpackageintothehomedirectory.

3. RegistertheJDKinthesystem:

sudoupdate-alternatives--install/usr/bin/javacjavac

/usr/lib/jvm/jdk1.6.0_45/bin/javac50000

sudoupdate-alternatives--install/usr/bin/javajava

/usr/lib/jvm/jdk1.6.0_45/bin/java50000

sudoupdate-alternatives--configjavac

Page 346: WebRTC Cookbook

sudoupdate-alternatives--configjava

cd/usr/lib

sudoln-s/usr/lib/jvm/jdk1.6.0_45java-6-sun

exportJAVA_HOME=/usr/lib/jvm/jdk1.6.0_45/

4. TesttheJavaversion:

java-version

YoushouldseesomethinglikeJavaHotSpotonthescreen—itmeansthatthecorrectJVMisinstalled.

GettingtheWebRTCsourcecodePerformthefollowingstepstogettheWebRTCsourcecode:

1. DownloadandprepareGoogleDeveloperTools:

mkdir–p~/dev&&cd~/dev

gitclone

https://chromium.googlesource.com/chromium/tools/depot_tools.git

exportPATH=`pwd`/depot_tools:"$PATH"

2. DownloadtheWebRTCsourcecode:

gclientconfighttp://webrtc.googlecode.com/svn/trunk

echo"target_os=['android','unix']">>.gclient

gclientsync

Thelastcommandcantakeacoupleofminutes(actually,itdependsonyourInternetconnectionspeed),asyouwillbedownloadingseveralgigabytesofsourcecode.

InstallingAndroidDeveloperToolsTodevelopAndroidapplications,youshouldhaveAndroidDeveloperTools(ADT)installed.ThisSDKcontainsAndroid-specificlibrariesandtoolsthatarenecessarytobuildanddevelopnativesoftwareforAndroid.PerformthefollowingstepstoinstallADT:

1. DownloadADTfromitshomepagehttp://developer.android.com/sdk/index.html#download.

2. UnpackADTtoafolder:

cd~/dev

unzip~/adt-bundle-linux-x86_64-20140702.zip

3. SetuptheANDROID_HOMEenvironmentvariable:

exportANDROID_HOME=`pwd`/adt-bundle-linux-x86_64-20140702/sdk

Page 347: WebRTC Cookbook

Howtodoit…Afteryou’vepreparedtheenvironmentandinstalledthenecessarysystemcomponentsandpackages,youcancontinuetobuildthedemoapplication:

1. PrepareAndroid-specificbuilddependencies:

cd~/dev/trunk

source./build/android/envsetup.sh

2. Configurethebuildscripts:

exportGYP_DEFINES="$GYP_DEFINESbuild_with_libjingle=1

build_with_chromium=0libjingle_java=1OS=android"

gclientrunhooks

3. BuildtheWebRTCcodewiththedemoapplication:

ninja-Cout/Debug-j5AppRTCDemo

Afterthelastcommand,youcanfindthecompiledAndroidpacketwiththedemoapplicationat~/dev/trunk/out/Debug/AppRTCDemo-debug.apk.

RunningontheAndroidsimulatorFollowthesestepstorunanapplicationontheAndroidsimulator:

1. RunAndroidSDKmanagerandinstallthenecessaryAndroidcomponents:

$ANDROID_HOME/tools/androidsdk

ChooseatleastAndroid4.x—lowerversionsdon’thaveWebRTCsupport.Inthefollowingscreenshot,I’vechosenAndroidSDK4.4and4.2:

Page 348: WebRTC Cookbook

2. CreateanAndroidvirtualdevice:

cd$ANDROID_HOME/tools

./androidavd&

ThelastcommandexecutestheAndroidSDKtooltocreateandmaintainvirtualdevices.Createanewvirtualdeviceusingthistool.Youcanseeanexampleinthefollowingscreenshot:

Page 349: WebRTC Cookbook

3. Starttheemulatorusingjustthecreatedvirtualdevice:

./emulator–avdemu1&

Thiscantakeacoupleofseconds(orevenminutes),afterthatyoushouldseeatypicalAndroiddevicehomescreen,likeinthefollowingscreenshot:

Page 350: WebRTC Cookbook

4. Checkwhetherthevirtualdeviceissimulatedandrunning:

cd$ANDROID_HOME/platform-tools

./adbdevices

Youshouldseesomethinglikethefollowing:

Listofdevicesattached

emulator-5554device

ThismeansthatyourjustcreatedvirtualdeviceisOKandrunning;sowecanuseittotestourdemoapplication.

5. Installthedemoapplicationonthevirtualdevice:

./adbinstall~/dev/trunk/out/Debug/AppRTCDemo-debug.apk

Youshouldseesomethinglikethefollowing:

636KB/s(2507985bytesin3.848s)

pkg:/data/local/tmp/AppRTCDemo-debug.apk

Success

Thismeansthattheapplicationistransferredtothevirtualdeviceandisreadytobestarted.

6. Switchtothesimulatorwindow;youshouldseethedemoapplication’sicon.ExecuteitlikeitisarealAndroiddevice.Inthefollowingscreenshot,youcanseetheinstalleddemoapplicationAppRTC:

Page 351: WebRTC Cookbook

TipWhiletryingtolaunchtheapplication,youmightseeanerrormessagewithaJavaruntimeexceptionreferringtoGLSurfaceView.Inthiscase,youprobablyneedtoswitchtotheUseHostGPUoptionwhilecreatingthevirtualdevicewithAndroidVirtualDevice(AVD)tool.

FixingabugwithGLSurfaceViewSometimesifyou’reusinganAndroidsimulatorwithavirtualdeviceontheARMarchitecture,youcanbefacedwithanissuewhentheapplicationsaysNoconfigchosen,throwsanexception,andexits.

ThisisaknowndefectintheAndroidWebRTCcodeanditsstatuscanbetrackedathttps://code.google.com/p/android/issues/detail?id=43209.

Thefollowingstepscanhelpyoufixthisbugintheoriginaldemoapplication:

1. Gotothe~/dev/trunk/talk/examples/android/src/org/appspot/apprtcfolderandedittheAppRTCDemoActivity.javafile.Lookforthefollowinglineofcode:

vsv=newAppRTCGLView(this,displaySize);

2. Rightafterthisline,addthefollowinglineofcode:

vsv.setEGLConfigChooser(8,8,8,8,16,16);

Page 352: WebRTC Cookbook

Youwillneedtorecompiletheapplication:

cd~/dev/trunk

ninja-Cout/DebugAppRTCDemo

3. Nowyoucandeployyourapplicationandtheissuewillnotappearanymore.

RunningonaphysicalAndroiddeviceFordeployingapplicationsonanAndroiddevice,youdon’tneedtohaveanydevelopercertificates(likeinthecaseofiOSdevices).SoifyouhaveanAndroidphysicaldevice,itprobablywouldbeeasiertodebugandrunthedemoapplicationonthedeviceratherthanonthesimulator.

1. ConnecttheAndroiddevicetothemachineusingaUSBcable.2. OntheAndroiddevice,switchtheUSBdebugmodeon.3. Checkwhetheryourmachineseesyourdevice:

cd$ANDROID_HOME/platform-tools

./adbdevices

Ifdeviceisconnectedandthemachineseesit,youshouldseethedevice’snameintheresultprintoftheprecedingcommand:

Listofdevicesattached

QO4721C35410device

4. Deploytheapplicationontothedevice:

cd$ANDROID_HOME/platform-tools

./adb-dinstall~/dev/trunk/out/Debug/AppRTCDemo-debug.apk

Youwillgetthefollowingoutput:

3016KB/s(2508031bytesin0.812s)

pkg:/data/local/tmp/AppRTCDemo-debug.apk

Success

AfterthatyoushouldseetheAppRTCdemoapplication’sicononthedevice.

Page 353: WebRTC Cookbook

Afteryouhavestartedtheapplication,youshouldseeaprompttoenteraroomnumber.Atthisstage,gotohttp://apprtc.webrtc.orginyourwebbrowseronanothermachine;you

Page 354: WebRTC Cookbook

willseeanimagefromyourcamera.CopytheroomnumberfromtheURLstringandenteritinthedemoapplicationontheAndroiddevice.YourAndroiddeviceandanothermachinewilltrytoestablishapeer-to-peerconnection,andmighttakesometime.Inthefollowingscreenshot,youcanseetheimageonthedesktopaftertheconnectionwithAndroidsmartphonehasbeenestablished:

Here,thebigimagerepresentswhatistranslatedfromthefrontalcameraoftheAndroidsmartphone;thesmallimagedepictstheimagefromthenotebook’swebcamera.Soboththedeviceshaveestablisheddirectconnectionandtranslateaudioandvideotoeachother.

ThefollowingscreenshotrepresentswhatwasseenontheAndroiddevice:

Page 355: WebRTC Cookbook
Page 356: WebRTC Cookbook

There’smore…Theoriginaldemodoesn’tcontainanyready-to-useIDEprojectfiles;soyouhavetodealwithconsolecommandsandscriptsduringallthedevelopmentprocess.Youcanmakeyourlifeabiteasierifyouusesomethird-partytoolsthatsimplifythebuildingprocess.Suchtoolscanbefoundathttp://tech.pristine.io/build-android-apprtc.

Page 357: WebRTC Cookbook

SeealsoIfyouconsiderdevelopingWebRTCapplicationsforiOS,theBuildingacustomizedWebRTCdemoforiOSrecipemightalsobeusefulforyou

Page 358: WebRTC Cookbook
Page 359: WebRTC Cookbook

BuildinganOpenWebRTClibraryAtthebeginningof2014,EricssonpresenteditsownopensourceimplementationofWebRTCstack—OpenWebRTC.EricssonstatesthatthisproductsupportsiOS,Android,Windows,Linux,andMacOSXplatformsfromthebox.Inthisrecipe,wewillbuildthisnewWebRTCstack.Thisimplementationcameoutjustacoupleofdaysagoandthereisn’taready-to-useexamplesuppliedwithit,sowewillbuildjustthelibrary.

Page 360: WebRTC Cookbook

GettingreadyAtthistime,OpenWebRTCbuildscriptssupportLinuxandMacOSXplatformsonly,andthereisnoreadysolutiontobuildOpenWebRTCunderWindows.SoyouneedLinuxorOSXinstalledtoworkonthisrecipe.

Inmycase,IusedaMacBookProwithMacOSX10.9installed.

Page 361: WebRTC Cookbook

Howtodoit…PerformthefollowingstepstobuildOpenWebRTC:

1. Getthesourcecodes:

mkdir~/dev&&cd~/dev

[email protected]:EricssonResearch/openwebrtc.git--recursive

cdopenwebrtc

2. Configuretheenvironment(thisstepwilltakesometime).Ifyou’reworkingunderLinux,putlinuxinsteadofosxinthecommand:

cdscripts/bootstrap

./bootstrap.sh-rosx

cd-

3. Buildthedependencies.Youcanalsouselinuxandandroidwordsifyou’rebuildingfortheappropriateplatforms.NotethatyouneedAndroidNDKinstalledandconfiguredtobuilddependenciesforthisplatform:

cdscripts/dependencies

./build-all.sh-rosxios

./deploy_deps.sh

cd–

4. BuildOpenWebRTCusingthefollowingcommand:

./build.sh-rosxios

Afterallthesecommandsareexecuted,youwillhaveOpenWebRTClibrariesbuiltandreadytouse.Tofurtherlearnthislibrary,itmightbeworthtakingalookatBowser—anopensourcedwebbrowsercompletelybuiltontheOpenWebRTCstack.

Page 362: WebRTC Cookbook

There’smore…Thisnewlibraryisunderactivedevelopmentandevenitsdocumentationactivelychanges.So,formoredetails,pleaserefertothehomepageoftheprojectathttp://www.openwebrtc.io.

AlsotakealookatBowser—anopensourceWebRTC-orientedwebbrowserfromEricsson.ThisbrowsercanrununderbothAndroidandiOS.Itshomepageisathttp://www.openwebrtc.io/bowser/.

Page 363: WebRTC Cookbook
Page 364: WebRTC Cookbook

Chapter7.Third-partyLibrariesInthischapter,wewillcoverthefollowingtopics:

BuildingavideoconferenceusingSimpleWebRTCCreatinganapplicationusingRTCMultiConnectionDevelopingasimpleWebRTCchatusingPeerJSMakingasimplevideochatwithrtc.ioUsingOpenToktocreateaWebRTCapplicationCreatingamultiuserconferenceusingWebRTCO

Page 365: WebRTC Cookbook

IntroductionWhenanewtechnologyoraninstrumentappearsonthemarket,itmightnotbereasonabletocreateyourownframeworkoralibrarybyutilizingthisnewtooltodevelopaproduct.SometimesitisworthlookingaroundandusingaSoftwareDevelopmentKit(SDK)oraready-to-useframeworkthatimplementsallthetechnology’snecessaryfeatures.

WebRTCisaveryyoungtechnologythatisunderactivedevelopment.Wedon’thaveacompletedstandardyet,onlyadraft.Therearemanythird-partyframeworksandlibrariesavailablethatutilizeWebRTCfeaturesandprovideaniceAPIforadeveloper.Tousesuchtools,itisnotnecessarytogetdeepintoWebRTCandstandards,butyoucanconcentratejustonyourproduct.

TipMostoftheframeworksprovideyouwithacompletesetoftools.Therefore,youmightneedtouseGoogle’sadapter.jsinadditiontokeepcompatibilitybetweenmultiplewebbrowsersortheir(browsers’)versions.

Usually,suchanSDKcanmakeadeveloper’slifeeasier—theyoftenprovideadditionalservicessuchassignalingandSTUN/TURNservers.Whenusingagoodthird-partyframework,youoftendon’tneedtotakecareoftheserverinfrastructureandinstallationandmaintenanceofyourownsignalingserver;youcanworkonlyontheclientcode—therestwillbeservedbythechosensolution.

Inthischapter,wewillconsiderafewsuchtools.Youwillfindrecipesthatutilizeatool’sAPItoimplementbasicexamplesofWebRTCapplications.Allexamplesarebasedontheofficialtool’sdocumentationanddemoapplicationsfromtheirhomepages.

TipWebRTCstackisdevelopedwithgreatattentiontosecurity,andthewebbrowsermightnotevenruntheapplicationincaseitisaccessedfromthelocalsystem.Sowhiletestingtheprovidedexamples,placethemonawebserver.Asanalternative,youcanusecloudservicessuchasDropboxforaccessingtheapplicationoverpublicfolder—inthiscase,youshouldchangeallHTTPlinksintheapplicationtoHTTPS.

Page 366: WebRTC Cookbook
Page 367: WebRTC Cookbook

BuildingavideoconferenceusingSimpleWebRTCSimpleWebRTCisaveryeasy-to-useframeworkwritteninJavaScript.Usingthisproduct,youcanstartyourfirstvideoconferenceinjustoneminute.Inthisrecipe,wewillcovertheprocessofcreatingofabasicWebRTCapplicationusingtheSimpleWebRTCsoftware.

Page 368: WebRTC Cookbook

GettingreadyInthisrecipe,wewillcreateasimpleHTMLpagebyutilizingaSimpleWebRTCframework.So,youwillneedatexteditorandaWebRTCcompliantwebbrowser.Ifyou’reusingFirefox,thedemomightbeexecutedfromthelocalfilesystem;ifyou’reusingChrome,youshoulduseawebserver—otherwise,thebrowserwillprohibittherunningoftheapplication.

Page 369: WebRTC Cookbook

Howtodoit…Tobuildabasicvideoconferenceusingthistool,youneedtocreatejustoneHTMLwebpage.Youdon’tevenneedtoregisteranaccountinthevendor’ssystem.

1. CreateanemptyHTMLfileandaddthefollowingcode:

<!DOCTYPEhtml>

<html>

<headlang="en">

<metacharset="UTF-8">

2. IncludeaSimpleWebRTCJavaScriptframework:

<scriptsrc="http://simplewebrtc.com/latest.js"></script>

</head>

<body>

3. Createavideoobjectforalocalvideo:

<videoheight="300"id="localVideo"></video>

4. Createavideoobjectforthevideotranslatedfromaremotepeer:

<divid="remotesVideos"></div>

<br>

5. Createabuttonandtieahandlerfunctiontoit.Whenyouclickthebutton,videoconferencewillbecreated:

<buttonid="btn1"onclick="startconf()">Startconference</button>

<scriptlanguage="JavaScript">

6. SetupavariabletohandletheSimpleWebRTCobject:

varwebrtc=null;

Thefollowingfunctioniscalledwhenacustomerclicksthebutton:

functionstartconf(){

7. CreateaSimpleWebRTCobjectwithinitialparameters.WewillsendtheIDsofboththevideoobjects(forlocalandremotevideo);also,wewillasktheframeworktogetmediaaccessimmediately:

webrtc=newSimpleWebRTC({

localVideoEl:'localVideo',

remoteVideosEl:'remotesVideos',

autoRequestMedia:true

});

Thefollowingcodeactuallystartsthevideoconference.Here,wewillalsosetupavirtualroomname,Room86#—youarefreetouseanynameyouwouldliketouse:

webrtc.on('readyToCall',function(){

webrtc.joinRoom('Room86#');

});

Page 370: WebRTC Cookbook

};

</script>

</body>

</html>

8. Now,savethisfileinafolderandopenitinyourwebbrowser(inmycase,I’veusedFirefoxforMacOSX).

Page 371: WebRTC Cookbook

Howitworks…WhenyouopentheHTMLfileinyourwebbrowser,youwillseeablankpagewithabutton.ClickontheStartconferencebutton—thewebbrowserwillcaptureavideofromyourwebcameraandshowitonthepage(itmayaskyouforaccesspermission).

Inthefollowingscreenshot,youcanseethisstage:

Now,itistimetoconnectanotherpeer.OpenthesameHTMLfileinanotherbrowser.Youcanevencopyittoanothermachineandopenitthere.ThenclickontheStartconferencebutton—afteracoupleofseconds,thepeerconnectionshouldbeestablishedandyoushouldseeboththelocalandremoteimagesoneverybrowserwindow,asshowninthefollowingscreenshot:

Page 372: WebRTC Cookbook

Noteyoudon’tneedtoinstallasignalingserver—SimpleWebRTCtakescareofit.WhenyoucallSimpleWebRTC’sJavaScriptAPImethods,itcommunicatestothesignalerserverinstalledontheSimpleWebRTC’sservers.

Page 373: WebRTC Cookbook

There’smore…AlthoughweconsideredaverysimpleexampleofusingaSimpleWebRTCframework,thistoolcanbeusedtobuildmorecomplexapplications.Formoredetails,pleaserefertotheofficialdocumentationfortheframeworkathttp://simplewebrtc.com.

Page 374: WebRTC Cookbook
Page 375: WebRTC Cookbook

CreatinganapplicationusingRTCMultiConnectionThisrecipecoverstheprocessofcreatingasimpleWebRTCapplicationusinganopensourceRTCMultiConnectionframework.ThisisaJavaScript-basedframeworkthatallowsyoutobuildapplicationsandservicesusingmanyWebRTCfeatures,includingexperimentalfeatures.

Page 376: WebRTC Cookbook

GettingreadyToworkwiththisframework,wewillbuildabasicWebRTCservicethatsupportsprivatevirtualroomsforvideoconferencing.YouwillneedtowritesomeHTMLandJavaScriptcode,whichdoesnotneedtodevelopanyserver-sideparts.So,havingjustatexteditorandaWebRTCcompliantwebbrowsershouldbeenoughtoworkonthisrecipe.

Page 377: WebRTC Cookbook

Howtodoit…TheRTCMultiConnectiontooltakesalloftheworkregardingthesignalingonitsown.Thus,youcanconcentrateontheclientsideandUI.

1. CreateanemptyHTMLfileandaddthefollowingcodeinsideit:

<!DOCTYPEhtml>

<html>

<headlang="en">

<metacharset="UTF-8">

2. IncludetheHTMLstylesuppliedwiththetool.Thisisnotnecessary,andyoucanuseyourownCSS:

<linkrel="stylesheet"href="http://cdn.webrtc-

experiment.com/style.css">

3. Includetheframework’sJavaScriptlibraries:

<scriptsrc="http://cdn.webrtc-experiment.com/firebase.js">

</script>

<scriptsrc="http://cdn.webrtc-

experiment.com/RTCMultiConnection.js">

</script></head>

<body>

<section>

<span>

4. Thefollowinganchorisusedforcreatingvirtualrooms:

<ahref=""target="_blank"title=""><code>

<strongid="unique-token"></strong></code></a></span>

5. Addaninputobjecttohandlethevirtualroomname:

<inputtype="text"id="conference-name">

6. Createanewbuttonelementonthepage.Whenitisclicked,anewconferencewillstart:

<buttonid="setup-new-conference"class="setup">SetupNew

Conference</button>

</section>

<tablestyle="width:100%;"id="rooms-list"></table>

7. Createaseparatedivlayerforthevideoobjects:

<divid="videos-container"></div>

</section>

<script>

8. Createanewconnectionobject.Usingthisobject,wecancontroltheconnectionitself:

varconnection=newRTCMultiConnection();

connection.session={

Page 378: WebRTC Cookbook

audio:true,

video:true

};

9. Declareacallbackhandlerthatwillbecalledwhenanewmediastreamisready.Thishandlerwillcreateanewvideoobjectforeverymediastreamandplaceitinthevideocontainerlayer:

connection.onstream=function(e){

e.mediaElement.width=300;

videosContainer.insertBefore(e.mediaElement,

videosContainer.firstChild);

};

10. Createahandlerforthestreamendedevent.Itwillbecalledwhenastreamisstopped(peerconnectionisinterrupted,forexample).Thisfunctionwillremovetheirrelevantvideoobject:

connection.onstreamended=function(e){

e.mediaElement.style.opacity=0;

setTimeout(function(){

if(e.mediaElement.parentNode){

e.mediaElement.parentNode.removeChild(e.mediaElement);

}

},1000);

};

varsessions={};

11. Makeafunctionthatwillbecalledwhenanewvirtualroomiscreated,andsomeoneiswaitingfortheremotepeertojoin:

connection.onNewSession=function(session){

if(sessions[session.sessionid])return;

sessions[session.sessionid]=session;

vartr=document.createElement('tr');

12. Weneedtonotifythecustomerwhenthevirtualroomiscreated.ThefollowingcodeshowssuchanotificationandcreatesaJoinbutton:

tr.innerHTML='<td><strong>'+session.extra['session-name']+

'</strong>isrunningaconference!</td>'+'<td><button

class="join">Join</button></td>';

roomsList.insertBefore(tr,roomsList.firstChild);

varjoinRoomButton=tr.querySelector('.join');

joinRoomButton.setAttribute('data-sessionid',

session.sessionid);

13. CreateanappropriatecodefortheJoinbutton:

joinRoomButton.onclick=function(){

this.disabled=true;

varsessionid=this.getAttribute('data-sessionid');

session=sessions[sessionid];

if(!session)throw'Nosuchsessionexists.';

connection.join(session);

};

Page 379: WebRTC Cookbook

};

varvideosContainer=document.getElementById('videos-container')||

document.body;

varroomsList=document.getElementById('rooms-list');

document.getElementById('setup-new-conference').onclick=

function(){

this.disabled=true;

connection.extra={

'session-name':document.getElementById('conference-

name').value||'Anonymous'

};

connection.open();

};

connection.connect();

14. TheuniqueURLtosharethevirtualroomwithothersiscreatedontheclientsideaswell.Thefollowingcoderepresentshowthistaskissolvedintheexample:

(function(){

varuniqueToken=document.getElementById('unique-token');

if(uniqueToken)

if(location.hash.length>2)

uniqueToken.parentNode.parentNode.parentNode.innerHTML='<h2

style="text-align:center;"><ahref="'+location.href+'"

target="_blank">Sharethislink</a></h2>';

elseuniqueToken.innerHTML=

uniqueToken.parentNode.parentNode.href='#'+(Math.random()*new

Date().getTime()).toString(36).toUpperCase().replace(/\./g,'-');

})();

</script>

</body>

</html>

Thatisall.Savethisfileonadisk,andnavigateyourwebbrowsertoit.

Page 380: WebRTC Cookbook

Howitworks…WhenyouopentheHTMLfile,youwillseeawebpagesimilartothefollowing:

Now,createanewprivatevirtualroombyclickingontheURLtotheleft(itwillopenanewtabinthebrowserasshowninthefollowingscreenshot).

Inthispage,youshouldenteryournameoraroom’snameintheinputtextbox,andthenclickontheSetupNewConferencebutton.Afterthat,youshouldseetheimagefromyourwebcamera:

Page 381: WebRTC Cookbook

Now,copytheSharethislinkURLandopenitonanothermachine,oryoucanopenitinanotherbrowser’stab,likeIdid.YouwillseeabigJoinbuttonliketheoneshowninthefollowingscreenshot:

So,toconnecttotheconference,justclickontheJoinbutton.Rightafterthat,theconferencewilltrytoestablishpeer-to-peerconnection.Ifeverythinggoeswell,everypeershouldseebothlocalandremoteimages.

TipInmycase,Iusedthesamemachine(justseparatebrowserwindows),sotheimagesareidentical.

Page 382: WebRTC Cookbook

ThislibraryusesFirebase(https://www.firebase.com)forsignaling,soyoudon’tneedtoinstallandmaintainyourownsignalingserver—RTCMultiConnectionwilltakecareofthat.

Page 383: WebRTC Cookbook

There’smore…RTCMultiConnectionallowsyoutocreatemorecomplexapplications,andutilizeadvancedWebRTCfeatures.Here,wetouchedjustthebasicconcepts.

Fordetailsonhowtousethisframework,refertoitsofficialhomepagehttps://www.webrtc-experiment.com/RTCMultiConnection/.

Page 384: WebRTC Cookbook
Page 385: WebRTC Cookbook

DevelopingasimpleWebRTCchatusingPeerJSInthisrecipe,wewillusethePeerJSWebRTCframeworktocreateasimplewebchatconceptbyutilizingdatachannels.

Page 386: WebRTC Cookbook

GettingreadyPeerJSrequiresdeveloperstoregisterbeforetheycanuseitsAPI.Duringtheregistrationprocess(itisfree),adevelopergetsauniqueIDthatcanbeusedtoworkwiththeAPI.Ifyouwouldliketousethisframeworkanddon’tmindregistering,thenvisititshomepageathttp://peerjs.com.

Page 387: WebRTC Cookbook

Howtodoit…UsingPeerJSisreallysimple,andabasicexamplecanbeperformedusingjustoneHTMLfile.Inthefollowingsteps,youwillfindsuchanindexfilewithcommentsinalltheimportantplaces:

1. PlacethestandardHTMLheaders:

<!DOCTYPEhtml>

<html>

<headlang="en">

<metacharset="UTF-8">

2. IncludethePeerJSlibrary:

<scriptsrc="http://cdn.peerjs.com/0.3/peer.js"></script>

</head>

<body>

3. Addaninputtextbox.Here,acustomercanenterhis/hernamewhileconnectingtothesystem.Forsimplicity,thesameboxwillbeusedtoenterfurtherchatmessages:

<br><inputtype="text"id="inputbox"/>

4. Createthreebuttonstoconnecttothesystem,tocalltheremotepeer,andtosendmessagestotheremotepeer:

<buttonid="btn_connect"onclick="Connect()">Connect!</button>

<buttonid="btn_call"onclick="CallTo()"disabled="true">Call

To</button>

<buttonid="btn_send"onclick="SendMessage()">Sendmessage</button>

<scriptlanguage="JavaScript">

5. Inthefollowingvariable,youshouldaddyourdeveloperAPIIDyougotfromthePeerJSsystemduringtheregistrationprocess:

varMY_API_ID=YOUR_API_ID;

varpeer=null;

varconn=null;

6. Thefollowingfunctiontakesthecustomer’snameandregistersitinthePeerJSsystem.Afterthat,anotherpeercanconnecttothiscustomerusingitsnameforconnection:

functionConnect(){

varmyname=document.getElementById("inputbox").value;

peer=newPeer(myname,{key:MY_API_ID});

7. Setupacallbackfunctionontheconnectionevent.Thisfunctionwillbecalledwhenaremotepeerestablishesaconnectionwithus.Here,wewillalsosetahelperfunctionthatwillprintthereceivedmessagesfromtheremotepeertothebrowser’sconsole:

peer.on('connection',function(connection){

connection.on('data',function(data){

Page 388: WebRTC Cookbook

console.log("Remotepeersaid:"+data);

});

conn=connection;

});

document.getElementById("btn_connect").setAttribute("disabled",

"true");

document.getElementById("btn_call").removeAttribute("disabled");

};

8. Wealsoneedafunctionthatwillcalltheremotepeer.Thefollowingcoderepresentssuchafunction.Ittakesaremotepeer’snamefromtheinputtextboxandcallsPeerJStoestablishtheconnection:

functionCallTo(){

varremotename=document.getElementById("inputbox").value;

conn=peer.connect(remotename);

document.getElementById("btn_call").setAttribute("disabled","true");

};

9. Tosendmessages,weneedanappropriatefunctionresponsibleforthat.Suchafunction,youcanfindinthefollowing:

functionSendMessage(){

varmsg=document.getElementById("inputbox").value;

conn.send(msg);

};

</script>

</body>

</html>

Thatisall.Savethisfileonadisk,andnavigateyourwebbrowsertothedemo.

Page 389: WebRTC Cookbook

Howitworks…OpenapreparedHTMLfile,inthat,youwillseeaninputboxandthreebuttons.Enterapeer’snameinthetextboxandclickontheConnect!button.ItwillconnecttoaPeerJSsystem.Now,openthefileinanotherbrowser(wecanalsoopenthefileonanothermachine).Enteranotherpeer’sname,andclickonConnect!.Inthefollowingscreenshot,Iusedpeer1andpeer2asnamesforthepeers:

Now,forthesecondpeer,enterthefirstpeer’sname(peer1inmycase)inthetextbox,andclickontheCallTobutton.Thiswillstarttoestablishthepeerconnection—peer2

willtrytomakeacalltopeer1.

Aftertheconnectionisestablished,wecantestmessageexchanging.Forpeer2,enteranyinputinthetextboxandclickonSendmessage.Theenteredtextwillbesenttopeer1,andwillbeprintedinitsbrowserconsole.Inthefollowingscreenshot,IhavesentaHello,peer1!!!message:

Page 390: WebRTC Cookbook

PeerJSusesitsowninfrastructuresuchassignalingmechanisms.Thus,ifyouusePeerJS,youdon’tneedtobeworriedofdevelopingsignalingprotocols,andyoucanconcentrateondevelopingyourapplication.

Page 391: WebRTC Cookbook

There’smore…YoucanfindoutmoreaboutPeerJSfromitshomepagehttp://peerjs.com.

Thisisafreeandopensourcetool,soitcanbeusedasanSDKorcanbetakenasacodebasefordevelopinganotherWebRTCframeworkforcustomapplication.

Page 392: WebRTC Cookbook
Page 393: WebRTC Cookbook

Makingasimplevideochatwithrtc.iortc.ioisafreeandopensourceprojectfordevelopingWebRTCapplications.ItprovidessimpleandcleanAPIs.Inthisrecipe,wewillusertc.iotocreateabasicvideochatservice.

Page 394: WebRTC Cookbook

GettingreadyLikemostoftheotherconsideredframeworks,rtc.ioservesitsownsignalingserver,soyoucancreateabasicapplicationusingjustafewlinesofJavaScriptcodeandHTML.Forthisrecipe,youwillneedatexteditorandwebbrowser.

Page 395: WebRTC Cookbook

Howtodoit…Createanemptyfileinthetexteditorandaddthefollowingcode.ThisisaplainHTMLwithaJavaScriptsection.Relevantplacesarecommentedinline.

1. Firstofall,let’saddthestandardHTMLheadsandbitofstyles:

<!DOCTYPEhtml>

<html>

<headlang="en">

<metacharset="UTF-8">

<style>

#messages{

border:1pxsolidblack;

min-height:20px;

}

</style>

2. Includethertc.ioframeworkinthisproject:

<scriptsrc="https://rawgit.com/rtc-io/rtc/master/dist/rtc.js">

</script></head>

<body>

3. Createseparatedivlayersforchatmessagesandbothlocalandremotevideo:

<divid="messages"contenteditable></div>

<divid="l-video"></div>

<divid="r-video"></div>

<scriptlanguage="JavaScript">

4. Settheframework’soptions—forabasiccase,wejustneedaroom’snameandsignalerserverURL.Here,weusedanativesignalerseverhostedonthertc.ioinfrastructure.It’sanopensourcecode,soyoucandownloadandinstallitonyourownserver:

varrtcOpts={

room:'my-cool-test-room',

signaller:'//switchboard.rtc.io'

};

5. InitializetheframeworkandcreateanRTCobject:

varrtc=RTC(rtcOpts);

varlocalVideo=document.getElementById('l-video');

varremoteVideo=document.getElementById('r-video');

varmessageWindow=document.getElementById('messages');

6. Bindhandlerfunctionstoappropriateeventsthatmightbegeneratedonthedatachannel:

functionbindDataChannelEvents(id,channel,attributes,connection){

channel.onmessage=function(evt){

messageWindow.innerHTML=evt.data;

};

messageWindow.onkeyup=function(){

Page 396: WebRTC Cookbook

channel.send(this.innerHTML);

};

}

7. Initializethesession:

functioninit(session){

session.createDataChannel('chat');

session.on('channel:opened:chat',bindDataChannelEvents);

}

8. Displaythelocalandremotevideo:

localVideo.appendChild(rtc.local);

remoteVideo.appendChild(rtc.remote);

9. Handlethesessionestablishingevent:

rtc.on('ready',init);

</script>

</body>

</html>

Theexamplecanbesavedonthediskanduploadedtothewebserver.

Page 397: WebRTC Cookbook

Howitworks…WecreatedanewRTCobjectusingtheframework’sAPI.Additionally,wesetacoupleoffunctionstohandleevents.Then,weinitializedtheframeworkbycallingtheappropriateAPImethod.Afterallthis,itwillhandlesignalingandpeerconnections.

Page 398: WebRTC Cookbook

There’smore…Foradditionaldetailsandadvancedexamplesofhowtousethisframework,refertoitshomepageathttp://rtc.io.

Page 399: WebRTC Cookbook
Page 400: WebRTC Cookbook

UsingOpenToktocreateaWebRTCapplicationOpenTokisaproprietaryframeworkthatallowsyoutobuildWebRTC-basedapplicationsusingtheprovidedSDK.Inthisrecipe,wewillbuildasimpledemoapplicationbyutilizingthebasicfeaturesofthetool.

Page 401: WebRTC Cookbook

GettingreadyTousethisframework,youshouldregisterwiththeOpenToksystem,andgetauniquedeveloperAPIID.Tousethissystem,youshouldhavethreekeys:theAPIkey,sessionID,andtoken.Thefollowinginstructionscovertheprocessofcreatingthesekeys:

1. Navigatetohttps://tokbox.com/opentok/andclickonSignUp.2. FilltheformandclickontheSignUpbutton:

3. Checkforane-mailfromOpenTok(TokBox),theywillsendaconfirmatione-mailwiththeAPIkey.WritedowntheAPIkey—thisisthefirstkey.Confirmyourregistrationwiththeirsystembyclickingontheappropriatelinkinthee-mail:

Page 402: WebRTC Cookbook

4. Navigatetohttps://dashboard.tokbox.com—findtheProjectssectionandclickontheViewDetailsbutton:

5. Inthenextpage,youwillseeProjectTools,whereyoucancreateanewsession.DoitbyusingtheCreatebutton:

Page 403: WebRTC Cookbook

6. Rightafterthat,youwillseethegeneratedsessionIDbelowthebutton.Writedownthisvalue—thisisthesecondkey.

7. Afteryou’vecreatedthenewsession,youshouldcreateanewtokenbasedonthissession.AttheGenerateTokensection,clickontheGeneratebutton:

8. Afteryou’veclickedontheGeneratebutton,youwillseeageneratedtokenbelowthebutton,asshowninthefollowingscreenshot:

Page 404: WebRTC Cookbook

9. Writedownthisvalue(generatedtoken)—thisisthethirdkey.

Now,youhaveallthethreekeystoworkwiththeOpenToksystem.

NoteThisframeworkrequiresyoutouseawebserver,soforthisrecipe,youshouldhaveawebserverinstalledandconfigured.

Page 405: WebRTC Cookbook

Howtodoit…Now,whenyouhaveyourAPIID,asessionID,andtwotokens,youcancontinuewiththeprocessofbuildinganapplicationusingOpenTok:

1. CreateanemptyHTMLfile(let’snameitindex.html)andaddthefollowingcode:

<!DOCTYPEhtml>

<html>

<headlang="en">

<metacharset="UTF-8">

<title></title>

2. IncludetheOpenTokcodeinyourproject:

<scriptsrc=

'http://static.opentok.com/webrtc/v2.2/js/opentok.min.js'>

</script>

<scripttype="text/javascript">

3. Inthefollowinglines,youshouldinserttheactualAPIID(APIkey)andsessionID,whichyouhavegeneratedwhilepreparingforthisrecipe:

varapiKey=<YOUR_API_ADI>;

varsessionId=<GENERATED_SESSION_ID>;

4. Asyouremember,wegeneratedtwotokens—oneperclient.Addthefirsttokeninthefollowingvariable:

vartoken=<TOKEN_1>;

5. InitializethesessionbycallingtheOpenTokmethod:

varsession=OT.initSession(apiKey,sessionId);

6. Subscribetoevents:

session.on("streamCreated",function(event){

session.subscribe(event.stream);

});

7. Openanewconnection:

session.connect(token,function(error){

varpublisher=OT.initPublisher();

session.publish(publisher);

});

</script>

</head>

<body>

8. WealsoneedanHTMLobjecttopublishavideothere:

<h1>Awesomevideofeed!</h1>

<divid="myPublisherDiv"></div>

</body>

</html>

Page 406: WebRTC Cookbook

9. Now,savethefileandcreateanotherone(let’snameitindex2.html).Makethesecondfileidenticaltothefirstone.Then,editthesecondfileandchangethetokenvalueinthefollowingline:

vartoken=<TOKEN_2>;

10. Inthesecondfile,youshouldaddthesecondtoken,whichyouhavegeneratedwhilepreparingforthisrecipe.Savethesecondfile.

Now,wehavetwofiles:index.htmlandindex2.html.Theyarebothidentical,exceptfortheirtokenvalue—everyfilecontainsitsowntokenID.Putboththefilesinthewebserver.

Page 407: WebRTC Cookbook

Howitworks…It’stimetotestwhatwe’vedeveloped.

Openawebbrowserandnavigatetotheplacewherethefirstfile(index.html)islocated.Notethatyoushouldnotuseafilesystem,andboththefilesshouldbeaccessibleonthewebserver.Afterthepageisopened,youwillseeanimagefromthewebcamera.

Now,onanothermachine,openawebbrowserandnavigatetothesecondfile(index2.html).Youwillseethesimilarpicture.Inacoupleofseconds,theconnectionwillbeestablishedandyouwillseelocalandremoteimagesonboththemachines.Thefollowingscreenshotrepresentsthiscase:

Inmycase,Ihaveusedthesamemachine,butopenedthefilesintwodifferentwebbrowsers.

OpenToktakescareofsignalingandothertechnicalprocesses.Asyoucansee,theapplicationisverycompact,andthecodeisveryshortandclean.Youdon’tneedtospendtimeoninstallationandmaintenanceofservercomponents,theyareprovidedandtransparentlyservedbytheframework.

Page 408: WebRTC Cookbook

There’smore…WeconsideredjustasimpleexampleofusingOpenTok,butthistoolallowsyoutocreatemorecomplexapplicationswithadvancedfeatures.Fordetails,refertoOpenTok’shomepageathttps://tokbox.com/opentok/.

Page 409: WebRTC Cookbook
Page 410: WebRTC Cookbook

CreatingamultiuserconferenceusingWebRTCOInthisrecipe,wewillcreateasimpleapplicationthatsupportsamultiuservideoconference.WewilldoitusingWebRTCO—anopensourceJavaScriptframeworkfordevelopingWebRTCapplications.

Page 411: WebRTC Cookbook

GettingreadyForthisrecipe,youshouldhaveawebserverinstalledandconfigured.Theapplicationwewillcreatecanworkwhilerunningonthelocalfilesystem,butitismoreconvenienttouseitviathewebserver.

Tocreatetheapplication,wewillusethesignalingserverlocatedontheframework’shomepage.Theframeworkisopensource,soyoucandownloadthesignalingserverfromGitHubandinstallitlocallyonyourmachine.GitHub’spagefortheprojectcanbefoundathttps://github.com/Oslikas/WebRTCO.

Page 412: WebRTC Cookbook

Howtodoit…Thefollowingrecipeisbuiltontheframework’sinfrastructure.Wewillusetheframework’ssignalingserver.Whatweneedtodoisincludetheframework’scodeanddosomeinitializationprocedure:

1. CreateanHTMLfileandaddcommonHTMLheads:

<!DOCTYPEhtml>

<htmllang="en">

<head>

<metacharset="utf-8">

2. Addsomestyledefinitionstomakethewebpagelookingnicer:

<styletype="text/css">

video{

width:384px;

height:288px;

border:1pxsolidblack;

text-align:center;

}

.container{

width:780px;

margin:0auto;

}

</style>

3. Includetheframeworkinyourproject:

<scripttype="text/javascript"src=

"https://cdn.oslikas.com/js/WebRTCO-1.0.0-beta-min.js"charset="utf-8">

</script>

</head>

4. DefinetheonLoadfunction—itwillbecalledafterthewebpageisloaded.Inthisfunction,wewillmakesomepreliminaryinitializingwork:

<bodyonload="onLoad();">

5. DefineHTMLcontainerswherethelocalvideowillbeplaced:

<divclass="container">

<videoid="localVideo"></video>

</div>

6. Defineaplacewheretheremotevideowillbeadded.Notethatwedon’tcreateHTMLvideoobjects,andwejustdefineaseparatediv.Further,videoobjectswillbecreatedandaddedtothepagebytheframeworkautomatically:

<divclass="container"id="remoteVideos"></div>

<divclass="container">

7. Createthecontrolsforthechatarea:

<divid="chat_area"style="width:100%;height:250px;overflow:auto;

Page 413: WebRTC Cookbook

margin:0auto0auto;border:1pxsolidrgb(200,200,200);background:

rgb(250,250,250);"></div>

</div>

<divclass="container"id="div_chat_input">

<inputtype="text"class="search-query"placeholder="chathere"

name="msgline"id="chat_input">

<inputtype="submit"class="btn"id="chat_submit_btn"

onclick="sendChatTxt();"/>

</div>

8. Initializeafewvariables:

<scripttype="text/javascript">

varvideoCount=0;

varwebrtco=null;

varparent=document.getElementById('remoteVideos');

varchatArea=document.getElementById("chat_area");

varchatColorLocal="#468847";

varchatColorRemote="#3a87ad";

9. Defineafunctionthatwillbecalledbytheframeworkwhenanewremotepeerisconnected.Thisfunctioncreatesanewvideoobjectandputsitonthepage:

functiongetRemoteVideo(remPid){

varvideo=document.createElement('video');

varid='remoteVideo_'+remPid;

video.setAttribute('id',id);

parent.appendChild(video);

returnvideo;

}

10. CreatetheonLoadfunction.Itinitializessomevariablesandresizesthecontrolsonthewebpage.Notethatthisisnotmandatory,andwedoitjusttomakethedemopagelooknicer:

functiononLoad(){

vardivChatInput=document.getElementById("div_chat_input");

vardivChatInputWidth=divChatInput.offsetWidth;

varchatSubmitButton=

document.getElementById("chat_submit_btn");

varchatSubmitButtonWidth=chatSubmitButton.offsetWidth;

varchatInput=document.getElementById("chat_input");

varchatInputWidth=divChatInputWidth-chatSubmitButtonWidth

-40;

chatInput.setAttribute("style","width:"+chatInputWidth+

"px");

chatInput.style.width=chatInputWidth+'px';

varlv=document.getElementById("localVideo");

11. CreateanewWebRTCOobjectandstarttheapplication.Afterthispoint,theframeworkwillstartsignalingconnection,getaccesstotheuser’smedia,andwillbereadyforincomeconnectionsfromremotepeers:

webrtco=newWebRTCO('wss://www.webrtcexample.com/signalling',lv,

OnRoomReceived,onChatMsgReceived,getRemoteVideo,OnBye);

};

Page 414: WebRTC Cookbook

Here,thefirstparameterofthefunctionistheURLofthesignalingserver.Inthisexample,weusedthesignalingserverprovidedbytheframework.However,youcaninstallyourownsignalingserveranduseanappropriateURL.ThesecondparameteristhelocalvideoobjectID.Then,wewillsupplyfunctionstoprocessmessagesofreceivedroom,receivedmessage,andreceivedremotevideostream.Thelastparameteristhefunctionthatwillbecalledwhensomeoftheremotepeershavebeendisconnected.

12. Thefollowingfunctionwillbecalledwhentheremotepeerhasclosedtheconnection.Itwillremovevideoobjectsthatbecameoutdated:

functionOnBye(pid){

varvideo=document.getElementById("remoteVideo_"+pid);

if(null!==video)video.remove();

};

13. WealsoneedafunctionthatwillcreateaURLtosharewithotherpeersinordertomakethemabletoconnecttothevirtualroom.Thefollowingpieceofcoderepresentssuchafunction:

functionOnRoomReceived(room){

addChatTxt("Now,ifsomebodywantstojoinyou,shouldusethis

link:<ahref=\""+window.location.href+"?

room="+room+"\">"+window.location.href+"?room="+room+"

</a>",chatColorRemote);

};

14. Thefollowingfunctionprintssometextinthechatarea.WewillalsouseittoprinttheURLtosharewithremotepeers:

functionaddChatTxt(msg,msgColor){

vartxt="<fontcolor="+msgColor+">"+getTime()+msg+"

</font><br/>";

chatArea.innerHTML=chatArea.innerHTML+txt;

chatArea.scrollTop=chatArea.scrollHeight;

};

15. Thenextfunctionisacallbackthatiscalledbytheframeworkwhenapeerhassentusamessage.Thisfunctionwillprintthemessageinthechatarea:

functiononChatMsgReceived(msg){

addChatTxt(msg,chatColorRemote);

};

16. Tosendmessagestoremotepeers,wewillcreateanotherfunction,whichisrepresentedinthefollowingcode:

functionsendChatTxt(){

varmsgline=document.getElementById("chat_input");

varmsg=msgline.value;

addChatTxt(msg,chatColorLocal);

msgline.value='';

webrtco.API_sendPutChatMsg(msg);

};

Page 415: WebRTC Cookbook

17. Wealsowanttoprintthetimewhileprintingmessages;sowehaveaspecialfunctionthatformatstimedataappropriately:

functiongetTime(){

vard=newDate();

varc_h=d.getHours();

varc_m=d.getMinutes();

varc_s=d.getSeconds();

if(c_h<10){c_h="0"+c_h;}

if(c_m<10){c_m="0"+c_m;}

if(c_s<10){c_s="0"+c_s;}

returnc_h+":"+c_m+":"+c_s+":";

};

18. Wehavesomehelpercodetomakeourlifeeasier.Wewilluseitwhileremovingobsoletevideoobjectsafterremotepeersaredisconnected:

Element.prototype.remove=function(){

this.parentElement.removeChild(this);

}

NodeList.prototype.remove=HTMLCollection.prototype.remove=

function(){

for(vari=0,len=this.length;i<len;i++){

if(this[i]&&this[i].parentElement){

this[i].parentElement.removeChild(this[i]);

}

}

}

</script>

</body>

</html>

Now,savethefileandputitonthewebserver,whereitcouldbeaccessiblefromwebbrowser.

Page 416: WebRTC Cookbook

Howitworks…Openawebbrowserandnavigatetotheplacewherethefileislocatedonthewebserver.Youwillseeanimagefromthewebcameraandachatareabeneathit.Atthisstage,theapplicationhascreatedtheWebRTCOobjectandinitiatedthesignalingconnection.Ifeverythingisgood,youwillseeanURLinthechatarea.OpenthisURLinanewbrowserwindoworonanothermachine—theframeworkwillcreateanewvideoobjectforeverynewpeerandwilladdittothewebpage.

Thenumberofpeersisnotlimitedbytheapplication.Inthefollowingscreenshot,Ihaveusedthreepeers:twowebbrowserwindowsonthesamemachineandanotebookasthethirdpeer:

Usingthisframework,youcanattainyourownsignalingserveroryoucanusetheonethatisprovidedbythetool.

Page 417: WebRTC Cookbook

There’smore…Fornow,thetoolsupportsbasicWebRTCfeaturesanditisinthebetastage.WebRTCOisunderdevelopmentanditmightbeimprovedinthefuture.

Fordetailsonthisframework,refertoitshomepageathttps://www.oslikas.com/.

SourcecodesandexamplescanbefoundontheGitHubpageathttps://github.com/Oslikas/WebRTCO.

Moreexamplescanbefoundonthedemopage,http://www.webrtcexample.com.

Page 418: WebRTC Cookbook
Page 419: WebRTC Cookbook

Chapter8.AdvancedFunctionsInthischapter,wewillcoverthefollowingtopics:

Visualizingamicrophone’ssoundlevelMutingamicrophonePausingavideoTakingascreenshotStreamingmedia

Page 420: WebRTC Cookbook

IntroductionThischaptercoversadvancedexamplesofusingWebRTCfeatures.Thefollowingrecipesallowyoutoimproveyourapplication’susabilityandmakeitfriendlierbyaddingadvancedfeaturesandfunctionality.

AlltherecipesinthischapterareorientedontheclientsideandimplementedinJavaScript.Someofthemappeartobeprettysimpleandothersmightbemorecomplex,butthemainpurposeoftheserecipesistomaketheapplicationmoreadaptabletoreallifeandfriendlyforcustomers.

Page 421: WebRTC Cookbook
Page 422: WebRTC Cookbook

Visualizingamicrophone’ssoundlevelIfyourapplicationworkswithaudioandvideo(forexample,you’redevelopingavideoconferencingservice),itwouldbeprobablyagoodideatoaddaliveindicationofthemicrophonesoundlevel.Usingthisfeature,peerscanestimateandcontroltheirmicrophone’saudiolevels.So,inthisrecipe,we’reimplementingmicrophoneactivityindication.

Page 423: WebRTC Cookbook

GettingreadyThisrecipeissimple,andyouwilljustneedatexteditortocreateandeditHTML.Totestthisrecipe,youshouldhaveawebserverinstalledandconfigured—itishighlyrecommendedtotesttheexampleviaawebserverratherthanjustonalocalfilesystem;otherwise,thewebbrowsermightblockcallstotheWebRTCAPI.

Page 424: WebRTC Cookbook

Howtodoit…Performthefollowingsteps:

1. CreateanHTMLfileandinsertthefollowingcodes.Notethattheimportantplacesarecommentedinline:

<!DOCTYPEhtml>

<html>

<headlang="en">

<metacharset="UTF-8">

2. IncludetheWebRTCadapterfromGoogle.Thisfileallowsyoutouseuniversalfunctionnamesinallsupportedwebbrowsers:

<scriptsrc=

"https://rawgit.com/GoogleChrome/webrtc/master/samples/web/js/adapter.j

s"></script>

</head>

<body>

3. CreateasimpleHTMLelementtodisplayalocalvideofromawebcamera:

<div><videowidth="384"id="lVideo"muted="true"autoplay="true">

</video></div>

4. Createacanvaselement—here,wewillrepresentthemicrophone’ssoundlevel:

<canvaswidth="384"height="20"id="micecanvas"style="background-

color:white;"></canvas>

<scripttype="text/javascript">

Thefollowingfunctiongetsaccesstousermedia:

functioninit(){

varconstraints={"audio":true,"video":{"mandatory":{},

"optional":[]}};

getUserMedia(constraints,onUserMediaSuccess,

onUserMediaError);

}

5. Weneedtohandleerrors,soasimpleerrorhandlerfunctioncanbefoundinthefollowingcode:

functiononUserMediaError(error){

console.log("Error:"+error);

}

Thefollowingcallbackfunctionwillbecalledaftertheapplicationhasaccesstotheusermedia:

functiononUserMediaSuccess(stream){

6. Toattachamediastreamtothevideocontrol,usethefollowingcode:

varlocalVideo=document.getElementById("lVideo");

attachMediaStream(localVideo,stream);

Page 425: WebRTC Cookbook

7. Setupafunctionaliastomakethisworkunderdifferentsupportedbrowsers:

window.AudioContext=window.AudioContext||

window.webkitAudioContext||window.mozAudioContext;

8. Initializethelocalvariablesandgetaccesstothemicrophone:

varaudioContext=newAudioContext();

varanalyser=audioContext.createAnalyser();

varmicrophone=

audioContext.createMediaStreamSource(stream);

9. Assignascriptprocessortotheaudiocontext.Byusingthescriptprocessor,wewillbeabletoprocessaudiodataandcalculatemicrophoneactivitylevel:

varjavascriptNode=

audioContext.createScriptProcessor(2048,1,1);

analyser.smoothingTimeConstant=0.3;

analyser.fftSize=1024;

microphone.connect(analyser);

analyser.connect(javascriptNode);

javascriptNode.connect(audioContext.destination);

varcanvasContext=

document.getElementById("micecanvas").getContext("2d");

10. Setupanaudiodataprocessingfunction—here,wewilldoallthecalculations:

javascriptNode.onaudioprocess=function(){

vararray=new

Uint8Array(analyser.frequencyBinCount);

analyser.getByteFrequencyData(array);

varvalues=0;

varlength=array.length;

for(vari=0;i<length;i++){

values+=array[i];

}

11. Calculatetheaveragesoundlevelvalueanddrawitonthecanvas:

varaverage=values/length;

canvasContext.clearRect(0,0,384,20);

canvasContext.fillStyle='red';

canvasContext.fillRect(0,0,average,20);

}

}

12. Thefollowingfunctionstartstheapplication:

init();

</script>

</body>

</html>

13. Now,savethefileandputitonthewebserver,makingitaccessiblethroughacertainURL.

14. NavigatetotheURL.Youwillseetheimagefromyourwebcamera,andashorthorizontalredbarbeneathit.Youwilljustseethelocalvideobecausewehaven’t

Page 426: WebRTC Cookbook

implementedaninterconnectionwithremotepeers.15. Now,talkthroughthemicrophoneandmakesomenoise—thebarwillrespondtothe

soundbychangingitslengthandtrembling.Thisbarrepresentsthemicrophone’ssoundactivitylevelandyoucanestimateitvisually.

Page 427: WebRTC Cookbook

Howitworks…UsingWebRTCAPI,wewillcreatetheaudiocontextandaudioanalyzerobjects.Then,wewillgetaccesstothemicrophone.WewillalsocreateScriptProcessorwithabufferof2048bytes,andoneinputandoneoutputchannel.UsingthefftSizeattributeoftheanalyzer,wewillsetthesizeoftheFastFourierTransform(FFT)bufferto1024.Wewillconnecttheanalyzerandthescriptprocessor,andthen,wewillsetuptheonaudioprocesshandlerfunction.Now,approximatelyevery0.3seconds,wewillgetasignalfromthebrowsertoourhandlerfunctionwhereweusereceiveddatatocalculatethesoundvolumeandtodrawitonthebar.

Page 428: WebRTC Cookbook

SeealsoRegardingdetailedexplanationsofthepossibleusageoftheaudioAPI,youcanrefertoitsofficialdocumentationathttp://webaudio.github.io/web-audio-api/

Page 429: WebRTC Cookbook
Page 430: WebRTC Cookbook

MutingamicrophoneUsually,voicecallingsoftwarehasamicrophonemutingfeature.So,youcanenableordisableyourmicrophoneduringthecall,decidingwhethertheremotepeershouldhearyourvoiceornot.Inthisrecipe,wewillimplementsuchafeatureforaWebRTCapplication.

Page 431: WebRTC Cookbook

GettingreadyForthisexample,youdon’tneedanypreliminaryspecificsteps.Useyourdevelopmentenvironmentasyouusuallydo.

Page 432: WebRTC Cookbook

Howtodoit…Followthesesteps:

1. Forthisfeature,youneedtoaddabuttonelementtoyourHTMLpage.Thisbuttonwillenableordisablethemicrophone:

<buttonid="mute_btn"onclick="muteBtnClick()">MuteMic</button>

2. Youalsoneedtosetupahandlerfortheonclickeventoftheelement—itwilldotheactualwork.Thefollowingcodeisanexampleofsuchahandler:

functionmuteBtnClick(){

3. Wewillupdateourbuttonwiththemicrophonestate,soweneedtogetthebuttonID:

varbtn=document.getElementById("mute_btn");

4. Beforewecandecidewhetherwewanttomuteorunmutethemicrophone,weshouldbeabletoknowitsactualstate—forthispurpose,wewillusetheisMicMutedfunction:

if(isMicMuted()){

5. Ourmicrophoneismuted,sowewanttounmuteitandupdatethebuttonwiththeappropriatestate:

muteMic(false);

btn.innerHTML="MuteMic";

}else{

6. Themicrophoneisunmuted,sowewillmuteitandupdatethebuttonaswell:

muteMic(true);

btn.innerHTML="UnmuteMic";

}

}

7. Inthehandler,wewillusetheisMicMutedfunctiontodetectwhetherthemicrophoneismuted.Let’simplementthisfunctionaswell:

functionisMicMuted(){

return!(localStream.getAudioTracks()[0].enabled);}

8. NotethattheWebRTCAPIcanletusknowwhethertheaudiotrackisenabled,butourfunctionreturnsthemicrophone’smutedvalue.So,wewillinverttheenabledvaluereceivedfromWebRTCstack.

9. Finally,weneedtoimplementtheactualmute/unmutefunction:

functionmuteMic(mute){

localStream.getAudioTracks()[0].enabled=!mute;

};

10. Here,localStreamisavariablethatcontainsalocalstreamobjectreceivedafterasuccessfulcallofthegetUserMediaWebRTCAPIfunction.

Page 433: WebRTC Cookbook

NoteInthisfunction,wewillsetuptheenabledvalue,butthefunctiongetstheshouldImutethemicrophoneparameter.Ifthisfunctiongetstrueasanargument,itshouldsetfalsetotheenabledpropertyoftheaudiotrack.Thisiswhywewillinvertthevalueagain,aswedoitintheisMicMutedfunction.

Page 434: WebRTC Cookbook

Howitworks…Themainideaistogetanappropriateaudiotrackofthelocalmediastream,andtochangeitsstatetodisabledorenabled.Inthefirstcase,thetrackwillbemutedandtheremotepeerwillnothearyourvoice.Changingthestatecanbedoneinrealtime.

Page 435: WebRTC Cookbook

There’smore…Ifyouhavemorethanoneaudiodevice,thegetAudioTracksfunctionmightreturnseveralaudiotracksanditmightbenecessarytogooverallofthem:

varaudiotracks=localStream.getAudioTracks();

for(vari=0,l=audiotracks.length;i<l;i++)

{

audiotracks[i].enabled=false;

}

Page 436: WebRTC Cookbook

SeealsoRefertothePausingavideorecipetoseeasimilartechniqueappliedtovideostreams

Page 437: WebRTC Cookbook
Page 438: WebRTC Cookbook

PausingavideoIfyou’reparticipatinginavideoconferencecall,youmightwanttotemporarilyswitchyourvideocameraoffandtakeapause.Duringthistime,yourremotepeershouldn’tseeanimagefromyourcamera.Inmostvideoconferencingsoftware,youcanenableordisableyourcameraduringthecall.Inthisrecipe,wewillimplementthisfeatureforaWebRTCapplication.

Page 439: WebRTC Cookbook

GettingreadyForthisrecipe,youdon’tneedanyspecificpreparations.JustcreateabasicconferencingWebRTCapplication.

Page 440: WebRTC Cookbook

Howtodoit…Performthefollowingsteps:

1. WeneedtoaddaPauseVideobuttontotheapplication’swebpage:

<buttonid="pause_video_btn"onclick="pauseVideoBtnClick()">Pause

Video</button>

2. Youalsoshouldsetupahandlerfortheonclickeventofthebutton:

functionpauseVideoBtnClick(){

3. Wewillupdateourbuttonwiththevideostreamstate(whetheritispausedornot),soweneedtogetthebuttonID:

varbtn=document.getElementById("pause_video_btn");

4. Beforewedecidewhetherweshouldpausethestreamorstartplayingitbackagain,weshouldbeabletoknowitscurrentstate—forthispurpose,wewillusetheisVideoPausedfunction:

if(isVideoPaused()){

5. Ifthevideostreamispaused,wewanttostartplayingitbackandupdatethebuttonwiththenewstate,thenusethefollowingcode:

pauseVideo(false);

btn.innerHTML="PauseVideo";

}else{

6. Incasethevideoisstreaming,wewillpauseitandupdatethebuttonaswell:

pauseVideo(true);

btn.innerHTML="StreamVideo";

}

}

7. Inthehandler,wewillusetheisVideoPausedfunctiontodetectwhetherthevideostreamispaused.Let’simplementthisfunctionaswell:

functionisVideoPaused(){

return!(localStream.getVideoTracks()[0].enabled);

}

8. NotethattheWebRTCAPIcanletusknowifacertainvideotrackisenabledornot,butourfunctionreturnstheisthevideopausedstate.So,wewillinverttheenabledvaluereceivedfromtheWebRTCstack.

9. Finally,weneedtoimplementthefunctionthatactuallyputsthevideoonpauseandviceversa:

functionpauseVideo(pause){

localStream.getVideoTracks()[0].enabled=!pause;

};

10. Here,localStreamisavariablethatcontainsalocalstreamobjectreceivedaftera

Page 441: WebRTC Cookbook

successfulcallofthegetUserMediaWebRTCAPIfunction.

NoteInthisfunction,wewillsetuptheenabledvalue,butthefunctiongetstheshouldIputthevideoonpauseparameter.So,ifitgetstrueasanargument,itshouldsettheenabledpropertyofthevideotracktofalse.

Page 442: WebRTC Cookbook

Howitworks…Therootideaofthedescribedsolutionistogetanappropriatevideotrackofthelocalmediastreamandtochangeitsstatetodisabledorenabled.Inthefirstcase,thevideotrackwillbepaused,streamingwillbestopped,andtheremotepeerwillnotseeyou.Changingthestatecanbedoneinrealtime.

Page 443: WebRTC Cookbook

SeealsoRefertotheMutingamicrophonerecipeforadditionaldetailsregardingtheusageofthissolutiontoworkwithaudiotracks

Page 444: WebRTC Cookbook
Page 445: WebRTC Cookbook

TakingascreenshotSometimes,itcanbeusefultobeabletotakescreenshotsfromavideoduringvideoconferencing.Inthisrecipe,wewillimplementsuchafeature.

Page 446: WebRTC Cookbook

GettingreadyNospecificpreparationisnecessaryforthisrecipe.YoucantakeanybasicWebRTCvideoconferencingapplication.WewilladdsomecodetotheHTMLandJavaScriptpartsoftheapplication.

Page 447: WebRTC Cookbook

Howtodoit…Followthesesteps:

1. Firstofall,addimageandcanvasobjectstothewebpageoftheapplication.Wewillusetheseobjectstotakescreenshotsanddisplaythemonthepage:

<imgid="localScreenshot"src="">

<canvasstyle="display:none;"id="localCanvas"></canvas>

2. Next,youhavetoaddabuttontothewebpage.Afterclickingonthisbutton,theappropriatefunctionwillbecalledtotakethescreenshotfromthelocalstreamvideo:

<buttononclick="btn_screenshot()"id="btn_screenshot">Makea

screenshot</button>

3. Finally,weneedtoimplementthescreenshottakingfunction:

functionbtn_screenshot(){

varv=document.getElementById("localVideo");

vars=document.getElementById("localScreenshot");

varc=document.getElementById("localCanvas");

varctx=c.getContext("2d");

4. Drawanimageonthecanvasobject—theimagewillbetakenfromthevideoobject:

ctx.drawImage(v,0,0);

5. Now,takereferenceofthecanvas,convertittotheDataURLobject,andinsertthevalueintothesrcoptionoftheimageobject.Asaresult,theimageobjectwillshowusthetakenscreenshot:

s.src=c.toDataURL('image/png');

}

6. Thatisit.Savethefileandopentheapplicationinawebbrowser.Now,whenyouclickontheMakeascreenshotbutton,youwillseethescreenshotintheappropriateimageobjectonthewebpage.Youcansavethescreenshottothediskusingright-clickandthepop-upmenu.

Page 448: WebRTC Cookbook

Howitworks…Weusethecanvasobjecttotakeaframeofthevideoobject.Then,wewillconvertthecanvas’datatoDataURLandassignthisvaluetothesrcparameteroftheimageobject.Afterthat,animageobjectisreferredtothevideoframe,whichisstoredinthecanvas.

Page 449: WebRTC Cookbook

SeealsoRefertotheVisualizingamicrophone’ssoundlevelandMutingamicrophonerecipesforexamplesregardinghowtoworkwithaudiodata

Page 450: WebRTC Cookbook
Page 451: WebRTC Cookbook

StreamingmediaThisrecipecoversanotherinterestingfeaturethatcanbeimplementedusingtheWebRTCstack:streamingprerecordedmediafromonepeertoanotherone.

Page 452: WebRTC Cookbook

GettingreadyWewillstreamaprerecordedWebMfile,soyouneedtohaveone.YoucandownloaddemoWebMfilesfromtheInternet.Forexample,fromhttp://www.webmfiles.org/demo-files/.

Inthisrecipe,wewillcreatetwofiles:anHTMLpageandaJavaScriptlibrary.

NoteThisfeaturedoesn’tworkonthelocalfilesystem.Toimplementthisfeature,youneedtohaveawebserverwhereyoucanplacealltheapplicationfiles,andwheretheapplicationisaccessibletothecustomer.

Asignalingserverisalsonecessaryforthisrecipe.YoucanusetheserverfromChapter1,PeerConnections.

Page 453: WebRTC Cookbook

Howtodoit…Openyourtexteditor,andlet’screatetheHTMLpagebyfollowingthegivensteps:

1. MakeasimpleHTMLheader:

<!DOCTYPEhtml>

<html>

<head>

<title>MyWebRTCfilemediastreamingdemo</title>

2. Addsomestyleforthevideocomponent:

<styletype="text/css">

video{

width:384px;

height:288px;

border:1pxsolidblack;

text-align:center;

}

</style>

3. IncludeaJavaScriptlibrarythatwewillwriteatthenextstage:

<scripttype="text/javascript"src="myrtclib.js"></script>

4. IncludeGoogle’sadaptertokeepcross-browsercompatibility:

<script

src="https://rawgit.com/GoogleChrome/webrtc/master/samples/web/js/adapt

er.js"></script>

</head>

<body>

5. Creatediv,whereaconnectionlinkwillbepublishedforpeers:

<divid="status"></div><br>

6. Createavideoelement.Thiselementwillshowthemediastreamedfromtheremotepeer:

<div><videoid="remotevideo"autoplay="true"controls="true"></video>

</div>

7. Createafilechoosingcomponentandabuttonthatwillstartthestreamingprocess:

<div>

fileyouwanttostream<inputtype="file"id="files"

name="files[]"/>thenpress<buttononclick="onSendBtnClick()">Start

streaming!</button>

</div>

<script>

varfilelist;

8. Checkwhetherthewebbrowsersupportscomponentsandtechnologiesthatweuseforthisfeature:

Page 454: WebRTC Cookbook

if(window.File&&window.FileReader&&window.FileList&&

window.Blob){

document.getElementById('files').addEventListener('change',

handleFileSelect,false);

9. ConnecttothesignalingserverandinitializeourWebRTClibrary.NotethatyoushoulduseanactualIPandportofthesignalingserverwhereitisrunningonyourmachine.Bydefault,theyare127.0.0.1and30001,asimplementedintheappropriaterecipesofChapter1,PeerConnections,whereweconsideredsignalingservers:

myrtclibinit("ws://127.0.0.1:30001",

document.getElementById("remotevideo"));

}else{

10. Createanalertforinstanceswhenthewebbrowserdoesn’tsupportnecessarytechnologies:

alert('TheFileAPIsarenotfullysupportedinthis

browser.');

}

11. Implementafunctionthathandlesthefilechoosingcomponent:

functionhandleFileSelect(evt){

filelist=evt.target.files;

};

12. Implementafunctionthatstartsthestreamingprocess.NotethatthedoStreamMediafunctionisimplementedintheJavaScriptlibrarythatwillbeconsideredinthenextstage:

functiononSendBtnClick(){

doStreamMedia(filelist[0]);

};

13. Implementacallbackfunctionthatconstructsaconnectionlinkandpublishesitonthewebpage:

functiononRoomReceived(room){

varst=document.getElementById("status");

st.innerHTML="Now,ifsomebodywantstojoinyou,shoulduse

thislink:<ahref=\""+window.location.href+"?

room="+room+"\">"+window.location.href+"?room="+room+"</a>";

};

</script></body></html>

Next,youneedtocreateaJavaScriptlibrarythatisusedintheHTMLpagewejustcreated.Mostofthecodeissimpleandidenticaltotheappropriatepartsoftherecipesfromotherchapters.Here,wewillcoveronlyspecificmomentsthatareimportantinthescopeofthefeature;knownpiecesofcodewillbeskipped.Notethatthefullsourcecodeforthisrecipeissuppliedalongwiththisbook.

ThisexampleactivelyusesWebRTCdatachannels,soyoucanrefertotheImplementingachatusingdatachannelsrecipefromChapter1,PeerConnections,formoredetailson

Page 455: WebRTC Cookbook

thistopic.Performthefollowingstepsforusingdatachannels:

1. Declareachunksize.Whilestreamingtheprerecordedmedia,theapplicationreadsthemediafilechunkbychunkandsendsittotheremotepeer.So,wehavetodeclarethechunksizevalue—1024,inthisparticularcase.Youcanplaywithothervaluesandseehowtheyaffectthedemo.Don’tusetoolowortoohighvalues:

varchunkSize=1024;

2. Declarevariablesthatwillhandlebufferandmediasource.Thebufferisastructurethathandlesrawmediadataontheclientside(wherethemediawillbestreamed).ThemediasourcerepresentsaWebRTCobjectthatwillbetiedwithavideoHTMLobject:

varreceiverBuffer=null;

varrecvMediaSource=null;

3. DeclareavariablethatwillhandletheHTMLvideoobjectwherethestreamedmediawillbeshown:

varremoteVideo=null;

4. Declareanarray.Thiswillbeusedasacachetotemporarilystorethereceivedchunksincasetheremotepeersendsthemfasterthanwecandrawthemonthevideo:

varqueue=[];

5. ThefollowingcodeisusedforcompatibilitybetweenFirefoxandChrome:

window.MediaSource=window.MediaSource||

window.WebKitMediaSource;

6. Establishanewpeer-to-peerdatachannel:

functioncreateDataChannel(role){

try{

data_channel=

pc.createDataChannel("datachannel_"+room+role,null);

}catch(e){

console.log('errorcreatingdatachannel'+e);

return;

}

initDataChannel();

}

7. Whilesettingasessiondescription,removebandwidthlimitations.Somewebbrowsers(forexample,someversionsofChrome)limitbandwidth,soconnectionperformancemightdegrade.Toavoidthat,wewillcallourcustomsetBandwidthfunction,whichremovessuchlimitations:

functionsetLocalAndSendMessage(sessionDescription){

sessionDescription.sdp=setBandwidth(sessionDescription.sdp);

pc.setLocalDescription(sessionDescription,function(){},

failureCallback);

Page 456: WebRTC Cookbook

sendMessage(sessionDescription);

};

8. ImplementthesetBandwidthfunction.Itsetsthebandwidthlimittoahighervalueinsteadofthedefaultone,whichmightbesetbythebrowser:

functionsetBandwidth(sdp){

sdp=sdp.replace(/a=mid:data\r\n/g,

'a=mid:data\r\nb=AS:1638400\r\n');

returnsdp;

}

9. ChangetheonReceiveMessageCallbackfunction,adoptingitforthenewfeature.YoushouldbefamiliarwiththisfunctionfromChapter1,PeerConnections.

functiononReceiveMessageCallback(event){

try{

varmsg=JSON.parse(event.data);

if(msg.type==='chunk'){

onChunk(msg.data);

}

}

catch(e){}

};

10. Declaretheauxiliaryvariablesforslicingthemediafile:

varstreamBlob=null;

varstreamIndex=0;

varstreamSize=0;

11. ImplementafunctionthatiscalledfromtheHTMLpage.Thisfunctionreadsthemediafile,slicesitintochunks,andsendsthemtotheremotepeer:

functiondoStreamMedia(fileName){

varfileReader=newwindow.FileReader();

fileReader.onload=function(e){

streamBlob=newwindow.Blob([new

window.Uint8Array(e.target.result)]);

streamSize=streamBlob.size;

streamIndex=0;

streamChunk();

};

fileReader.readAsArrayBuffer(fileName);

}

functionstreamChunk(){

if(streamIndex>=streamSize)sendDataMessage({end:true});

varfileReader=newwindow.FileReader();

fileReader.onload=function(e){

varchunk=newwindow.Uint8Array(e.target.result);

streamIndex+=chunkSize;

pushChunk(chunk);

window.requestAnimationFrame(streamChunk);

};

fileReader.readAsArrayBuffer(streamBlob.slice(streamIndex,

streamIndex+chunkSize));

}

Page 457: WebRTC Cookbook

12. Implementafunctiontoreceivemediadata.Thisfunctioninitializesthemediasourceandbufferobjects,andpreparestoreceivemediachunksthataresentbytheremotepeer:

functiondoReceiveStreaming(){

recvMediaSource=newMediaSource();

remoteVideo.src=window.URL.createObjectURL(recvMediaSource);

recvMediaSource.addEventListener('sourceopen',function(e){

remoteVideo.play();

13. WewillusetheWebMmediafile,soweshouldsetanappropriatemediatypeforthemediabuffer:

receiverBuffer=

recvMediaSource.addSourceBuffer('video/webm;codecs="vorbis,vp8"');

receiverBuffer.addEventListener('error',function(e){

console.log('error:'+receiverBuffer.readyState);});

receiverBuffer.addEventListener('abort',function(e){

console.log('abort:'+receiverBuffer.readyState);});

receiverBuffer.addEventListener('update',function(e){

if(queue.length>0&&!receiverBuffer.updating)

doAppendStreamingData(queue.shift());

});

console.log('mediasourcestate:',this.readyState);

doAppendStreamingData(queue.shift());

},false);

recvMediaSource.addEventListener('sourceended',function(e){

console.log('sourceended:'+this.readyState);});

recvMediaSource.addEventListener('sourceclose',function(e){

console.log('sourceclose:'+this.readyState);});

recvMediaSource.addEventListener('error',function(e){

console.log('error:'+this.readyState);});

};

14. Thefollowingfunctionactuallyputsthemediadataintothemediabuffer:

functiondoAppendStreamingData(data){

varuint8array=newwindow.Uint8Array(data);

receiverBuffer.appendBuffer(uint8array);

};

15. Implementafunctionthatwillstopplayingbackthemediawhenthemediadataisover:

functiondoEndStreamingData(){

recvMediaSource.endOfStream();

};

16. Createafunctiontosendmediadatachunkstotheremotepeer.WewillusetheJSONformatforsuchmessagestodeclaretypeanddatafields:

functionpushChunk(data){

varmsg=JSON.stringify({"type":"chunk","data":

Array.apply(null,data)});

sendDataMessage(msg);

};

Page 458: WebRTC Cookbook

17. Implementafunctionthattakesthereceivedchunksandprocessesthem:

functiononChunk(data){

18. WewillputthefirstchunkintoacacheandcallthedoReceiveStreamingfunctiontopreparemediacomponents:

chunks++;

if(chunks==1){

console.log("firstframe");

queue.push(data);

doReceiveStreaming();

return;

}

if(data.end){

console.log("lastframe");

doEndStreamingData();

return;

}

19. Incasethecache(queue)isnotemptyalready,wewillputthenewlyreceivedchunkinthequeue.That’sbecauseanon-emptyqueuemeansthatwe’rereceivingnewchunksfasterthanwecanprocessandshowthem:

if(receiverBuffer.updating||queue.length>0)

queue.push(data);

20. Incasethequeueisempty,wecancallthedoAppendStreamingDatafunctionthatwillputthechunkinthemediabuffer,andthemediadatawillbeshownonthepage:

elsedoAppendStreamingData(data);

};

So,youhavetheindexpageandtheJavaScriptlibrarynow.Putthembothinthewebserverfolder,andstartthesignalingserver.Navigateyourwebbrowsertowherethedemoisaccessible.Thennavigateanotherwebbrowser(orwebbrowsertab)tothelinkatthetopofthepage;afterthis,peerswillestablishadirectconnection.

Atthebottompartofthepage,youshouldseesomethingsimilartothefollowing:

Page 459: WebRTC Cookbook

NotethebuttonsChooseFileandStartstreaming!.ClickontheChooseFilebuttonandselectthepreloadedWebMmediafile.Then,clickontheStartstreaming!button.Thewebbrowserwhereyouclickedthebuttonswillstartreadingthemediafileandstreamingittothesecondbrowser.So,onanotherbrowserwindow,youshouldseeyourmediafileplaying.

Inthefollowingscreenshot,youcanseetwobrowserwindows:ChromeatthetopandFirefoxattheback.Here,I’mstreamingthemediafilefromChrometoFirefox.

Page 460: WebRTC Cookbook

Notethatthisfeatureisinthebetastage,andyoumightneedtomakeappropriatechangestomakethedemoworkonotherbrowserversions.

AnotherimportantnoteisthatFirefoxhasdisabledthemediasourcecomponentbydefault,soyoushouldcheckthatandenableitbeforeusingthisrecipewithFirefox.Todothat,youshouldnavigatetoabout:config,lookforthemedia.mediasource.enabledoptionandsetittotrue.Youcanseethissolutioninthefollowingscreenshot:

NotethatFirefoxstartsplayingimmediatelyafteritgetsthefirstbytesofthemediadata.

Page 461: WebRTC Cookbook

Chromewillwaituntilitgetsallthemediadataandonlythenwillstartplayingthem.Thisbehaviormightbechangedinotherbrowserversions.

Page 462: WebRTC Cookbook

Howitworks…Thelogicofthisfeatureissimple.Firstofall,peersestablishadirectconnectionandcreatedatachannel.Then,thesender(streamingpeer)actsasshowninthefollowingsteps:

1. ReadsthewholemediafileinthememoryandcreatesaBLOBobject.2. ReadstheBLOBobjectchunkbychunk,slicesthemintosmallerblocks.3. SendstheBLOBobjectchunkbychunktotheremotepeer.4. Repeatsstep3untiltheendofthemediafile.

Ontheotherhand,anotherpeerperformsthefollowingsteps:

1. Createsamediasourceobject.Preparesmediabuffer.TiestheobjectswiththevideoHTMLobjectonthepage.

2. Getschunksfromtheremotepeerandputsbinarydatainthemediabuffer,whichistiedtothevideoobject.

3. Incasethestreamersendsdatafasterthanthereceivercanprocessit,thereceiverusesaqueuetotemporarilystorethereceivedmediadata.

4. Repeatssteps2and3untilthereissomemediadatareceivedfromtheremotepeer.

Thus,thereceiverplaysbackthevideothatisstreamedbytheremotepeer.

Page 463: WebRTC Cookbook

SeealsoThisrecipeactivelyusesWebRTCdatachannels.Inthecode,weconsideredonlystreaming-relatedimportantpartsofcode.Forcodesspecifictodatachannels,refertoChapter1,PeerConnections,wherethistopicisexplainedinamoredetailedway.

Page 464: WebRTC Cookbook

IndexA

AndroidDeveloperTools(ADT)/InstallingAndroidDeveloperToolsAndroidVirtualDevice(AVD)tool/RunningontheAndroidsimulatorApache

configuring/ConfiguringApacheapplication

creating,RTCMultiConnectionused/CreatinganapplicationusingRTCMultiConnection,Howtodoit…,Howitworks…,There’smore…

ApplicationRequestRouting(ARR)/ConfiguringIISApplicationRequestRouting3.0/ConfiguringIISAsterisk

URL/There’smore…

Page 465: WebRTC Cookbook

Bbasicconfigurationitems,TURN

listeningIP/InstallingtheTURNserverrelayIP/InstallingtheTURNserververbosity/InstallingtheTURNserveranonymousaccess/InstallingtheTURNserver

blureffectimplementing/Implementingtheblureffect,Howtodoit…,Howitworks…

BriaURL/InstallingsipML5

brightnessworkingwith/Workingwithbrightness,Howtodoit…,Howitworks…

bweforvideo/Usingwebrtc-internals

Page 466: WebRTC Cookbook

C3CXPhone

URL/InstallingsipML5calls

making/Makingandansweringcalls,Makingacallanswering/Makingandansweringcalls,Answeringacall,There’smore…making,fromwebpage/Makingcallsfromawebpage,Howtodoit…

certificateauthority(CA)about/Generatingaself-signedcertificate

Chromeabout/DebuggingwithChromeWebRTCapplication,debuggingwith/DebuggingwithChrome,GettingreadyURL/Gettingready

Chromemechanisms,fordebuggingWebRTCapplicationswebrtc-internals,using/Usingwebrtc-internalsloggingmechanism,using/UsingChromeloggingmechanism,There’smore…

client-sidecode,TURNserverimplementing/Implementingtheclient-sidecode

colorsworkingwith/Workingwithcolorsandgrayscale,Howtodoit…inverting/Invertingcolors,Howtodoit…,Howitworks…

Conn-audioobject/Usingwebrtc-internalscontrast

workingwith/Workingwithcontrast,Howtodoit…customizedWebRTCdemo

building,foriOS/BuildingacustomizedWebRTCdemoforiOS,Howtodoit…

customvideoprocessingabout/Customvideoprocessing,Howtodoit…

Page 467: WebRTC Cookbook

Ddebugging

about/Introductiondemoproject

building,foriOSsimulator/BuildingademoprojectforaiOSsimulator,Seealso

demoWebMfilesURL/Gettingready

DoS(denialofservice)/Configuringafirewalldroppedshadoweffect

implementing/Implementingthedroppedshadoweffect,Howtodoit…DtlsSrtpKeyAgreementoption/Usingwebrtc-internals

Page 468: WebRTC Cookbook

EErlang

signalingserver,building/Gettingready,Howtodoit…URL/Gettingready

ExpressTalkURL/InstallingsipML5

Page 469: WebRTC Cookbook

FFastFourierTransform(FFT)buffer/Howitworks…filters

about/Introductioncombining/Combiningfilters,Howtodoit…,Howitworks…

FirebaseURL/Howitworks…

firewallconfiguring/Configuringafirewallconfiguring,onserver/Configuringafirewallonaserverconfiguring,onclient/Configuringafirewallonaclient

FreeSWITCHabout/There’smore…

Page 470: WebRTC Cookbook

GgetStatsWebRTCAPIfunction

about/Howtodoit…usecases/Howtodoit…

GLSurfaceViewbug,fixingwith/FixingabugwithGLSurfaceView

grayscaleworkingwith/Workingwithcolorsandgrayscale,Howtodoit…

Page 471: WebRTC Cookbook

Hhue

workingwith/Workingwithhue,Howtodoit…

Page 472: WebRTC Cookbook

IIIS

configuring/ConfiguringIIS,There’smore…InteractiveConnectivityEstablishment(ICE)

about/Howtodoit…/ConfiguringafirewallonaclientInternetInformationServices(IIS)ResourceKitTools/There’smore…inversionofcolors/Invertingcolors

Page 473: WebRTC Cookbook

JJava

signalingserver,building/BuildingasignalingserverinJava,Howtodoit…URL/Gettingready

Java7about/Gettingready

JavaDeveloperKit(JDK)/GettingreadyJSON

URL/GettingreadyJsSIP

URL/There’smore…

Page 474: WebRTC Cookbook

Mmedia

streaming/Streamingmedia,Howtodoit…,Howitworks…microphone

muting/Mutingamicrophone,Howtodoit…microphonelevel

visualizing/Visualizingamicrophone’ssoundlevel,Gettingready,Howtodoit…

mtr/There’smore…multiuserconference

creating,WebRTCOused/CreatingamultiuserconferenceusingWebRTCO,Howtodoit…,Howitworks…

Page 475: WebRTC Cookbook

Nnativeapplication

about/Introductionbuilding/Introduction

nativedemoWebRTCapplication,forAndroidcompiling/CompilingandrunningademoforAndroidsystem,preparing/PreparingthesystemOracleJDK,installing/InstallingOracleJDKWebRTCsourcecode,obtaining/GettingtheWebRTCsourcecodeAndroidDeveloperTools,installing/InstallingAndroidDeveloperTools,Howtodoit…running,onAndroidsimulator/RunningontheAndroidsimulatorbug,fixingwithGLSurfaceView/FixingabugwithGLSurfaceViewrunning,onphysicalAndroiddevice/RunningonaphysicalAndroiddevice

NetworkAddressTranslation(NAT)/ConfiguringafirewallonaclientNetworkAddressTranslator(NAT)/Howtodoit…Nginx

configuring/ConfiguringNginxNumb

about/There’smore…URL/There’smore…

Page 476: WebRTC Cookbook

Oopacityfilter

using/Usingtheopacityfilter,Howtodoit…OpenTok

about/UsingOpenToktocreateaWebRTCapplicationused,forcreatingWebRTCapplication/UsingOpenToktocreateaWebRTCapplication,Gettingready,Howtodoit…,Howitworks…

OpenWebRTClibrarybuilding/BuildinganOpenWebRTClibrary,Gettingready,There’smore…

originalGoogleWebRTCnativedemoapplicationcompiling/CompilingandrunninganoriginaldemoforiOSdemoproject,buildingforiOSdevice/BuildingademoprojectforaniOSdevicedemoproject,buildingforiOSsimulator/BuildingademoprojectforaniOSsimulator

Page 477: WebRTC Cookbook

Ppeer-to-peerprivatemessagingservice

implementing,datachannelsused/Implementingachatusingdatachannels,GettingreadymainHTMLpage,creating/Howtodoit…,CreatingthemainHTMLpageoftheapplicationJavaScripthelperlibrary,creating/CreatingtheJavaScripthelperlibraryworking/Howitworks…implementing,signalingserverused/Implementingachatusingasignalingserver,Howtodoit…,There’smore…

peerconnectionssignalingserver,buildinginErlang/BuildingasignalingserverinErlang,Howtodoit…signalingserver,buildinginJava/BuildingasignalingserverinJava,Howtodoit…calls,making/Gettingreadycalls,answering/Gettingready

PeerJSused,fordevelopingsimpleWebRTCchat/DevelopingasimpleWebRTCchatusingPeerJS,Howtodoit…,Howitworks…

publickeyinfrastructure(PKI)about/Generatingaself-signedcertificateURL/Generatingaself-signedcertificate

Page 478: WebRTC Cookbook

Rrfc5766-turn-server

about/Gettingreadyrootcertificates

about/Generatingaself-signedcertificatertc.io

used,forcreatingsimplevideochat/Makingasimplevideochatwithrtc.io,Howtodoit…

RTCMultiConnectionused,forcreatingapplication/CreatinganapplicationusingRTCMultiConnection,Howtodoit…,Howitworks…

Page 479: WebRTC Cookbook

Ssaturation

workingwith/Workingwithsaturation,Howtodoit…Sawbuck

about/UsingChromeloggingmechanismURL/UsingChromeloggingmechanism

screenshotcapturing/Takingascreenshot,Howtodoit…

SecureSocketsLayer(SSL)/Gettingreadysecurity

about/Introductionself-signedcertificate

generating/Generatingaself-signedcertificate,Gettingready,Howtodoit…sepiafilter

using/Usingthesepiafilter,Howtodoit…,Howitworks…server-sidecode,TURNserver

implementing/Implementingtheserver-sidecode,Howitworks…sessiondescription

about/IntroductionSessionDescriptionProtocol(SDP)

about/Howtodoit…signalingserver

about/Introductionbuilding/Introductionbuilding,inErlang/BuildingasignalingserverinErlang,Howtodoit…building,inJava/BuildingasignalingserverinJava,Howtodoit…

signalingstageabout/Introduction

simplevideochatcreating,withrtc.io/Makingasimplevideochatwithrtc.io,Howtodoit…

SimpleWebRTCabout/BuildingavideoconferenceusingSimpleWebRTCused,forbuildingvideoconference/Gettingready,Howtodoit…,Howitworks…

simpleWebRTCchatdeveloping,PeerJSused/DevelopingasimpleWebRTCchatusingPeerJS,Howtodoit…,Howitworks…

SIP.jsURL/There’smore…

sipML5about/InstallingsipML5,There’smore…installing/InstallingsipML5

SoftwareDevelopmentKit(SDK)/Introduction

Page 480: WebRTC Cookbook

Spring4about/There’smore…

statisticsAPIabout/Introduction

STUNabout/Introductionconfiguring/ConfiguringandusingSTUN,Howtodoit…using/Howitworks…

Page 481: WebRTC Cookbook

Ttcpdump/There’smore…Telephone

URL/InstallingsipML5TransportLayerSecurity(TLS)

about/GettingreadyTURN

about/Introductionconfiguring/ConfiguringandusingTURNinstalling/InstallingtheTURNserverbasicconfigurationitems/InstallingtheTURNserverusing,inWebRTCapplication/UsingTURNinWebRTCapplicationdebugging/DebuggingTURN,Howtodoit…

TURNRESTAPI/Howitworks…TurnServer

about/There’smore…URL/There’smore…

TURNserver,withauthenticationconfiguring/ConfiguringaTURNserverwithauthentication,Gettingreadyclient-sidecode,implementing/Implementingtheclient-sidecodeserver-sidecode,implementing/Implementingtheserver-sidecode,Howitworks…,There’smore…username/Howitworks…password/Howitworks…TTL/Howitworks…URIs/Howitworks…

Page 482: WebRTC Cookbook

UUseHostGPUoption/RunningontheAndroidsimulator

Page 483: WebRTC Cookbook

Vvideo

pausing/Pausingavideo,Howtodoit…videoconference

building,SimpleWebRTCused/BuildingavideoconferenceusingSimpleWebRTC,Howtodoit…,Howitworks…

Page 484: WebRTC Cookbook

WWebPlatformInstaller(WebPI)module/ConfiguringIISWebRTC

security/Introductionwebrtc-internals

about/Usingwebrtc-internalsWebRTCapplication

debugging,withChrome/DebuggingwithChrome,Gettingreadydebugging,withWireshark/DebuggingusingWireshark,Howtodoit…creating,OpenTokused/UsingOpenToktocreateaWebRTCapplication,Gettingready,Howtodoit…,Howitworks…

WebRTCfunctions,supportedbybrowserdetecting/DetectingWebRTCfunctionssupportedbyabrowser,Howitworks…

WebRTCintegrationabout/Introduction

WebRTCintegration,withAsteriskperforming/IntegratingWebRTCwithAsterisklibSRTP,installing/InstallinglibSRTPAsterisk,installing/InstallingAsteriskworking/Howitworks…about/There’smore…

WebRTCintegration,withFreeSWITCHperforming/IntegratingWebRTCwithFreeSWITCHFreeSWITCH,installing/InstallingFreeSWITCHWebRTC,enabling/EnablingWebRTCFreeSWITCH,starting/StartingFreeSWITCH

WebRTCintegration,withwebcamerasperforming/IntegrationofWebRTCwithwebcameras,Gettingreadywebcam,configuring/ConfiguringthewebcamWebRTCmediaserver/InstallingWebRTCmediaserver

WebRTCmediaserverimplementing/Timeformagic,Howitworks…

WebRTCOabout/CreatingamultiuserconferenceusingWebRTCOused,forcreatingmultiuserconference/Gettingready,Howtodoit…,Howitworks…

WebRTCstandarddraftURL/There’smore…

WebRTCstatisticsAPIworkingwith/WorkingwithaWebRTCstatisticsAPI,Howtodoit…,Howitworks…estimatedbandwidth,checking/Checkingestimatedbandwidth

Page 485: WebRTC Cookbook

packetloss,checking/Checkingpacketlosswebserver

configuring/ConfiguringawebservertoworkoverHTTPS,Howtodoit…WebSockets

about/ConfiguringaWebSocketsproxyonthewebserverWebSocketsproxyconfiguration

onwebserver/ConfiguringaWebSocketsproxyonthewebserver,Howitworks…Nginx,configuring/ConfiguringNginxApache,configuring/ConfiguringApacheIIS,configuring/ConfiguringIIS

Wiresharkabout/DebuggingusingWiresharkWebRTCapplication,debuggingwith/DebuggingusingWireshark,Howtodoit…URL/Gettingready

Page 486: WebRTC Cookbook

XX-Lite

URL/InstallingsipML5

Page 487: WebRTC Cookbook

ZZoiper

URL/InstallingsipML5