SlideShare a Scribd company logo
Python, WebRTC and You
Saúl Ibarra Corretgé

@saghul
v2
github.com/saghul
WebRTC, anyone?
Have you ever used it?
Internals, anyone?
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.
Python, WebRTC and You (v2)
Python, WebRTC and You (v2)
Python, WebRTC and You (v2)
Well,
everyone
better
Restart
Their
Chrome
You need an adapter
Implementation in browsers is
currently inconsistent

Some APIs are still in flux
rtcninja.js
https://github.com/eface2face/rtcninja.js

Nice name, right?!
Temasys WebRTC
Plugin
Free (as in beer) plugin for IE and
Safari

http://skylink.io/plugin/
WebRTC APIs
getUserMedia

RTCPeerConnection

RTCDataChannel
getUserMedia
if (!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);	
}	
);
Python, WebRTC and You (v2)
RTCPeerConnection
Handles streaming of media between
2 peers

Uses state of the art technology

JSEP
RTCPeerConnection (2)
Get local media Send SDP offer
Get local media
Send SDP answer
ICE candidates
Audio / Video
Interactive Connectivity Establishment
ICE
Helps find the best path for media

Solves NAT traversal and other
hostile network problems

Communication Consent Verification

It can trickle!
Python, WebRTC and You (v2)
What about the
signalling?
It’s not specified!

Use SIP, XMPP or roll your own!
Python, WebRTC and You (v2)
Python, WebRTC and You (v2)
RTCDataChannel
P2P, message boundary based
channel for arbitrary data

Implemented using SCTP, different
reliability choices possible
Python, WebRTC and You (v2)
Call Roulette
Python
JavaScript
The Protocol
WebSocket based, JSON payload

Users enter the roulette when they
connect over WebSocket

Session is negotiated / established

No end message, just disconnect the
WebSocket
Saghul’s Imbecile Protocol
(v1)
yo
(v2)
{'yo': 'yo'}
{'jsep': {'sdp': '...',	
'type': 'offer'},	
'yo': 'yo'}
{'jsep': {'sdp': '...',	
'type': 'answer'},	
'yo': 'yo'}
{'candidate': {'candidate': '...',	
'sdpMLineIndex': 1,	
'sdpMid': ''},	
'yo': 'yo'}
Python, WebRTC and You (v2)
Shopping for a
framework
Python >= 3.3, because future!

WebSocket support built-in

Async, because blocking is so 2001

New, because why not?
asyncio + aiohttp
github.com/saghul/CallRoulette
@asyncio.coroutine	
def 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
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)
class WebSocketHandler:	
def __init__(self):	
self.waiter = None	
!
@asyncio.coroutine	
def __call__(self, request):	
ws = web.WebSocketResponse(protocols=('callroulette-v2',))	
ws.start(request)	
!
conn = Connection(ws)	
if self.waiter is None:	
self.waiter = asyncio.Future(loop=ws._loop)	
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()

