Python, WebRTC and You
-
Upload
saul-ibarra-corretge -
Category
Technology
-
view
1.582 -
download
5
Transcript of Python, WebRTC and You
![Page 1: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/1.jpg)
Python, WebRTC and YouSaúl Ibarra Corretgé
@saghul
![Page 2: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/2.jpg)
print(“hello!”)
@saghul
FOSDEM
Open Source
![Page 4: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/4.jpg)
Listen at your own risk
![Page 5: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/5.jpg)
Do you know about WebRTC?
![Page 6: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/6.jpg)
Have you ever used it?
![Page 7: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/7.jpg)
What is WebRTC?
WebRTC (Web Real-Time Communication) is an API definition drafted by the World Wide Web Consortium (W3C) that supports browser-to-browser applications for voice calling, video chat, and P2P file sharing without the need of either internal or external plugins.
![Page 8: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/8.jpg)
![Page 9: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/9.jpg)
![Page 10: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/10.jpg)
You need an adaptorImplementation in browsers is currently inconsistent
Some APIs are still in flux
I’ll be using rtcninja
https://github.com/eface2face/rtcninja.js
![Page 11: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/11.jpg)
WebRTC APIs
getUserMedia
RTCPeerConnection
RTCDataChannel
![Page 12: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/12.jpg)
getUserMediaif (!rtcninja.hasWebRTC()) { console.log('Are you from the past?!'); return;}!rtcninja.getUserMedia( // constraints {video: true, audio: true},! // successCallback function(localMediaStream) { var video = document.querySelector('video'); rtcninja.attachMediaStream(video, localMediaStream); },! // errorCallback function(err) { console.log("The following error occured: " + err); });
![Page 13: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/13.jpg)
![Page 14: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/14.jpg)
RTCPeerConnection
Handles streaming of media between 2 peers
Uses state of the art technology
ICE for NAT traversal
![Page 15: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/15.jpg)
RTCPeerConnection (2)Get local media
Send SDP offer Get local media
Send SDP answer
Audio / Video
![Page 16: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/16.jpg)
![Page 17: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/17.jpg)
![Page 18: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/18.jpg)
RTCDataChannelP2P, message boundary based channel for arbitrary data
Implemented using SCTP, different reliability choices possible
This is the game-changer
Did I mention it’s P2P?
![Page 19: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/19.jpg)
![Page 20: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/20.jpg)
What about the signalling?
It’s not specified!
Use SIP, XMPP, or your own!
![Page 21: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/21.jpg)
Call Roulette
![Page 22: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/22.jpg)
Saghul’s Imbecile Protocol
![Page 23: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/23.jpg)
The ProtocolUsers enter the roulette when they connect over WebSocket
3 types of messages: offer_request, offer and answer
No end message, just disconnect the WebSocket
![Page 24: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/24.jpg)
![Page 25: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/25.jpg)
Shopping for a framework
Python >= 3.3, because future!
WebSocket support built-in
Async, because blocking is so 2001
New, because hype!
![Page 26: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/26.jpg)
asyncio + aiohttp
![Page 27: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/27.jpg)
@asyncio.coroutinedef init(loop): app = web.Application(loop=loop) app.router.add_route('GET', '/', LazyFileHandler(INDEX_FILE, 'text/html')) app.router.add_route('GET', '/ws', WebSocketHandler()) app.router.add_route('GET', '/static/{path:.*}', StaticFilesHandler(STATIC_FILES))! handler = app.make_handler() server = yield from loop.create_server(handler, '0.0.0.0', 8080) print("Server started at http://0.0.0.0:8080") return server, handler
![Page 28: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/28.jpg)
class StaticFilesHandler: def __init__(self, base_path): self.base_path = base_path self.cache = {}! @asyncio.coroutine def __call__(self, request): path = request.match_info['path'] try: data, content_type = self.cache[path] except KeyError: full_path = os.path.join(self.base_path, path) try: with open(full_path, 'rb') as f: content_type, encoding = mimetypes.guess_type(full_path, strict=False) data = f.read() except IOError: log.warning('Could not open %s file' % path) raise web.HTTPNotFound() self.cache[path] = data, content_type log.debug('Loaded file %s (%s)' % (path, content_type)) return web.Response(body=data, content_type=content_type)
![Page 29: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/29.jpg)
class WebSocketHandler: def __init__(self): self.waiter = None! @asyncio.coroutine def __call__(self, request): ws = web.WebSocketResponse(protocols=('callroulette',)) ws.start(request)! conn = Connection(ws) if self.waiter is None: self.waiter = asyncio.Future() fs = [conn.read(), self.waiter] done, pending = yield from asyncio.wait(fs, return_when=asyncio.FIRST_COMPLETED) if self.waiter not in done: # the connection was most likely closed self.waiter = None return ws other = self.waiter.result() self.waiter = None reading_task = pending.pop() asyncio.async(self.run_roulette(conn, other, reading_task)) else: self.waiter.set_result(conn)! yield from conn.wait_closed()! return ws
![Page 30: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/30.jpg)
@asyncio.coroutine def run_roulette(self, peerA, peerB, initial_reading_task): log.info('Running roulette: %s, %s' % (peerA, peerB))! def _close_connections(): peerA.close() peerB.close()! # request offer data = dict(type='offer_request'); peerA.write(json.dumps(data))! # get offer # I cannot seem to cancel the reading task that was started before, which is the # only way one can know if the connection was closed, so use if for the initial # reading try: data = yield from asyncio.wait_for(initial_reading_task, READ_TIMEOUT) except asyncio.TimeoutError: data = '' if not data: return _close_connections()! data = json.loads(data) if data.get('type') != 'offer' or not data.get('sdp'): log.warning('Invalid offer received') return _close_connections()
![Page 31: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/31.jpg)
# send offer data = dict(type='offer', sdp=data['sdp']); peerB.write(json.dumps(data))! # wait for answer data = yield from peerB.read(timeout=READ_TIMEOUT) if not data: return _close_connections()! data = json.loads(data) if data.get('type') != 'answer' or not data.get('sdp'): log.warning('Invalid answer received') return _close_connections()! # dispatch answer data = dict(type='answer', sdp=data['sdp']); peerA.write(json.dumps(data))! # wait for end fs = [peerA.read(), peerB.read()] yield from asyncio.wait(fs, return_when=asyncio.FIRST_COMPLETED)! # close connections return _close_connections()
![Page 32: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/32.jpg)
![Page 33: Python, WebRTC and You](https://reader034.fdocuments.in/reader034/viewer/2022050805/55a5d1761a28abd4298b48e4/html5/thumbnails/33.jpg)
Questions?
bettercallsaghul.com@saghul