Slides for the 90 minutes workshop I presented at the RTC2019 event in Beijing. The many slides cover different aspects in Janus, ranging from configuration, to plugins, how to write your own plugin, core features, recording, monitoring, and so on.
2. Who am I?
Lorenzo Miniero
• Ph.D @ UniNA
• Chairman @ Meetecho
• Main author of Janus®
Contacts and info
• rtcexpo@meetecho.com
• https://twitter.com/elminiero
• https://www.slideshare.net/LorenzoMiniero
3. Just a few words on Meetecho
• Co-founded in 2009 as an academic spin-off
• University research efforts brought to the market
• Completely independent from the University
• Focus on real-time multimedia applications
• Strong perspective on standardization and open source
• Several activities
• Consulting services
• Commercial support and Janus licenses
• Streaming of live events (IETF, ACM, etc.)
• Proudly brewed in sunny Napoli, Italy
16. What’s Janus?
Janus
General purpose, open source WebRTC server
• https://github.com/meetecho/janus-gateway
• Demos and documentation: https://janus.conf.meetecho.com
• Community: https://groups.google.com/forum/#!forum/meetecho-janus
18. Modular architecture
• The core only implements the WebRTC stack
• JSEP/SDP, ICE, DTLS-SRTP, Data Channels, Simulcast, VP9-SVC, ...
• Plugins expose Janus API over different “transports”
• Currently HTTP / WebSockets / RabbitMQ / Unix Sockets / MQTT / Nanomsg
• “Application” logic implemented in plugins too
• Users attach to plugins via the Janus core
• The core handles the WebRTC stuff
• Plugins route/manipulate the media/data
• Plugins can be combined on client side as “bricks”
• Video SFU, Audio MCU, SIP gatewaying, broadcasting, etc.
19. Modular architecture
• The core only implements the WebRTC stack
• JSEP/SDP, ICE, DTLS-SRTP, Data Channels, Simulcast, VP9-SVC, ...
• Plugins expose Janus API over different “transports”
• Currently HTTP / WebSockets / RabbitMQ / Unix Sockets / MQTT / Nanomsg
• “Application” logic implemented in plugins too
• Users attach to plugins via the Janus core
• The core handles the WebRTC stuff
• Plugins route/manipulate the media/data
• Plugins can be combined on client side as “bricks”
• Video SFU, Audio MCU, SIP gatewaying, broadcasting, etc.
20. Modular architecture
• The core only implements the WebRTC stack
• JSEP/SDP, ICE, DTLS-SRTP, Data Channels, Simulcast, VP9-SVC, ...
• Plugins expose Janus API over different “transports”
• Currently HTTP / WebSockets / RabbitMQ / Unix Sockets / MQTT / Nanomsg
• “Application” logic implemented in plugins too
• Users attach to plugins via the Janus core
• The core handles the WebRTC stuff
• Plugins route/manipulate the media/data
• Plugins can be combined on client side as “bricks”
• Video SFU, Audio MCU, SIP gatewaying, broadcasting, etc.
21. Modular architecture
• The core only implements the WebRTC stack
• JSEP/SDP, ICE, DTLS-SRTP, Data Channels, Simulcast, VP9-SVC, ...
• Plugins expose Janus API over different “transports”
• Currently HTTP / WebSockets / RabbitMQ / Unix Sockets / MQTT / Nanomsg
• “Application” logic implemented in plugins too
• Users attach to plugins via the Janus core
• The core handles the WebRTC stuff
• Plugins route/manipulate the media/data
• Plugins can be combined on client side as “bricks”
• Video SFU, Audio MCU, SIP gatewaying, broadcasting, etc.
24. Configuring Janus
• Janus and plugins can be configured via .jcfg files (libconfig format)
• Old INI format still supported, though
• Some (core-only) properties can be set via command-line as well
• Several options to configure the server’s behaviour
• Logging, transport, media settings, etc.
• Format of libconfig files is quite simple to understand and use
# This is a comment
name0 = value0
category1: {
name1 = number
name2 = "string"
name3 = boolean
...
}
category2: {
name2 = [ array ]
...
}
25. Configuring Janus
• Janus and plugins can be configured via .jcfg files (libconfig format)
• Old INI format still supported, though
• Some (core-only) properties can be set via command-line as well
• Several options to configure the server’s behaviour
• Logging, transport, media settings, etc.
• Format of libconfig files is quite simple to understand and use
# This is a comment
name0 = value0
category1: {
name1 = number
name2 = "string"
name3 = boolean
...
}
category2: {
name2 = [ array ]
...
}
26. Configuring Janus
• Janus and plugins can be configured via .jcfg files (libconfig format)
• Old INI format still supported, though
• Some (core-only) properties can be set via command-line as well
• Several options to configure the server’s behaviour
• Logging, transport, media settings, etc.
• Format of libconfig files is quite simple to understand and use
# This is a comment
name0 = value0
category1: {
name1 = number
name2 = "string"
name3 = boolean
...
}
category2: {
name2 = [ array ]
...
}
28. Configuring the core
• The Janus core is configured in janus.jcfg
• As anticipated, some properties can be overridden via command-line too
• Different categories that can be configured
• general
• General settings (logging, daemonization, etc.)
• certificates
• Certificate and key to use (DTLS only, autogenerated if missing)
• media
• Media related stuff (RTP range, DTLS mtu, etc.)
• nat
• ICE related settings (ICE Lite/TCP, STUN/TURN, etc.)
• plugins, transports
• Media and transport plugins NOT to load
• events
• Event handlers settings
29. Configuring the core
• The Janus core is configured in janus.jcfg
• As anticipated, some properties can be overridden via command-line too
• Different categories that can be configured
• general
• General settings (logging, daemonization, etc.)
• certificates
• Certificate and key to use (DTLS only, autogenerated if missing)
• media
• Media related stuff (RTP range, DTLS mtu, etc.)
• nat
• ICE related settings (ICE Lite/TCP, STUN/TURN, etc.)
• plugins, transports
• Media and transport plugins NOT to load
• events
• Event handlers settings
30. Configuring the core
• The Janus core is configured in janus.jcfg
• As anticipated, some properties can be overridden via command-line too
• Different categories that can be configured
• general
• General settings (logging, daemonization, etc.)
• certificates
• Certificate and key to use (DTLS only, autogenerated if missing)
• media
• Media related stuff (RTP range, DTLS mtu, etc.)
• nat
• ICE related settings (ICE Lite/TCP, STUN/TURN, etc.)
• plugins, transports
• Media and transport plugins NOT to load
• events
• Event handlers settings
31. Configuring the core
• The Janus core is configured in janus.jcfg
• As anticipated, some properties can be overridden via command-line too
• Different categories that can be configured
• general
• General settings (logging, daemonization, etc.)
• certificates
• Certificate and key to use (DTLS only, autogenerated if missing)
• media
• Media related stuff (RTP range, DTLS mtu, etc.)
• nat
• ICE related settings (ICE Lite/TCP, STUN/TURN, etc.)
• plugins, transports
• Media and transport plugins NOT to load
• events
• Event handlers settings
32. Configuring the core
• The Janus core is configured in janus.jcfg
• As anticipated, some properties can be overridden via command-line too
• Different categories that can be configured
• general
• General settings (logging, daemonization, etc.)
• certificates
• Certificate and key to use (DTLS only, autogenerated if missing)
• media
• Media related stuff (RTP range, DTLS mtu, etc.)
• nat
• ICE related settings (ICE Lite/TCP, STUN/TURN, etc.)
• plugins, transports
• Media and transport plugins NOT to load
• events
• Event handlers settings
33. Configuring the core
• The Janus core is configured in janus.jcfg
• As anticipated, some properties can be overridden via command-line too
• Different categories that can be configured
• general
• General settings (logging, daemonization, etc.)
• certificates
• Certificate and key to use (DTLS only, autogenerated if missing)
• media
• Media related stuff (RTP range, DTLS mtu, etc.)
• nat
• ICE related settings (ICE Lite/TCP, STUN/TURN, etc.)
• plugins, transports
• Media and transport plugins NOT to load
• events
• Event handlers settings
34. Configuring the core
• The Janus core is configured in janus.jcfg
• As anticipated, some properties can be overridden via command-line too
• Different categories that can be configured
• general
• General settings (logging, daemonization, etc.)
• certificates
• Certificate and key to use (DTLS only, autogenerated if missing)
• media
• Media related stuff (RTP range, DTLS mtu, etc.)
• nat
• ICE related settings (ICE Lite/TCP, STUN/TURN, etc.)
• plugins, transports
• Media and transport plugins NOT to load
• events
• Event handlers settings
35. Media/IP settings (media)
Name Value Description
ipv6 true/false Enable IPv6 for media or not
dtls_mtu int Maximum size of DTLS packets
dtls_timeout int Retransmission step in ms (BoringSSL only)
rtp_port_range min-max Range of ports to bind to for RTP/RTCP
rfc_4588 true/false Whether rtx should be supported
max_nack_queue int How many packets (window size in ms) to store for
retransmissions
no_media_timer int How long to wait (in seconds) before detecting no
incoming media
Considerations
• dtls_mtu and dtls_timeout can have an impact on DTLS handshake
• Make sure rtp_port_range reflects the server firewall, if any
36. Generic ICE settings (nat)
Name Value Description
ice_lite true/false Whether to use ICE Lite or not
ice_tcp true/false Whether to use ICE TCP or not (needs ICE Lite)
full_trickle true/false Whether Janus should do full-trickle or not
nat_1_1_mapping ip IP to replace host addresses with (e.g., AWS)
ice_enforce_list list List of interfaces/IPs (even partial) to gather on
ice_ignore_list list List of interfaces/IPs (even partial) NOT to gather on
nice_debug true/false Enable libnice debugging or not
Considerations
• ice_lite can be quicker, if the server has a public address
• Don’t mix nat_1_1_mapping and STUN, and only use it on AWS
• ice_enforce_list and ice_ignore_list can make gathering faster
37. STUN settings (nat)
Most of the times you won’t need STUN in Janus (only for users), but if you do...
Name Value Description
stun_server address Address of the STUN server
stun_port port Port of the STUN server
Considerations
• If Janus has a public address (common) or NAT-1-1, STUN makes things slower
• If Janus is NATted, check the type of NAT first
• STUN would most likely NOT work if it’s behind a symmetric NATs
38. TURN settings (nat)
Most of the times you won’t need TURN in Janus (only for users), but if you do...
Name Value Description
turn_server address Address of the TURN server
turn_port port Port of the TURN server
turn_type udp/tcp/tls Protocol to use to connect to the TURN server
turn_user string Username to authenticate, if needed
turn_pwd string Password to authenticate, if needed
Considerations
• 99% of the times, it’s users that need TURN, NOT Janus
• If Janus can work with host or STUN, TURN makes things MUCH slower
• Connections are much less efficient when TURN is used in Janus
39. TURN REST API settings (nat)
In case TURN credentials are not static, but ephemeral...
Name Value Description
turn_rest_api address Backend to contact for ephemeral credentials
turn_rest_api_key string API key to authenticate at the backend
turn_rest_api_method GET/POST HTTP method to use
Considerations
• As for TURN, plus the overhead of a new GET/POST per each PeerConnection
• Explicit TURN info and TURN REST API are mutually exclusive
40. A ton of scenarios done today with Janus!
• SIP and RTSP gatewaying
• WebRTC-based call/contact centers
• Conferencing & collaboration
• E-learning & webinars
• Cloud platforms
• Media production
• Broadcasting & Gaming
• Identity verification
• Internet of Things
• Augmented/Virtual Reality
• ...and more!
41. A quick look at plugins: EchoTest
https://janus.conf.meetecho.com/docs/echotest
42. A quick look at plugins: Record & Play
https://janus.conf.meetecho.com/docs/recordplay
43. A quick look at plugins: Record & Play
https://janus.conf.meetecho.com/docs/recordplay
44. A quick look at plugins: SIP gateway
https://janus.conf.meetecho.com/docs/sipsofia
45. A quick look at plugins: Audio MCU
https://janus.conf.meetecho.com/docs/audiobridge
46. A quick look at plugins: Video SFU
https://janus.conf.meetecho.com/docs/videoroom
47. A quick look at plugins: Streaming
https://janus.conf.meetecho.com/docs/streaming
48. Writing your own plugin in C (1)
• Plugin initialization and information
• init(): called when plugin is loaded
• destroy(): called when Janus is shutting down
• get_api_compatibility(): must return JANUS_PLUGIN_API_VERSION
• get_version(): numeric version identifier (e.g., 3)
• get_version_string(): verbose version identifier (e.g., “v1.0.1”)
• get_description(): verbose description of the plugin (e.g., “This is my awesome plugin
that does this and that”)
• get_name(): short display name for your plugin (e.g., “My Awesome Plugin”)
• get_author(): author of the plugin (e.g., “Meetecho s.r.l.”)
• get_package(): unique package identifier for your plugin (e.g., “janus.plugin.myplugin”)
49. Writing your own plugin in C (2)
• Sessions management (callbacks invoked by the core)
• create_session(): a user (session+handle) just attached to the plugin
• handle_message(): incoming message/request (with or without a JSEP/SDP)
• handle_admin_message(): incoming message/request from Admin API
• setup_media(): PeerConnection is now ready to be used
• incoming_rtp(): incoming RTP packet
• incoming_rtcp(): incoming RTCP message
• incoming_data(): incoming DataChannel message
• slow_link(): notification of problems on media path
• hangup_media(): PeerConnection has been closed (e.g., DTLS alert)
• query_session(): called to get plugin-specific info on a user session
• destroy_session(): existing user gone (handle detached)
50. Writing your own plugin in C (3)
• Interaction with the core (methods invoked by the plugin)
• push_event(): send the user a JSON message/event (with or without a JSEP/SDP)
• relay_rtp(): send/relay the user an RTP packet
• relay_rtcp(): send/relay the user an RTCP message
• relay_data(): send/relay the user a DataChannel message
• close_pc(): close the user’s PeerConnection
• end_session(): close a user session (force-detach core handle)
• events_is_enabled(): check whether the event handlers mechanism is enabled
• notify_event(): notify an event to the registered and subscribed event handlers
88. Anything wrong? Check the Admin API first!
• One option is the requests/response API to interrogate Janus
• Query server capabilities
• Control some aspects (e.g., enable/disable debugging)
• Inspect handles and WebRTC “internals”
https://www.meetecho.com/blog/understanding-the-janus-admin-api/
92. Admin API features: capturing traffic
https://www.meetecho.com/blog/capturing-webrtc-traffic-in-janus/
93. An asynchronous approach
• Admin API is cool, but is request/response...
• Needs constant polling, and data is unavailable after the session ends
• What about an asynchronous approach?
• A new mechanism: Event Handlers
• Core and plugins generate events
• Custom modules can subscribe to and handle them
• e.g., save to DB, send to external service, CDR, etc.
• Multiple handlers available out of the box
• HTTP, WebSockets, RabbitMQ, MQTT, Nanomsg
94. An asynchronous approach
• Admin API is cool, but is request/response...
• Needs constant polling, and data is unavailable after the session ends
• What about an asynchronous approach?
• A new mechanism: Event Handlers
• Core and plugins generate events
• Custom modules can subscribe to and handle them
• e.g., save to DB, send to external service, CDR, etc.
• Multiple handlers available out of the box
• HTTP, WebSockets, RabbitMQ, MQTT, Nanomsg
95. An asynchronous approach
• Admin API is cool, but is request/response...
• Needs constant polling, and data is unavailable after the session ends
• What about an asynchronous approach?
• A new mechanism: Event Handlers
• Core and plugins generate events
• Custom modules can subscribe to and handle them
• e.g., save to DB, send to external service, CDR, etc.
• Multiple handlers available out of the box
• HTTP, WebSockets, RabbitMQ, MQTT, Nanomsg
97. Type of events
• Different events handlers can subscribe to
• Core events (e.g., startup/shutdown)
• Session related events (e.g., session created/destroyed)
• Handle related events (e.g., handle attached/detached)
• JSEP related events (e.g., got/sent offer/answer)
• WebRTC related events (e.g., ICE/DTLS state changes)
• Media related events (e.g., stats on packets/bytes)
• Plugin-originated events (specific to the application)
• Transport-originated (specific to the transport)
• External events (originated via Admin API)
• Correlation possible on different identifiers
• Transport instances that originate specific session
• Opaque ID applications can set on handles of same “user”
• Plugin-specific identifiers (e.g., in VideoRoom)
98. Type of events
• Different events handlers can subscribe to
• Core events (e.g., startup/shutdown)
• Session related events (e.g., session created/destroyed)
• Handle related events (e.g., handle attached/detached)
• JSEP related events (e.g., got/sent offer/answer)
• WebRTC related events (e.g., ICE/DTLS state changes)
• Media related events (e.g., stats on packets/bytes)
• Plugin-originated events (specific to the application)
• Transport-originated (specific to the transport)
• External events (originated via Admin API)
• Correlation possible on different identifiers
• Transport instances that originate specific session
• Opaque ID applications can set on handles of same “user”
• Plugin-specific identifiers (e.g., in VideoRoom)
102. “Sample Event Handler”: HTTP as a notifier
• Simply forwards all events as JSON to an HTTP backend
• Supports basic authentication
• Can group events (i.e., JSON array vs. multiple JSON objects)
• Implements basic retransmissions (exponential back-off)
• Does nothing more than that: logic needs to be elsewhere
• HTTP backend decides what to do with events, if anything
• Behaviour can be tweaked via Admin API calls
Need something else? Check the alternatives or write your own!
A few other event handlers also available
• Other transports (in repo), SQLite (by Mozilla)
103. “Sample Event Handler”: HTTP as a notifier
• Simply forwards all events as JSON to an HTTP backend
• Supports basic authentication
• Can group events (i.e., JSON array vs. multiple JSON objects)
• Implements basic retransmissions (exponential back-off)
• Does nothing more than that: logic needs to be elsewhere
• HTTP backend decides what to do with events, if anything
• Behaviour can be tweaked via Admin API calls
Need something else? Check the alternatives or write your own!
A few other event handlers also available
• Other transports (in repo), SQLite (by Mozilla)
104. “Sample Event Handler”: HTTP as a notifier
• Simply forwards all events as JSON to an HTTP backend
• Supports basic authentication
• Can group events (i.e., JSON array vs. multiple JSON objects)
• Implements basic retransmissions (exponential back-off)
• Does nothing more than that: logic needs to be elsewhere
• HTTP backend decides what to do with events, if anything
• Behaviour can be tweaked via Admin API calls
Need something else? Check the alternatives or write your own!
A few other event handlers also available
• Other transports (in repo), SQLite (by Mozilla)
107. Writing your own event handler in C (1)
• Plugin initialization and information
• init(): called when event handler is loaded
• destroy(): called when Janus is shutting down
• get_api_compatibility(): must return JANUS_EVENTHANDLER_API_VERSION
• get_version(): numeric version identifier (e.g., 3)
• get_version_string(): verbose version identifier (e.g., “v1.0.1”)
• get_description(): verbose description of the plugin (e.g., “This is my awesome event
handler that does this and that”)
• get_name(): short display name for your plugin (e.g., “My Awesome Event Handler”)
• get_author(): author of the plugin (e.g., “Meetecho s.r.l.”)
• get_package(): unique package identifier for your plugin (e.g.,
“janus.eventhandler.myhandler”)
108. Writing your own event handler in C (2)
• Events management (callbacks invoked by the core)
• incoming_event(): incoming event to manage (queue and process in your thread)
• handle_request(): incoming request from Admin API to tweak the plugin
109. How can you handle events?
• Generating events is easy, evaluating them is another matter...
• Event Handlers typically just relay events, and don’t do processing themselves
• Analyzing and correlating tons of events is complicated
• A few different approaches, from easiest to trickiest
1 https://github.com/stirlab/janus-event-server (dumping events to file)
2 https://github.com/mozilla/janus-eventhandler-sqlite (dumping events to SQLite)
3 Write your own backend, e.g.,
https://www.meetecho.com/blog/event-handlers-a-practical-example/
https://www.meetecho.com/blog/correlating-janus-event-handlers/
• A much better approach: trust the smart guys!
• https://github.com/sipcapture/homer
• https://hepic.tel/
110. How can you handle events?
• Generating events is easy, evaluating them is another matter...
• Event Handlers typically just relay events, and don’t do processing themselves
• Analyzing and correlating tons of events is complicated
• A few different approaches, from easiest to trickiest
1 https://github.com/stirlab/janus-event-server (dumping events to file)
2 https://github.com/mozilla/janus-eventhandler-sqlite (dumping events to SQLite)
3 Write your own backend, e.g.,
https://www.meetecho.com/blog/event-handlers-a-practical-example/
https://www.meetecho.com/blog/correlating-janus-event-handlers/
• A much better approach: trust the smart guys!
• https://github.com/sipcapture/homer
• https://hepic.tel/
111. How can you handle events?
• Generating events is easy, evaluating them is another matter...
• Event Handlers typically just relay events, and don’t do processing themselves
• Analyzing and correlating tons of events is complicated
• A few different approaches, from easiest to trickiest
1 https://github.com/stirlab/janus-event-server (dumping events to file)
2 https://github.com/mozilla/janus-eventhandler-sqlite (dumping events to SQLite)
3 Write your own backend, e.g.,
https://www.meetecho.com/blog/event-handlers-a-practical-example/
https://www.meetecho.com/blog/correlating-janus-event-handlers/
• A much better approach: trust the smart guys!
• https://github.com/sipcapture/homer
• https://hepic.tel/