reading_task.cancel()	
asyncio.async(self.run_roulette(conn, other))	
else:	
self.waiter.set_result(conn)	
!
yield from conn.wait_closed()	
!
return ws
from jsonmodels import models, fields	
from jsonmodels.errors import ValidationError	
!
!
class StringChoiceField(fields.StringField):	
def __init__(self, choices=None, *args, **kw):	
self.choices = choices or []	
super(StringChoiceField, self).__init__(*args, **kw)	
!
def validate(self, value):	
if value not in self.choices:	
raise ValidationError('invalid choice value')	
super(StringChoiceField, self).validate(value)	
!
class Jsep(models.Base):	
type = StringChoiceField(choices=['offer', 'answer'], required=True)	
sdp = fields.StringField(required=True)	
!
class Candidate(models.Base):	
candidate = fields.StringField(required=True)	
sdpMid = fields.StringField(required=True)	
sdpMLineIndex = fields.IntField(required=True)	
!
class YoPayload(models.Base):	
yo = fields.StringField(required=True)	
jsep = fields.EmbeddedField(Jsep)	
candidate = fields.EmbeddedField(Candidate)
@asyncio.coroutine	
def run_roulette(self, peerA, peerB):	
log.info('Running roulette: %s, %s' % (peerA, peerB))	
!
@asyncio.coroutine	
def close_connections():	
yield from asyncio.wait([peerA.close(), peerB.close()],

return_when=asyncio.ALL_COMPLETED)	
!
def parse(data):	
try:	
data = json.loads(data)	
payload = YoPayload(**data)	
payload.validate()	
except Exception as e:	
log.warning('Error parsing payload: %s' % e)	
return None	
return payload
# request offer	
offer_request = YoPayload(yo='yo')	
peerA.write(json.dumps(offer_request.to_struct()))	
!
# get offer	
data = yield from peerA.read(timeout=READ_TIMEOUT)	
if not data:	
yield from close_connections()	
return	
!
offer = parse(data)	
if offer is None or offer.jsep is None or offer.jsep.type != 'offer':	
log.warning('Invalid offer received')	
yield from close_connections()	
return	
!
# send offer	
peerB.write(json.dumps(offer.to_struct()))
# wait for answer	
data = yield from peerB.read(timeout=READ_TIMEOUT)	
if not data:	
yield from close_connections()	
return	
!
answer = parse(data)	
if answer is None or answer.jsep is None or answer.jsep.type != 'answer':	
log.warning('Invalid answer received')	
yield from close_connections()	
return	
!
# dispatch answer	
peerA.write(json.dumps(answer.to_struct()))
# wait for candidates / end	
while True:	
peer_a_read = asyncio.async(peerA.read())	
peer_a_read.other_peer = peerB	
peer_b_read = asyncio.async(peerB.read())	
peer_b_read.other_peer = peerA	
done, pending = yield from asyncio.wait([peer_a_read, peer_b_read],	
return_when=asyncio.FIRST_COMPLETED)	
for task in pending:	
task.cancel()	
for task in done:	
data = task.result()	
if not data:	
break	
# all we can get at this point is trickled ICE candidates	
candidate = parse(data)	
if candidate is None or candidate.candidate is None:	
log.warning('Invalid candidate received!')	
break	
task.other_peer.write(json.dumps(candidate.to_struct()))	
else:	
continue	
break	
# close connections	
yield from close_connections()
Python, WebRTC and You (v2)
In WebRTC trouble?
bettercallsaghul.com
@saghul
Ad

Recommended

深入淺出C語言
深入淺出C語言
Simen Li
 
Unreal Engineでのコンフィギュレーター制作と映像制作 UNREAL FEST EXTREME 2021 SUMMER
Unreal Engineでのコンフィギュレーター制作と映像制作 UNREAL FEST EXTREME 2021 SUMMER
エピック・ゲームズ・ジャパン Epic Games Japan
 
【続】OpenXRでHoloLensアプリを作る
【続】OpenXRでHoloLensアプリを作る
Takahiro Miyaura
 
on log messages
on log messages
Laurence Chen
 
Algorithm Design and Analysis
Algorithm Design and Analysis
Reetesh Gupta
 
Freer Monads, More Extensible Effects
Freer Monads, More Extensible Effects
Hiromi Ishii
 
UE4とUnrealC++について
UE4とUnrealC++について
Masahiko Nakamura
 
GUI Programming using NetBeans (1).pptx
GUI Programming using NetBeans (1).pptx
Sumalee Sonamthiang
 
Epic Online Services でできること
Epic Online Services でできること
エピック・ゲームズ・ジャパン Epic Games Japan
 
WebLogic Scripting Tool
WebLogic Scripting Tool
ALI ANWAR, OCP®
 
4_5802928814682016556.pptx
4_5802928814682016556.pptx
AshenafiGirma5
 
Rsa in CTF
Rsa in CTF
SoL ymx
 
コルーチンの使い方
コルーチンの使い方
Naohiro Yoshikawa
 
ARマーカーを利用したHoloLens同士の位置合わせ
ARマーカーを利用したHoloLens同士の位置合わせ
Takahiro Miyaura
 
Nmapの真実(ゾクゾク)
Nmapの真実(ゾクゾク)
Keigo Yamazaki
 
【Unite Tokyo 2019】ゼロから始めるアラビア語レンダリング
【Unite Tokyo 2019】ゼロから始めるアラビア語レンダリング
UnityTechnologiesJapan002
 
UniRxHandsOnVol1
UniRxHandsOnVol1
Shoji Oshima
 
HoloLensでコンテンツを操作する方法 - Gaze And Dwell -
HoloLensでコンテンツを操作する方法 - Gaze And Dwell -
Takahiro Miyaura
 
