Fork me on GitHub
Event handlers documentation

Controlling and monitoring a Janus instance can be done using the Admin/Monitor API which includes ways to query information related to the state of ongoing PeerConnections (ICE/DTLS state, stats, etc.). That said, while powerful and useful the Admin API is a poll-based protocol: this means that you have to query for information yourself, and if you want to keep up-to-date with what is happening, you have to do that on a regular basis. As such, things can get problematic when dealing with many sessions and handles running in your application, as you may not be immediately aware of which session/handle corresponds to what, or which of them belong to the same scenario (e.g., all PeerConnections established in the context of the same VideoRoom).

This is where Event Handlers can help. Just like media and transport plugins, Event Handlers plugins in Janus themselves, meaning their modular nature allows for extensibility. When enabling Event handlers, Janus and other plugins generate real-time events related to several different aspects that may be happening during its lifetime: these events are then passed to all the available event handler plugins, plugins that can then decide to do with these events whatever they want. They might choose to store these events somehow, aggregate, dump or process them, format and send them to an external application, and so on. This really depends on what these events should be used for.

Janus will generate events related to:

  • session related events (e.g., session created/destroyed, etc.);
  • handle related events (e.g., handle attached/detached, etc.);
  • JSEP related events (e.g., got/sent offer/answer);
  • WebRTC related events (e.g., PeerConnection up/down, ICE updates, DTLS updates, etc.);
  • media related events (e.g., media started/stopped flowing, stats on packets/bytes, etc.);
  • generic events originated by the Janus core (e.g., Janus started/stopped);
  • events originated by plugins (content specific plugins themselves);
  • events originated by transports (see above);
  • events originated by external applications via the Admin API (content specific to source).

Events format

All events generated by Janus are JSON object, which have a shared header and a custom body that will depend on the type (and in some cases subtype) of the event itself.

The header of the event will contain some information that is usually common to all events: this includes type and (when needed) subtype of the event, a timestamp in microseconds (so that you can know exactly when the event was generated in the first place from the server's perspective, no matter it was received), and various IDs. These IDs include the session identifier (Janus session the event refers to), the handle identifier (Janus handle the event refers to) and an opaque ID (set by whoever controls the Janus API): as we'll see, all these IDs are optional, as there are events that are not related to a session in particular (e.g., a server shutdown event), but can be very important for correlation purposes when they're used.

The generic format of events is the following:

    {
        "emitter" : "<string identifying the source of the event, if configured (optional)>",
        "type" : <numeric event type identifier>,
        "subtype" : <numeric event subtype identifier (specific to the event type; optional)>,
        "timestamp" : <time of when the event was generated>,
        "session_id" : <unique session identifier, if provided/available (optional)>,
        "handle_id" : <unique handle identifier, if provided/available (optional)>,
        "opaque_id" : "<user-provided opaque identifier, if provided/available (optional)>",
        "event" : {
             <event body, custom depending on event type>
        }
    }

For instance, this is what an event related to a new session being created would look like:

    {
        "emitter": "MyJanusInstance",
        "type": 1,
        "timestamp": 1582211094846980,
        "session_id": 3439056127855429,
        "event": {
            "name": "created",
            "transport": {
                "transport": "janus.transport.http",
                "id": "0x60400002c2d0"
            }
        }
    }

Since type 1 is related to session events, this event basically tells us that a new session with ID 3439056127855429 was created (we know this from the name property in the event body) on the Janus instance called MyJanusInstance at the timestamp 1582211094846980 . There are no subtype , handle_id or opaque_id properties as they were unneeded or not applicable here.

Event types

As we've seen from the previous example, event types are numeric. In order to figure out what you're receiving, you can refer to the following table as a reference:

TypeCategory of event
1Session related event
2Handle related event
4External event (injected via Admin API)
8JSEP event (SDP offer/answer)
16WebRTC state event (ICE/DTLS states, candidates, etc.)
32Media event (media state, reports, etc.)
64Plugin-originated event (e.g., event coming from VideoRoom)
128Transport-originated event (e.g., WebSocket connection state)
256Core event (server startup/shutdown)

The types of events are not monotonically increasing as, internally, they're represented as a mask: this allows event handler plugins to only subscribe to a subset of them, rather than them all, when needed.

The event type property dictates the syntax of the event body , meaning that the body for a JSEP event (type 8 ) will for instance be very different from a media event (type 32 ). That said, the format of some events can change even within the same type: for instance, a WebRTC state event includes a lot of different notifications, including ICE states, DTLS states, local and remote candidates, selected pair, etc. In order to allow event handler recipients written in strongly typed languages to be able to use different classes for the different events, a different property called subtype can help further discriminate an event of a specified type. At the time of writing, a subtype attribute will only be present if the event is of type 256 (core), 16 (WebRTC) and 32 (media): all other event types have a consistent format, and so don't need this differentiation (e.g., type 8 includes both SDP offers and answers, but the nature of the SDP is indicated in an attribute that has the same name in both cases).

The available subtypes are the following:

Core subtype
1Server startup
2Server shutdown
WebRTC subtype
1ICE state
2Local candidate
3Remote candidate
4Selected pair
5DTLS state
6PeerConnection state
Media subtype
1Medium state
2Slow link
3Report/stats