 core team. I'm a partner at Rockin' Cat. Small claims of fame. As many years ago I wrote the plug logger and I added the microsecond symbol to the log. So every time you see that I think about my face. So yeah, I'm here to talk today a little bit about WebRTC and I want to start off with a small question. So raise your hand if you've used video calling the Google Hangouts or peer.in or Slack before. Great, pretty much everyone. And then how many of you were having a meeting and you had to disable the video because the connection sucked or the quality sucked and it was distracting? Right, so pretty much everyone raise your hands. I had the same exact problem. So I created a project called Team Chat, which was kind of there for me to learn WebRTC. And basically it's a website you go to, you give it a name, then you get a URL. And you can share that URL with anyone and as long as they have a supported browser they can instantly talk with you. Just voice communications. No video doesn't try to do any shanigans. It just does your voice so it's really quick. And I learned a lot about WebRTC in this process and I wanted to kind of share my experiences about this really cool technology that we all have in our browsers that none of us really use outside of the video and audio context. So today we're going to talk a little bit about what is WebRTC, how you might use it. I'm going to go through a small technical demo. Then I'm going to get into some of the technical bits and some of the things I like to see in the future. So WebRTC is at its basis sort of a peer-to-peer framework in your browser. It's the only way for two browsers to directly communicate with each other. There's no middle server. When WebRTC was first designed, it was designed specifically for connecting one browser to another browser. But it's not just a browser. There's also mobile devices and there's even server implementations. So for example, we used Apple FaceTime that uses the WebRTC protocol. And now the latest versions of Skype and everything use WebRTC as well. And a lot of people think when they hear WebRTC, they think it's only video and audio. And that's really great because your browser will handle encoding, handle decoding. I'm going to handle bit rate. It'll figure out what the optimal resolution is to send over the wire automatically for you. But when Google was making the first version of WebRTC so that they could support Google Hangouts, they also snuck in the data channel. So basically in our browsers, we have a way to build and deploy peer-to-peer applications that can communicate directly between two browsers very easily. And it's like I said, the only way to send peer-to-peer data between two browsers without a middle person. And it also happens to be the easiest way currently today to deploy a peer-to-peer application. If you think about peer-to-peer applications that we use today like BitTorrent or like Napster or Kaza or something, you have to download a client on your local machine. You have to run it. You have to open all these ports. You have to figure out how to use it. But with a browser, you just have to go to a website and it works. The connections are automatically encrypted for you by default. You can't have an unencrypted WebRTC connection. So when you talk with a Google Hangout or a peer.in or something, it's fully encrypted. You don't have to really think about the browser handles it for you. And between two browsers, direct connections are always going to have the best possible latency. And that's kind of alluding to the subtitle when you talk about microseconds. You're never going to have a better connection between two browsers than a direct connection on the LAN or even on the same building. You're always going to have a better time than going up to a server and back. So that's WebRTC. It's a peer-to-peer application. And when you're developing a peer-to-peer application, you have three fundamental things you have to figure out before you can build it and while you build it. And the first one is kind of like peer discovery. So it's basically who do you connect to and who has the data that I want. If you think about Skype for Hangouts, you have a user list that you sign up and you create an account and it's got a list of users you can talk to and you can communicate with. And then once the connections are made, it's handled peer-to-peer, right? When you talk on a Skype call, you're making a direct connection to another user in their application, usually. With BitTorrent, a very famous peer-to-peer application, there is a tracker, which is a central server that has sort of a bootstrap list of peers that you can connect to to kind of get the rest of the data, get the rest of the peers. And then there's sort of like services like Kaza and Napster use a distributed hash table where you'd have, you start off with a single peer and because you can talk to that one peer, you can find out where any data is in the entire network. When you're building a WebRTC application, we really only have one solution right now, which is sort of a central server like Hangouts and Skype. Because it lives in the browser, there are certain limitations about what we can connect to and what we can talk to. But it's not really a limitation, it's a very small limitation. You still need a central server and that's kind of, in our case, where Phoenix and Elixir will come in down the line. The second problem is opening and maintaining a connection is kind of hard, especially in a peer-to-peer context. Like right now, we're all in a network with a router and it's got certain restrictions on what ports it has open, who can make connections to who, what your bandwidth is. And in the corporate environment, you have a lot of situations with Nats and VPNs and all kinds of weird rules with firewalls. Luckily, in our case, the browser attempts to handle all of this for you and we'll go over that in a bit and then maintaining the connection. When you're in this conference, you're probably moving from router to router as you switch rooms. When you use your cell phone, you're moving between from Wi-Fi networks, LTE networks, and then you may even be changing towers as you use your network. In our case, again, the browser attempts to handle all of this for you. And then the third problem is like, what is my application domain and how do we connect to each other? So here's an example of one peer-to-peer application where two peers are directly communicating and that's basically the whole topology. This is, I think my bad. So this is a case like a Skype call or a direct phone call. Each user is talking directly to each other. You could have a mesh topology or many to many. This is what I used in TeamChat where each user maintains another connection to every other user. An application like a peer.in also does this. In the context of a browser, especially when you're doing video and audio, you can about handle six peers. And that's because with each user, you have to encode the video and send it. And then when they send their video to you, you have to decode it and display it. And you have to do this once for each user. So for the user case, if they have a bad connection or a bad internet source or low bandwidth or bandwidth caps, you may not want to ship an app like this because they're doing three times the work that they would have to do unless they're an essential server. I did it for TeamChat just because it was simple and I was learning what peer-to-peer is. And it's great if you're all in the same building or in the same geographic area because you get really low latency. But like I said, browsers can handle up to six. If you do data channels, you can probably get a lot more. But with Audio Video Six, it seems to be everyone agrees that's the one word of Chrome crashes. You can do start apologies. There are one to many where one user is kind of like the broadcaster and everyone just kind of communicates with them. You can imagine sort of a Twitch streaming or like a webinar service where the green user is presenting to all the users. You could also imagine a situation where the green person is accepting streams from everyone and then they're rebroadcasting it out to all the other users. This is something you have to decide and it's basically purely on your application domain again. We'll talk about this one a little bit later in some future uses. And then finally, with WebRTC, there is a centralized approach where each user communicates with a central server and that central server either acts as sort of a proxy and bounces the messages between green to red, from green to red and red to green and red to blue or whatever. Or it will do some sort of aggregation like merging video streams and audio streams and then sending only one stream down. Unfortunately right now, because of the limits of WebRTC and the limits of networks in general and because the people who are doing it are like big Google and Apple, they do a lot of things like this. A lot of the services are built like this because you get certain, you get guarantees that a user is going to be able to connect to it and like I said, you can do transformations and you can keep the video around. So like if you're at Google, maybe you want to keep the streams around so that they can replay it later. So in Google Hangouts case they do this. So yeah, I've been listing off a bunch of apps that are using in the real world. Right now, it's a lot of big, sort of big players. Google Hangouts was the first one. They're the reason we have WebRTC because they wanted to make Skype in the browser. They wrote their own plugin and then they said, hey, let's make this a spec. So then Firefox and then fought forever and they're still fighting about the spec. But Peer.in is a good example. Slack recently had calls to their platform. They use WebRTC. Apple FaceTime is a weird example. They use WebRTC as a protocol for the video and audio transmission, but as you'll see in a bit, they don't support it in the browser at all. The newest version of Skype use of WebRTC, they just started supporting it. On my project and then there's WebTorrent, which is a really cool example. It's a fully functioning WebTorrent client in your browser. It connects. There's some magic that happens in the tracker side, but it will connect to actual BitTorrent clients out there. You can fully stream, upload and download Torrents in the browser. It's a really cool example of WebRTC and if you're interested, you should really check it out because they're doing some of the coolest things. I'm gonna go ahead and rip off the Band-Aid right away. It's pretty well supported. You can see that the usual player support at Chrome and Firefox. Internet Explorer actually supports it in the latest version. They support everything but Data Channel for some reason and then they invented their own, you can see right here, their own spec called ORTC, which is almost WebRTC, but it's a little different. Slowly but surely WebRTC and ORTC will merge into one spec. It's supposed to be the next version of WebRTC or something, but the big elfin in the room is Safari, not supporting it at all. Once they support it, WebRTC will pretty much be like 100% ready. Everyone should be able to use it in deploy apps confidently. They were supposed to be hiring a WebRTC person last year but we don't know what happened. It wasn't a part of the Mac OS Sierra beta and everything, but that's kind of the downer. Safari doesn't support it, but everyone else supports it and it's an official spec now, so everyone's going to support it. They even decided on audio and video and codecs that they're going to support and fallback codecs that they'll support, so no more fighting or anything. Then this is a list of features. If you're interested in learning about when it's going to be ready, the website is WebRTCReady.com lists off all the features about WebRTC and what you can use in a web browser. Let's talk through a really small example. Here we have an example where I'm trying to design a WebRTC calling app where I have the green user wants to talk directly with the red user. We need to have a central server to serve up the HTTP and in my case it's a Phoenix web application where green and red are communicating with Phoenix. I'm using Phoenix.Presence. This kind of emulates what my demo is going to be, so keep this in your brain. We're using Phoenix.Presence to know that green and red are online and available to talk. Green says, hey I want to talk to red, so it creates an offer and then tells ask Phoenix to give it to red. What is the offer? The offer is a little packet of data that your browser generates. Basically it says this is what my browser is capable of doing. It says I can speak this audio encoding, I can speak this video encoding, I want to send it at this resolution at this bit rate. This is the encryption I want to use. This is a protocol I'd like to speak. When you're using data channels, it sets up all the data channels that you want to set up. You can set up as many data channels as you want and it'll multiplex it for you. And then finally it says this is what I think my IP address is and how I think you can connect to me. And the browser handles all this for you. There's a spec that you can review if you're interested in that kind of thing. But you just say hey browser give me an offer so I can send it to the other user and then it works. So yeah, back to our example. Phoenix routes the offer to red. Red says oh hey great here's my offer and then Phoenix routes it back. So now green and red nobody each other what they can do and how they connect to each other. They make a connection. Again the browser handles all that for you and then Phoenix can kind of get out of the picture. And this whole process is called signaling. And in my case I've been trying to make a strong argument that Phoenix.Presence and Phoenix channels are really really great for signaling. And I think airline is really great for it as well because if you kind of think about what airline was first invented for is invented for routing phone calls. And that's essentially what this process is signaling. It's how do I connect to someone. In the case of a phone call you have a phone number and you say I want to talk to user you know 1-800 whatever. And then airline figures out how to route that phone call to the other user and then it makes a connection. In our case you know it's whatever your application is you know it's I want to talk to you know this user with this username you know Phoenix figure it out. Phoenix.Presence manages that for you. It manages a list of who's online what their idea is what the devices they're connected to so maybe you want to make the call to their mobile device instead of their actual browser. Phoenix.Presence can handle all that for you. But you don't have to use Phoenix.Presence. There's tons of tons and tons of signaling services out there. A lot of people use SIP or Jingle. You can use IRC or even Slack XMPP or even Ajax. Basically any way you can share a small JSON payload. So there's some examples online where you copy and paste the JSON object and you send it to them for email or something and they send you their offer back. But this is the process of signaling and that's like basically once you've got the two browsers have the offer real-time communications can happen without Phoenix needing to be around at all. Basically it's you know three-step process. Create an offer, get the offer to the other person and you guys can talk. And that's like that's the absolute high level. That's all you have to do to make WebRTC work in your browser. In my demo in a bit right after this I'm going to be using a library called SimplePeer. Every browser right now has a slightly different API. It kind of sucks and SimplePeer just kind of extracts the API into an easy to use system. I like to think of it as kind of like the jQuery.ajx of WebRTC right now. The same person who wrote WebTorrent.js and he also wrote a CDN based on WebRTC where if you visit the website it'll it'll serve up the JavaScript for you know everyone on the same land as you from your computer. He created SimplePeer and it's really great. So you should use it. So let's do let's do a small demo. So I think basically what I built is chat roulette for Elixir Conf. And basically you have a website here. You come to the website and you're put in the waiting queue and then someone shows up. I have a plant in the audience. Nick our network is not super great apparently. You can see super high latency but and then you guys are instantly streaming. And then if Nick leaves and someone else joins I would be instantly reconnected with them. So yeah this is phoenix-webRTC.roquep.com. You can see it if you'd like but it's a really simple example of how to use WebRTC. So I'm going to close this just in case someone else comes and then try not to do lewd things. This isn't chat roulette. But so here's the first bit of Elixir code. I'm going to start with Elixir because it's a lot easier to follow. Here we have sort of the user lobby and this is where you get immediately entered into when you join the website. We track the user's presence. I'm just using phoenix presence. And then I grab the whole list of users. I filter out myself and then I grab the first user. If that user exists then I tell them to start a call and then I give them sort of a room to join so that they can send their offers privately to each other. And that's this room over here. It's basically it joins. I do a little authentication here and then I track that they're in the room. I don't really need to do this in this case. And then the browser can send up an event called signal that I just broadcast all the users in the room which is only two with payload. So yeah, like I said, phoenix makes this almost trivial to set up. In Node.js they have a socket that I appear to appear that you have to set up and you basically have almost the exact same amount of code but you need to have another library to make it possible. In terms of the JavaScript side it's about 80 lines of code total. It's just ES6. I'm sorry I didn't use React or TypeScript or something. But really a simple example here. You join the channel. I check to see if you have WebRTC support. And this is from peer.js. Whenever you see peer it's for peer.js. Join the user lobby. You listen for the chat start message. If you get the chat start message check to see if you're in it. This is kind of a hack I did because I didn't really want to write a whole system. I just wanted a really easy example. If you're in it then you leave the user lobbies so that you're not recued up with someone else. You join the call room. And then I grab the video. Let's get user media. It's the function you use to grab video and audio from the browser. Some air handling, JavaScript stuff. I add your video to the page and then I play it. And then here I create the WebRTC peer. I pass the stream to it. I have some other config options like iServer which we'll talk about in a bit. And then you have to tell it which is who's the initiator. So in this case it would be the red user's initiator. Scroll past some of this air handling that I have in a branch, fixed elsewhere. But then here's kind of like this code right here is all you need to do to handle WebRTC. It's five lines of code. You ask your browser for an offer and it's an asynchronous process and it gives you your offer. I send it down the channel and then on the other user they'll receive the signal from the other user and they accept it. And then we just wait for a connection to be made. We wait for the user stream to be sent to us and we add it to a video element and we play it. If we were doing a data channel we would just have peer.onData and whenever a user sent data down the pipe we'd have a callback to handle it. And it's peer.push to push data down the pipe. You can push arbitrary JSON. You can also push binaries and stuff down the pipe. But like this is all you need to do to make a purely application in your browser. So let's get back to the presentation. So yeah that code, the website's phoenix.showboard to see it at hokweb.com. The code's open source so if you want to if I went too fast and you want to take a look or copy and paste it for your project go nuts. It's right there. So here's just an example code and I want to talk about it a little bit. Sorry it's a little washed out. But I mentioned that the signal was asynchronous. And it's asynchronous because the hardest part about generating an offer isn't figuring out what your browser's capable of doing but it's figuring out what your IP address is. And because you exist in a usually a private network or a private router your browser has a hard time knowing what its IP address is. So they devised a protocol called stun or ice. And you'll see this all the time. It's always in all caps. That's why it's in all caps here. But it's a protocol basically where it's a third party server that's running on the internet somewhere, public internet with a public IP address that you know where your browser says you ask it to make an offer and then your browser goes to the ice server and says hey, what do you think my IP address is? And they have this back and forth communication until they figure out what your public IP address is. And once they figure that out you get an offer and then you send it off. Whenever you're waiting in Google Hangouts for a call to like start and you see a little loading screen or like in Slack you see a little loader. You can see the person's online trying to make a call and you just see a little spinner. It's basically your browser trying to figure out what your IP address is. There is a way to make this faster and it's called Trickle Ice. The ice protocol is basically just a back and forth. Like I said, they try up to 12 times to figure out, you know, make the trade, basically the tracerot hops all the way from the trickle server to your IP address until it figures out what it thinks it is. With Trickle Ice, you get each one of those IP addresses and your first offer has, you know, the dumb guess that your browser makes and all the, you know, the encoding and encryption stuff that you send off to them. But then the next few offers are just IP addresses that your browser can try. And this drastically will speed up your connection times. And that's what I did in Team Chat. That's why it's so much faster. But if you see some of our ice or Trickle Ice, you know, it's just a configuration option. It was, like I said, you saw me set up the pier. There's an ice server's option. I gave it a URL for a public trickle server and it was set up. In the case when you cannot figure out what your public IP address is, when you cannot make a connection happen because for whatever reason your network sucks, there's, you can set up a turn server. And a turn server acts like a proxy. Basically it's a public server. When red and green are trying to talk, instead of talking directly, they talk to the turn server. It will forward off all packets to the red server and the same thing with red. Red will send packets to the turn server and it will forward off the green user. This is generally okay because your connection is by default encrypted. And because your offer goes through a secure channel, you know, your secure signaling process, you don't really have to worry about anyone knowing what your keys are or anything. Some services, for instance Slack, Slack calls enforce this behavior to happen. And in their case, their application domain is business users who are by default behind a weird firewall or weird NAT. So by forcing a turn server it makes sure that connections happen really quick and then they can also kind of guarantee what the latency is going to be because they can put servers near their users. In terms of this, you can host your own Stun or Ice server. There's an airline one built by Process One called Stun. It does turn and ice. I don't think it does trickle ice but it's a possibility. There's also services like Tulio. I'm a big fan of these services because, especially with turn, you want to be as close as possible to your users. You don't want to have your turn server hosted in the west coast and then have users in Ireland trying to talk through the turn server, having the round trip latency of the Atlantic Ocean. So Tulio has a geolocated service globally geolocated and it's like pennies for data. It's not really that expensive. But yeah, so we kind of talked about WebRTC at a high level. I would like to talk a little bit about like the low level aspects of WebRTC, some of the cooler things that get me excited about WebRTC and the protocol underneath it. Some of the more technical bits. So WebRTC is built on top of a protocol called stream control transmission protocol or SCTP. It was invented in the late 90s and it was fully ratified as a spec in the early 2000s. It's a protocol that's designed to be built just like UDP or TCP. It kind of lines up in the middle between SCTP or TCP and UDP a little bit. The problems are it's not supported at all by operating systems or networks pretty much or firewalls. Like Amazon, like I mean it makes sense, right? A system admin sets up a router and they're going to accept UDP and TCP because who the hell would use a different protocol? They're just going to block everything else because it's a security risk. So telecoms are pretty much the only one that use this by default in their own networks. It was built for to be a message-based, multi-homing, multi-streaming protocol. So you can get some of the benefits of UDP without sacrificing some of the benefits of TCP. It also has like, say I'll show this list, basically here's how it kind of lines up with TCP and UDP. You get, so like with TCP, like basically the protocol when we do WebSockets at HTTP, you have, you know, a fully reliable and ordered protocol and you get flow control and congested control by default. When you think about UDP, it's fully unreliable and unordered and it's message-oriented, right? So that's typically used, like example, BitTorrent uses UDP because they just want to send as many packets down the pipe as possible and, you know, they have their own resolution process of a packet to get dropped or something. They can re-request it. But SCP is kind of like sort of the middle ground where you get to decide if reliability or order is important to you but you also get the message-oriented aspect of it so you can send multiple streams, you know, because you're sending, because in TCP it's byte-oriented you just send as many bytes down as you can and then they have to read it. With UDP you send a message down the pipe and then you can send multiple messages down the pipe for different streams and then the protocol kind of re-routes them to the correct spot. At SCP you also get flow control and congestion control by default. And with the data channel this is really kind of cool because you get to configure this. You get to decide if you want it to be ordered or reliable. You get to decide what your application needs. And, you know, in terms of the browser this is kind of unique because up until now we just got what we got and we just had to use it, right? So we had AJAX which is, you know, a TCP connection that you make with HTTP and it's pretty good for most cases. And then you have WebSockets that are a little bit faster because we have one connection open and we're not sending headers back and forth but it's kind of limited to what TCP can do. In the data channel of your WebRTC you get to decide, you know, if you want, you know, if you want completely unordered and almost, you know, partially reliable you can decide that, right? You can basically get the semantics of UDP in the browser. And this is what WebTorrent does, right? They say, I want it to act like UDP so I can get much data in and out as possible without having to do round-trip acts and all that stuff that you have with TCP. So yeah, these are all the different things you can configure, all the different options when you initialize your data channel. Some of the neat ones I think are kind of like the time-out base reliability or, you know, retransmit of a packet. So if you kind of think about like high-speed trading or audio or video you might want to set up a time-out for your packets where, you know, I only care about what happened in the last five milliseconds in an audio conversation, right? I don't care if something happened, you know, 30 seconds ago, right? If a packet got dropped, it got dropped, I don't care about it. You can configure that. I mean the same with like high-speed trading, right? You may not care about the trades that happened minutes ago. You only really care about now because you can only really process now fast enough. So you get to configure all of that inside of a, inside of your data channel which I think is super neat, right? Inside your browser you have the option to, you know, write applications in like you couldn't do before. So let's talk about the future of what I think is really neat about what we've already seen that are coming and that you can do today. If I talk about like a browser spec just assume Chrome and Firefox support it and nobody else right now, but in the future everyone will support it. So right away one of the neat things is web audio support which is, you can take a stream for another user. If you saw Josh Adams talk today about web audio where, you know, they were editing or creating audio on the fly you could take a bunch of streams from a voice call or a video call and you can merge them you can apply effects to them you could do fast warrior transference on them. Basically anything you can do with a web audio stream you can do with a web RTC stream. One neat idea you could, you know, do a real time authentication so you're talking to you know with a voice chat and they could analyze their voice to make sure they are who they say they are. That's kind of neat. You could also do like, you know, is this person talking and you can show wave forms and you can do all kinds of weird stuff with streams. Another neat thing is you can do screen sharing so you can grab any window on your computer and share it so you could very easily, you know, with that five lines of code you could share you could create your own screen hero or you could create your own Webinar application. Yeah, that's a pretty neat one. So then there's a process of stream re-broadcasting and this kind of goes into that sort of start topology, right? This allows you to do some really weird topologies in the browser that you couldn't do before. And if you could imagine, you know, kind of like a network like this where the green users may be like a famous Twitch streamer or a YouTube streamer and they want to live broadcast to all their users but they're sick and tired of paying Twitch. You know, whatever they have to pay Twitch. So the green user broadcasts the red, this green user shows up and says, hey, I want to view it so they stream from red and then red just re-broadcasts the stream to green. So everyone in the network is sharing the cost of the bandwidth. You don't need to have centralized servers like, you know, Twitch or YouTube where Google pays the cost of streaming all that both the upload and the download. In this case, everyone's just sharing it. And again, you'd have to figure out how to maintain this state. You'd have to figure out how to route people to the right spot. If you search for WebRTC stream re-broadcasting, there are some libraries where they attempt to do this. You still get really bad, I mean, so the further you get away from them, you get bad latency, right? The worse your latency gets because each person has to re-broadcast, upload and download it. But that's kind of neat, right? You can do those kind of things now. There's full canvas support. So if you'd like to take the video, put it in canvas, draw weird hats and snapchat filter all over the face and process it. You can totally do that today in real time. You can also do the opposite where you take a canvas, draw on it, and then send it down the pipe and stream it to other users. You can imagine, you know, with WebRTC support, using the data channel, you can imagine making a game with the canvas and the data channel where, you know, it's a multiplayer game and you're talking back and forth with the lowest possible latency. And this final idea is kind of like, I'm kind of hoping it kind of brings home, brings it home to the LixarConf. And I think it would be really neat to see a library like GenWebRTC where the client can connect directly to AirLang as if it's a peer. And some of the neat things, you get all the neat characteristics of SCTP where you can control the latency and the reliability. So for example, if you're making a game and WebSockets have too high of latency because of the BrownTrip app, you could use GenWebRTC to communicate directly with the server which obviously leads into allowing us to use the abstractions we have in Phoenix with channels. So like you could use phoenix.channels by simply, by developing a phoenix.transforce.webRTC you could develop, you could use your same channels and the same code we use today to communicate between a browser and a server. And this is super neat, right? This is the technology all of us have in our computers today but it allows us to build, you know, higher performance applications in the context of a browser. Whereas previously we were limited to whatever WebSocket can support. So yeah, that's, I mean, that's my talk. If you want to learn more about WebRTC, this first website, hpbn.co, High Performance Browser Networking, it's an Arayali book that was open sourced and it's made free online. They talk about HTTP and WebSockets and performance and it's pretty much right now the best bot for documentation for WebRTC online. All the different browsers support different APIs right now but this one kind of goes over everything. It's really great. There's WebRTC.org which is Google's website and then there's WebRTC Hacks which is sort of like a blog of, you know, when Slack released our call features, you know, someone looked in to internals and sell what they're doing and, you know, you can kind of keep up the date with who supports WebRTC and what they're doing with it. It's kind of neat to see you, how industry is using it and like how they're getting around some of the limitations and things. But, you know, I want to have one more slide. We're all professional engineers here. I got to say it. You know, HP and WebStock are great. For most use cases, I wouldn't suggest rewriting your application to use WebRTC. It's not super well supported by Safari and other browsers and when you're making a WebRTC app, you're making a peer-to-peer application which means it's going to be harder to debug. It's going to be slower in some cases. It's going to be faster in some cases and you're going to get a lot of weird bugs which if that's what your application is all about, that's great. You've already seen it. It's amazing. But don't go out of WebRTC. So, I'm Jason Sibbs. I'm Peregrine on Twitter. My GitHub is Jeregrine. I'm a co-founder of Rockin' Cat. We do a lot of electric coaching, consulting and development and other stuff. We make mobile apps and stuff. So, if you're interested in working with me or on WebRTC or electric stuff, let me know. If you have any questions about this, I think we have time for some questions still. I don't... Yeah, probably. So just find the person with the mic right there. Yep. And I'll answer any questions you have. Hey, Jason. Thanks for a really great talk. And what you were talking about with Phoenix Transport, that's exactly what I just spent the last month or six weeks looking into. Cool. We should talk. I also started a Slack channel, WebRTC Slack channel. I don't know whether you knew about it. Great. I'd love to work with you and try and make that happen. Awesome. So, yeah, I'll talk to you. Thanks. That's great. So you might have it. Be cool. I've got a question here. So, have you... What's the deal with GEN-SCTP in early? Have you used that? So, yeah, thanks for asking. I forgot to mention that. OTP has GEN-SCTP built into it. I looked at the commit logs and the mailing list. It was started, but never finished. So it has some tests that don't run or pass and it's in there, but it doesn't work. If you were to make this, we'd also have to develop, obviously, I think we'd have to make GEN-DTLS so that we can do the encryption on top of UDP. And then we'd have to make an SDP parser, which is sort of the format for the offer. So there's a couple libraries that would have to get written to make it possible. But once those are written, you know, it's on. It's open. So, and I know there's some C++ libraries and stuff, so like if we wanted to build it with a NIF or something, we could probably do that. But, you know, it's kind of lame. I don't know if you mentioned it, but mobile browsers? Oh, yeah. So mobile browsers right now, no support. It's across the board. But there are mobile libraries. So, for example, Slack calls. There's Google WebRTC. Well, I guess, okay, sorry. Google Chrome, on the latest version of Android, will support WebRTC. That's it. There are libraries for WebRTC. There's C++ libraries that people have compiled on Android and iOS. So if you want to make an app that supports it, it's very simple. You just have to follow the instructions and then you get the JavaScript library. No questions. Cool. Thanks, guys.