Python, WebRTC and You
Python, WebRTC and You
Saúl Ibarra Corretgé
 
Planning libuv v2
Planning libuv v2
Saúl Ibarra Corretgé
 
CDRTool: CDR mediation and rating engine for OpenSIPS
CDRTool: CDR mediation and rating engine for OpenSIPS
Saúl Ibarra Corretgé
 
Trust No One
Trust No One
Saúl Ibarra Corretgé
 
The Future of the PBX
The Future of the PBX
Saúl Ibarra Corretgé
 
WebRTC enabling your OpenSIPS infrastructure
WebRTC enabling your OpenSIPS infrastructure
Saúl Ibarra Corretgé
 
libuv, NodeJS and everything in between
libuv, NodeJS and everything in between
Saúl Ibarra Corretgé
 
Building an Open Source VoIP Hardware Phone
Building an Open Source VoIP Hardware Phone
Saúl Ibarra Corretgé
 
From SIP to WebRTC and vice versa
From SIP to WebRTC and vice versa
Saúl Ibarra Corretgé
 
Proyecto Open Pi Phone
Proyecto Open Pi Phone
Saúl Ibarra Corretgé
 
SylkServer: State of the art RTC application server
SylkServer: State of the art RTC application server
Saúl Ibarra Corretgé
 
Escalabilidad horizontal desde las trincheras
Escalabilidad horizontal desde las trincheras
Saúl Ibarra Corretgé
 

More Related Content

What's hot (10)

Epic Online Services でできること
Epic Online Services でできること
エピック・ゲームズ・ジャパン Epic Games Japan
 
WebLogic Scripting Tool
WebLogic Scripting Tool
ALI ANWAR, OCP®
 
4_5802928814682016556.pptx
4_5802928814682016556.pptx
AshenafiGirma5
 
Rsa in CTF
Rsa in CTF
SoL ymx
 
コルーチンの使い方
コルーチンの使い方
Naohiro Yoshikawa
 
ARマーカーを利用したHoloLens同士の位置合わせ
ARマーカーを利用したHoloLens同士の位置合わせ
Takahiro Miyaura
 
Nmapの真実(ゾクゾク)
Nmapの真実(ゾクゾク)
Keigo Yamazaki
 
【Unite Tokyo 2019】ゼロから始めるアラビア語レンダリング
【Unite Tokyo 2019】ゼロから始めるアラビア語レンダリング
UnityTechnologiesJapan002
 
UniRxHandsOnVol1
UniRxHandsOnVol1
Shoji Oshima
 
HoloLensでコンテンツを操作する方法 - Gaze And Dwell -
HoloLensでコンテンツを操作する方法 - Gaze And Dwell -
Takahiro Miyaura
 
4_5802928814682016556.pptx
4_5802928814682016556.pptx
AshenafiGirma5
 
Rsa in CTF
Rsa in CTF
SoL ymx
 
ARマーカーを利用したHoloLens同士の位置合わせ
ARマーカーを利用したHoloLens同士の位置合わせ
Takahiro Miyaura
 
Nmapの真実(ゾクゾク)
Nmapの真実(ゾクゾク)
Keigo Yamazaki
 
【Unite Tokyo 2019】ゼロから始めるアラビア語レンダリング
【Unite Tokyo 2019】ゼロから始めるアラビア語レンダリング
UnityTechnologiesJapan002
 
HoloLensでコンテンツを操作する方法 - Gaze And Dwell -
HoloLensでコンテンツを操作する方法 - Gaze And Dwell -
Takahiro Miyaura
 

Viewers also liked (20)

Python, WebRTC and You
Python, WebRTC and You
Saúl Ibarra Corretgé
 
Planning libuv v2
Planning libuv v2
Saúl Ibarra Corretgé
 
CDRTool: CDR mediation and rating engine for OpenSIPS
CDRTool: CDR mediation and rating engine for OpenSIPS
Saúl Ibarra Corretgé
 
Trust No One
Trust No One
Saúl Ibarra Corretgé
 
The Future of the PBX
The Future of the PBX
Saúl Ibarra Corretgé
 
WebRTC enabling your OpenSIPS infrastructure
WebRTC enabling your OpenSIPS infrastructure
Saúl Ibarra Corretgé
 
libuv, NodeJS and everything in between
libuv, NodeJS and everything in between
Saúl Ibarra Corretgé
 
Building an Open Source VoIP Hardware Phone
Building an Open Source VoIP Hardware Phone
Saúl Ibarra Corretgé
 
From SIP to WebRTC and vice versa
From SIP to WebRTC and vice versa
Saúl Ibarra Corretgé
 
Proyecto Open Pi Phone
Proyecto Open Pi Phone
Saúl Ibarra Corretgé
 
SylkServer: State of the art RTC application server
SylkServer: State of the art RTC application server
Saúl Ibarra Corretgé
 
Escalabilidad horizontal desde las trincheras
Escalabilidad horizontal desde las trincheras
Saúl Ibarra Corretgé
 
A deep dive into libuv
A deep dive into libuv
Saúl Ibarra Corretgé
 
libuv: cross platform asynchronous i/o
libuv: cross platform asynchronous i/o
Saúl Ibarra Corretgé
 
Videoconferencias: el santo grial de WebRTC
Videoconferencias: el santo grial de WebRTC
Saúl Ibarra Corretgé
 
Jitsi: State of the Union
Jitsi: State of the Union
Saúl Ibarra Corretgé
 
Asyncio
Asyncio
Andrew Svetlov
 
Introduction to asyncio
Introduction to asyncio
Saúl Ibarra Corretgé
 
Rethinking the PBX
Rethinking the PBX
Saúl Ibarra Corretgé
 
Developing rich SIP applications with SIPSIMPLE SDK
Developing rich SIP applications with SIPSIMPLE SDK
Saúl Ibarra Corretgé
 
CDRTool: CDR mediation and rating engine for OpenSIPS
CDRTool: CDR mediation and rating engine for OpenSIPS
Saúl Ibarra Corretgé
 
WebRTC enabling your OpenSIPS infrastructure
WebRTC enabling your OpenSIPS infrastructure
Saúl Ibarra Corretgé
 
libuv, NodeJS and everything in between
libuv, NodeJS and everything in between
Saúl Ibarra Corretgé
 
Building an Open Source VoIP Hardware Phone
Building an Open Source VoIP Hardware Phone
Saúl Ibarra Corretgé
 
SylkServer: State of the art RTC application server
SylkServer: State of the art RTC application server
Saúl Ibarra Corretgé
 
Escalabilidad horizontal desde las trincheras
Escalabilidad horizontal desde las trincheras
Saúl Ibarra Corretgé
 
libuv: cross platform asynchronous i/o
libuv: cross platform asynchronous i/o
Saúl Ibarra Corretgé
 
Videoconferencias: el santo grial de WebRTC
Videoconferencias: el santo grial de WebRTC
Saúl Ibarra Corretgé
 
Developing rich SIP applications with SIPSIMPLE SDK
Developing rich SIP applications with SIPSIMPLE SDK
Saúl Ibarra Corretgé
 
Ad

Similar to Python, WebRTC and You (v2) (20)

Python, do you even async?
Python, do you even async?
Saúl Ibarra Corretgé
 
A deep dive into PEP-3156 and the new asyncio module
A deep dive into PEP-3156 and the new asyncio module
Saúl Ibarra Corretgé
 
Real-Time Python Web: Gevent and Socket.io
Real-Time Python Web: Gevent and Socket.io
Rick Copeland
 
Tornado in Depth
Tornado in Depth
Òscar Vilaplana
 
Power ai image-pipeline
Power ai image-pipeline
Paulo Sergio Lemes Queiroz
 
DevCon 5 (July 2013) - WebSockets
DevCon 5 (July 2013) - WebSockets
Crocodile WebRTC SDK and Cloud Signalling Network
 
Twisted logic
Twisted logic
ashfall
 
Websocket 101 in Python
Websocket 101 in Python
Juti Noppornpitak
 
WebRTC 101 - How to get started building your first WebRTC application
WebRTC 101 - How to get started building your first WebRTC application
Dan Jenkins
 
Building Web APIs that Scale
Building Web APIs that Scale
Salesforce Developers
 
SwampDragon presentation: The Copenhagen Django Meetup Group
SwampDragon presentation: The Copenhagen Django Meetup Group
Ernest Jumbe
 
Server side story
Server side story
Simone Deponti
 
Enhancing Mobile User Experience with WebSocket
Enhancing Mobile User Experience with WebSocket
Mauricio "Maltron" Leal
 
WebSocket Push Fallback - Transcript.pdf
WebSocket Push Fallback - Transcript.pdf
ShaiAlmog1
 
WebSockets-Revolutionizing-Real-Time-Communication.pptx
WebSockets-Revolutionizing-Real-Time-Communication.pptx
YasserLina
 
Java API for WebSocket 1.0: Java EE 7 and GlassFish
Java API for WebSocket 1.0: Java EE 7 and GlassFish
Arun Gupta
 
Python, async web frameworks, and MongoDB
Python, async web frameworks, and MongoDB
emptysquare
 
Demuxed 2020
Demuxed 2020
SeanDuBois3
 
Python & Django TTT
Python & Django TTT
kevinvw
 
연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015
연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015
Jeongkyu Shin
 
A deep dive into PEP-3156 and the new asyncio module
A deep dive into PEP-3156 and the new asyncio module
Saúl Ibarra Corretgé
 
Real-Time Python Web: Gevent and Socket.io
Real-Time Python Web: Gevent and Socket.io
Rick Copeland
 
Twisted logic
Twisted logic
ashfall
 
WebRTC 101 - How to get started building your first WebRTC application
WebRTC 101 - How to get started building your first WebRTC application
Dan Jenkins
 
SwampDragon presentation: The Copenhagen Django Meetup Group
SwampDragon presentation: The Copenhagen Django Meetup Group
Ernest Jumbe
 
Enhancing Mobile User Experience with WebSocket
Enhancing Mobile User Experience with WebSocket
Mauricio "Maltron" Leal
 
WebSocket Push Fallback - Transcript.pdf
WebSocket Push Fallback - Transcript.pdf
ShaiAlmog1
 
WebSockets-Revolutionizing-Real-Time-Communication.pptx
WebSockets-Revolutionizing-Real-Time-Communication.pptx
YasserLina
 
Java API for WebSocket 1.0: Java EE 7 and GlassFish
Java API for WebSocket 1.0: Java EE 7 and GlassFish
Arun Gupta
 
Python, async web frameworks, and MongoDB
Python, async web frameworks, and MongoDB
emptysquare
 
Python & Django TTT
Python & Django TTT
kevinvw
 
연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015
연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015
Jeongkyu Shin
 
Ad

More from Saúl Ibarra Corretgé (16)

JanusCon 2024: Mom there are robots in my meeting
JanusCon 2024: Mom there are robots in my meeting
Saúl Ibarra Corretgé
 
Challenges running Jitsi Meet at scale during the pandemic
Challenges running Jitsi Meet at scale during the pandemic
Saúl Ibarra Corretgé
 
The Road to End-to-End Encryption in Jitsi Meet
The Road to End-to-End Encryption in Jitsi Meet
Saúl Ibarra Corretgé
 
Jitsi: State of the Union 2020
Jitsi: State of the Union 2020
Saúl Ibarra Corretgé
 
Jitsi Meet: our tale of blood, sweat, tears and love
Jitsi Meet: our tale of blood, sweat, tears and love
Saúl Ibarra Corretgé
 
Jitsi Meet: Video conferencing for the privacy minded
Jitsi Meet: Video conferencing for the privacy minded
Saúl Ibarra Corretgé
 
Jitsi - Estado de la unión 2019
Jitsi - Estado de la unión 2019
Saúl Ibarra Corretgé
 
Get a room! Spot: the ultimate physical meeting room experience
Get a room! Spot: the ultimate physical meeting room experience
Saúl Ibarra Corretgé
 
Going Mobile with React Native and WebRTC
Going Mobile with React Native and WebRTC
Saúl Ibarra Corretgé
 
Going Mobile with React Native and WebRTC
Going Mobile with React Native and WebRTC
Saúl Ibarra Corretgé
 
Jitsi: Estado de la Unión (2018)
Jitsi: Estado de la Unión (2018)
Saúl Ibarra Corretgé
 
Jitsi: state-of-the-art video conferencing you can self-host
Jitsi: state-of-the-art video conferencing you can self-host
Saúl Ibarra Corretgé
 
WebRTC: El epicentro de la videoconferencia y IoT
WebRTC: El epicentro de la videoconferencia y IoT
Saúl Ibarra Corretgé
 
Jitsi: Open Source Video Conferencing
Jitsi: Open Source Video Conferencing
Saúl Ibarra Corretgé
 
Extendiendo SIP con WebRTC
Extendiendo SIP con WebRTC
Saúl Ibarra Corretgé
 
De SIP a WebRTC y vice versa
De SIP a WebRTC y vice versa
Saúl Ibarra Corretgé
 
JanusCon 2024: Mom there are robots in my meeting
JanusCon 2024: Mom there are robots in my meeting
Saúl Ibarra Corretgé
 
Challenges running Jitsi Meet at scale during the pandemic
Challenges running Jitsi Meet at scale during the pandemic
Saúl Ibarra Corretgé
 
The Road to End-to-End Encryption in Jitsi Meet
The Road to End-to-End Encryption in Jitsi Meet
Saúl Ibarra Corretgé
 
Jitsi Meet: our tale of blood, sweat, tears and love
Jitsi Meet: our tale of blood, sweat, tears and love
Saúl Ibarra Corretgé
 
Jitsi Meet: Video conferencing for the privacy minded
Jitsi Meet: Video conferencing for the privacy minded
Saúl Ibarra Corretgé
 
Get a room! Spot: the ultimate physical meeting room experience
Get a room! Spot: the ultimate physical meeting room experience
Saúl Ibarra Corretgé
 
Going Mobile with React Native and WebRTC
Going Mobile with React Native and WebRTC
Saúl Ibarra Corretgé
 
Going Mobile with React Native and WebRTC
Going Mobile with React Native and WebRTC
Saúl Ibarra Corretgé
 
Jitsi: state-of-the-art video conferencing you can self-host
Jitsi: state-of-the-art video conferencing you can self-host
Saúl Ibarra Corretgé
 
WebRTC: El epicentro de la videoconferencia y IoT
WebRTC: El epicentro de la videoconferencia y IoT
Saúl Ibarra Corretgé
 

Recently uploaded (20)

AI VIDEO MAGAZINE - June 2025 - r/aivideo
AI VIDEO MAGAZINE - June 2025 - r/aivideo
1pcity Studios, Inc
 
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
revolcs10
 
War_And_Cyber_3_Years_Of_Struggle_And_Lessons_For_Global_Security.pdf
War_And_Cyber_3_Years_Of_Struggle_And_Lessons_For_Global_Security.pdf
biswajitbanerjee38
 
OpenACC and Open Hackathons Monthly Highlights June 2025
OpenACC and Open Hackathons Monthly Highlights June 2025
OpenACC
 
Information Security Response Team Nepal_npCERT_Vice_President_Sudan_Jha.pdf
Information Security Response Team Nepal_npCERT_Vice_President_Sudan_Jha.pdf
ICT Frame Magazine Pvt. Ltd.
 
You are not excused! How to avoid security blind spots on the way to production
You are not excused! How to avoid security blind spots on the way to production
Michele Leroux Bustamante
 
The Future of Data, AI, and AR: Innovation Inspired by You.pdf
The Future of Data, AI, and AR: Innovation Inspired by You.pdf
Safe Software
 
AI vs Human Writing: Can You Tell the Difference?
AI vs Human Writing: Can You Tell the Difference?
Shashi Sathyanarayana, Ph.D
 
From Manual to Auto Searching- FME in the Driver's Seat
From Manual to Auto Searching- FME in the Driver's Seat
Safe Software
 
Connecting Data and Intelligence: The Role of FME in Machine Learning
Connecting Data and Intelligence: The Role of FME in Machine Learning
Safe Software
 
“From Enterprise to Makers: Driving Vision AI Innovation at the Extreme Edge,...
“From Enterprise to Makers: Driving Vision AI Innovation at the Extreme Edge,...
Edge AI and Vision Alliance
 
Turning the Page – How AI is Exponentially Increasing Speed, Accuracy, and Ef...
Turning the Page – How AI is Exponentially Increasing Speed, Accuracy, and Ef...
Impelsys Inc.
 
Security Tips for Enterprise Azure Solutions
Security Tips for Enterprise Azure Solutions
Michele Leroux Bustamante
 
cnc-processing-centers-centateq-p-110-en.pdf
cnc-processing-centers-centateq-p-110-en.pdf
AmirStern2
 
Enabling BIM / GIS integrations with Other Systems with FME
Enabling BIM / GIS integrations with Other Systems with FME
Safe Software
 
Enhance GitHub Copilot using MCP - Enterprise version.pdf
Enhance GitHub Copilot using MCP - Enterprise version.pdf
Nilesh Gule
 
9-1-1 Addressing: End-to-End Automation Using FME
9-1-1 Addressing: End-to-End Automation Using FME
Safe Software
 
June Patch Tuesday
June Patch Tuesday
Ivanti
 
"Database isolation: how we deal with hundreds of direct connections to the d...
"Database isolation: how we deal with hundreds of direct connections to the d...
Fwdays
 
MuleSoft for AgentForce : Topic Center and API Catalog
MuleSoft for AgentForce : Topic Center and API Catalog
shyamraj55
 
AI VIDEO MAGAZINE - June 2025 - r/aivideo
AI VIDEO MAGAZINE - June 2025 - r/aivideo
1pcity Studios, Inc
 
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
ReSTIR [DI]: Spatiotemporal reservoir resampling for real-time ray tracing ...
revolcs10
 
War_And_Cyber_3_Years_Of_Struggle_And_Lessons_For_Global_Security.pdf
War_And_Cyber_3_Years_Of_Struggle_And_Lessons_For_Global_Security.pdf
biswajitbanerjee38
 
OpenACC and Open Hackathons Monthly Highlights June 2025
OpenACC and Open Hackathons Monthly Highlights June 2025
OpenACC
 
Information Security Response Team Nepal_npCERT_Vice_President_Sudan_Jha.pdf
Information Security Response Team Nepal_npCERT_Vice_President_Sudan_Jha.pdf
ICT Frame Magazine Pvt. Ltd.
 
You are not excused! How to avoid security blind spots on the way to production
You are not excused! How to avoid security blind spots on the way to production
Michele Leroux Bustamante
 
The Future of Data, AI, and AR: Innovation Inspired by You.pdf
The Future of Data, AI, and AR: Innovation Inspired by You.pdf
Safe Software
 
AI vs Human Writing: Can You Tell the Difference?
AI vs Human Writing: Can You Tell the Difference?
Shashi Sathyanarayana, Ph.D
 
From Manual to Auto Searching- FME in the Driver's Seat
From Manual to Auto Searching- FME in the Driver's Seat
Safe Software
 
Connecting Data and Intelligence: The Role of FME in Machine Learning
Connecting Data and Intelligence: The Role of FME in Machine Learning
Safe Software
 
“From Enterprise to Makers: Driving Vision AI Innovation at the Extreme Edge,...
“From Enterprise to Makers: Driving Vision AI Innovation at the Extreme Edge,...
Edge AI and Vision Alliance
 
Turning the Page – How AI is Exponentially Increasing Speed, Accuracy, and Ef...
Turning the Page – How AI is Exponentially Increasing Speed, Accuracy, and Ef...
Impelsys Inc.
 
Security Tips for Enterprise Azure Solutions
Security Tips for Enterprise Azure Solutions
Michele Leroux Bustamante
 
cnc-processing-centers-centateq-p-110-en.pdf
cnc-processing-centers-centateq-p-110-en.pdf
AmirStern2
 
Enabling BIM / GIS integrations with Other Systems with FME
Enabling BIM / GIS integrations with Other Systems with FME
Safe Software
 
Enhance GitHub Copilot using MCP - Enterprise version.pdf
Enhance GitHub Copilot using MCP - Enterprise version.pdf
Nilesh Gule
 
9-1-1 Addressing: End-to-End Automation Using FME
9-1-1 Addressing: End-to-End Automation Using FME
Safe Software
 
June Patch Tuesday
June Patch Tuesday
Ivanti
 
"Database isolation: how we deal with hundreds of direct connections to the d...
"Database isolation: how we deal with hundreds of direct connections to the d...
Fwdays
 
MuleSoft for AgentForce : Topic Center and API Catalog
MuleSoft for AgentForce : Topic Center and API Catalog
shyamraj55
 

Python, WebRTC and You (v2)

  • 1. Python, WebRTC and You Saúl Ibarra Corretgé
 @saghul v2
  • 4. Have you ever used it?
  • 6. 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.
  • 11. You need an adapter Implementation in browsers is currently inconsistent Some APIs are still in flux
  • 13. Temasys WebRTC Plugin Free (as in beer) plugin for IE and Safari http://skylink.io/plugin/
  • 15. getUserMedia if (!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); } );
  • 17. RTCPeerConnection Handles streaming of media between 2 peers Uses state of the art technology JSEP
  • 18. RTCPeerConnection (2) Get local media Send SDP offer Get local media Send SDP answer ICE candidates Audio / Video
  • 20. ICE Helps find the best path for media Solves NAT traversal and other hostile network problems Communication Consent Verification It can trickle!
  • 22. What about the signalling? It’s not specified! Use SIP, XMPP or roll your own!
  • 25. RTCDataChannel P2P, message boundary based channel for arbitrary data Implemented using SCTP, different reliability choices possible
  • 29. The Protocol WebSocket based, JSON payload Users enter the roulette when they connect over WebSocket Session is negotiated / established No end message, just disconnect the WebSocket
  • 33. {'jsep': {'sdp': '...', 'type': 'offer'}, 'yo': 'yo'}
  • 34. {'jsep': {'sdp': '...', 'type': 'answer'}, 'yo': 'yo'}
  • 37. Shopping for a framework Python >= 3.3, because future! WebSocket support built-in Async, because blocking is so 2001 New, because why not?
  • 40. @asyncio.coroutine def 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
  • 41. 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)
  • 42. class WebSocketHandler: def __init__(self): self.waiter = None ! @asyncio.coroutine def __call__(self, request): ws = web.WebSocketResponse(protocols=('callroulette-v2',)) ws.start(request) ! conn = Connection(ws) if self.waiter is None: self.waiter = asyncio.Future(loop=ws._loop) 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()
 reading_task.cancel() asyncio.async(self.run_roulette(conn, other)) else: self.waiter.set_result(conn) ! yield from conn.wait_closed() ! return ws
  • 43. from jsonmodels import models, fields from jsonmodels.errors import ValidationError ! ! class StringChoiceField(fields.StringField): def __init__(self, choices=None, *args, **kw): self.choices = choices or [] super(StringChoiceField, self).__init__(*args, **kw) ! def validate(self, value): if value not in self.choices: raise ValidationError('invalid choice value') super(StringChoiceField, self).validate(value) ! class Jsep(models.Base): type = StringChoiceField(choices=['offer', 'answer'], required=True) sdp = fields.StringField(required=True) ! class Candidate(models.Base): candidate = fields.StringField(required=True) sdpMid = fields.StringField(required=True) sdpMLineIndex = fields.IntField(required=True) ! class YoPayload(models.Base): yo = fields.StringField(required=True) jsep = fields.EmbeddedField(Jsep) candidate = fields.EmbeddedField(Candidate)
  • 44. @asyncio.coroutine def run_roulette(self, peerA, peerB): log.info('Running roulette: %s, %s' % (peerA, peerB)) ! @asyncio.coroutine def close_connections(): yield from asyncio.wait([peerA.close(), peerB.close()],
 return_when=asyncio.ALL_COMPLETED) ! def parse(data): try: data = json.loads(data) payload = YoPayload(**data) payload.validate() except Exception as e: log.warning('Error parsing payload: %s' % e) return None return payload
  • 45. # request offer offer_request = YoPayload(yo='yo') peerA.write(json.dumps(offer_request.to_struct())) ! # get offer data = yield from peerA.read(timeout=READ_TIMEOUT) if not data: yield from close_connections() return ! offer = parse(data) if offer is None or offer.jsep is None or offer.jsep.type != 'offer': log.warning('Invalid offer received') yield from close_connections() return ! # send offer peerB.write(json.dumps(offer.to_struct()))
  • 46. # wait for answer data = yield from peerB.read(timeout=READ_TIMEOUT) if not data: yield from close_connections() return ! answer = parse(data) if answer is None or answer.jsep is None or answer.jsep.type != 'answer': log.warning('Invalid answer received') yield from close_connections() return ! # dispatch answer peerA.write(json.dumps(answer.to_struct()))
  • 47. # wait for candidates / end while True: peer_a_read = asyncio.async(peerA.read()) peer_a_read.other_peer = peerB peer_b_read = asyncio.async(peerB.read()) peer_b_read.other_peer = peerA done, pending = yield from asyncio.wait([peer_a_read, peer_b_read], return_when=asyncio.FIRST_COMPLETED) for task in pending: task.cancel() for task in done: data = task.result() if not data: break # all we can get at this point is trickled ICE candidates candidate = parse(data) if candidate is None or candidate.candidate is None: log.warning('Invalid candidate received!') break task.other_peer.write(json.dumps(candidate.to_struct())) else: continue break # close connections yield from close_connections()