["trace", "warn"]
): only enable selected debuggers (allowed tokens: trace, debug, log, warn, error)
* - \c false: disable all debuggers
* - \c callback: a user provided function that is invoked when the initialization is complete
* - \c dependencies: a user provided implementation of Janus library dependencies
*
* Here's an example:
*
*
\verbatim
Janus.init({
debug: true,
dependencies: Janus.useDefaultDependencies(), // or: Janus.useOldDependencies() to get the behaviour of previous Janus versions
callback: function() {
// Done!
});
\endverbatim
*
* \note When using one of the JavaScript module variants of \c janus.js, you
* will need to import the \c Janus symbol from the module first. See also: \ref js-modules
* For example, using the ECMAScript module variant, the above example should be altered to:
*
*
\verbatim
import * as Janus from './janus.es.js'
Janus.init({
debug: true,
dependencies: Janus.useDefaultDependencies(), // or: Janus.useOldDependencies() to get the behaviour of previous Janus versions
callback: function() {
// Done!
});
});
\endverbatim
*
* Once the library has been initialized, you can start creating sessions.
* Normally, each browser tab will need a single session with the server: in
* fact, each Janus session can contain several different plugin handles
* at the same time, meaning you can start several different WebRTC sessions
* with the same or different plugins for the same user using the same
* Janus session. That said, you're free to set up different Janus
* sessions in the same page, should you prefer so.
*
* Creating a session is quite easy. You just need to use the \c new constructor
* to create a new \c Janus object that will handle your interaction with the
* server. Considering the dynamic and asynchronous nature of Janus sessions
* (events may occur at any time), there are several properties and callbacks you
* can configure when creating a session:
*
* - \c server: the address of the server as a specific address (e.g.,
* http://yourserver:8088/janus to use the plain HTTP API or ws://yourserver:8188/
* for WebSockets) or as an array of addresses to try sequentially to allow
* automatic for fallback/failover during setup;
* - \c iceServers: a list of STUN/TURN servers to use (a default STUN server
* will be used if you skip this property);
* - \c ipv6: whether IPv6 candidates should be gathered or not;
* - \c withCredentials: whether the \c withCredentials property of XHR requests
* should be enabled or not (false by default, and only valid when using HTTP
* as a transport, ignored for WebSockets);
* - \c max_poll_events: the number of events that should be returned when polling;
* the default is 1 (polling returns an object), passing a higher number will
* have the backend return an array of objects instead (again, only valid for
HTTP usage as this is strictly related to long polling, ignored for WebSockets);
* - \c destroyOnUnload: whether we should destroy automatically try and
* destroy this session via Janus API when \c onbeforeunload is called (true by default);
* - \c token , \c apisecret: optional parameters only needed in case you're \ref auth ;
* - a set of callbacks to be notified about events, namely:
* - \c success: the session was successfully created and is ready to be used;
* - \c error: the session was NOT successfully created;
* - \c destroyed: the session was destroyed and can't be used any more.
*
* These properties and callbacks are passed to the method as properties
* of a single parameter object: that is, the \c Janus constructor takes a
* single parameter, which although acts as a container for all the available
* options. The \c success callback is where you tipically start your application
* logic, e.g., attaching the peer to a plugin and start a media session.
*
* Here's an example:
*
\verbatim
var janus = new Janus(
{
server: 'http://yourserver:8088/janus',
success: function() {
// Done! attach to plugin XYZ
},
error: function(cause) {
// Error, can't go on...
},
destroyed: function() {
// I should get rid of this
}
});
\endverbatim
*
* As anticipated, the server may be a specific address, e.g.:
*
\verbatim
var janus = new Janus(
{
server: 'http://yourserver:8088/janus',
// or
server: 'ws://yourserver:8188/',
[..]
\endverbatim
*
* or an array of addresses. Such an array can be especially useful if
* you want the library to first check if the WebSockets server is
* reachable and, if not, fallback to plain HTTP, or just to provide
* a link multiple instances to try for failover. This is an example of
* how to pass a 'try websockets and fallback to HTTP' array:
*
\verbatim
var janus = new Janus(
{
server: ['ws://yourserver:8188/','http://yourserver:8088/janus'],
[..]
\endverbatim
*
* Once created, this object represents your session with the server.
* you can interact with a \c Janus object in several different ways.
* In particular, the following properties and methods are defined:
*
* - \c getServer(): returns the address of the server;
* - \c isConnected(): returns \c true if the Janus instance is connected
* to the server, \c false otherwise;
* - \c getSessionId(): returns the unique Janus session identifier;
* - \c attach(parameters): attaches the session to a plugin, creating an handle;
* more handles to the same or different plugins can be created at the same time;
* - \c destroy(parameters): destroys the session with the server, and closes
* all the handles (and related PeerConnections) the session may have with any plugin as well.
*
* The most important property is obviously the \c attach() method, as
* it's what will allow you to exploit the features of a plugin to manipulate
* the media sent and/or received by a PeerConnection in your web page.
* This method will create a plugin handle you can use for the purpose,
* for which you can configure properties and callbacks when calling the
* \c attach() method itself. As for the \c Janus constructor, the \c attach()
* method takes a single parameter that can contain any of the following
* properties and callbacks:
*
* - \c plugin: the unique package name of the plugin (e.g., \c janus.plugin.echotest );
* - \c opaqueId: an optional opaque string meaningful to your application (e.g., to map all the handles of the same user);
* - a set of callbacks to be notified about events, namely:
* - \c success: the handle was successfully created and is ready to be used;
* - \c error: the handle was NOT successfully created;
* - \c consentDialog: this callback is triggered just before \c getUserMedia is called
* (parameter=true) and after it is completed (parameter=false); this means it can
* be used to modify the UI accordingly, e.g., to prompt the user about the need to accept the device access consent requests;
* - \c webrtcState: this callback is triggered with a true value
* when the PeerConnection associated to a handle becomes active (so ICE, DTLS and
* everything else succeeded) from the Janus perspective, while false is
* triggered when the PeerConnection goes down instead; useful to figure out
* when WebRTC is actually up and running between you and Janus (e.g., to notify
* a user they're actually now active in a conference); notice that in case
* of false a reason string may be present as an optional parameter;
* - \c iceState: this callback is triggered when the ICE state for the
* PeerConnection associated to the handle changes: the argument of the callback
* is the new state as a string (e.g., "connected" or "failed");
* - \c mediaState: this callback is triggered when Janus starts or stops
* receiving your media: for instance, a \c mediaState with type=audio and
* on=true means Janus started receiving your audio stream (or started
* getting them again after a pause of more than a second); a \c mediaState with
* type=video and on=false means Janus hasn't received any video
* from you in the last second, after a start was detected before; useful to
* figure out when Janus actually started handling your media, or to detect
* problems on the media path (e.g., media never started, or stopped at some time);
* - \c slowLink: this callback is triggered when Janus reports trouble
* either sending or receiving media on the specified PeerConnection, typically
* as a consequence of too many NACKs received from/sent to the user in the
* last second: for instance, a \c slowLink with uplink=true means
* you notified several missing packets from Janus, while uplink=false
* means Janus is not receiving all your packets; useful to figure out when
* there are problems on the media path (e.g., excessive loss), in order to
* possibly react accordingly (e.g., decrease the bitrate if most of our
* packets are getting lost);
* - \c onmessage: a message/event has been received from the plugin;
* - \c onlocalstream: a local \c MediaStream is available and ready to be displayed;
* - \c onremotestream: a remote \c MediaStream is available and ready to be displayed;
* - \c ondataopen: a Data Channel is available and ready to be used;
* - \c ondata: data has been received through the Data Channel;
* - \c oncleanup: the WebRTC PeerConnection with the plugin was closed;
* - \c detached: the plugin handle has been detached by the plugin itself,
* and so should not be used anymore.
*
* Here's an example:
*
\verbatim
// Attach to echo test plugin, using the previously created janus instance
janus.attach(
{
plugin: "janus.plugin.echotest",
success: function(pluginHandle) {
// Plugin attached! 'pluginHandle' is our handle
},
error: function(cause) {
// Couldn't attach to the plugin
},
consentDialog: function(on) {
// e.g., Darken the screen if on=true (getUserMedia incoming), restore it otherwise
},
onmessage: function(msg, jsep) {
// We got a message/event (msg) from the plugin
// If jsep is not null, this involves a WebRTC negotiation
},
onlocalstream: function(stream) {
// We have a local stream (getUserMedia worked!) to display
},
onremotestream: function(stream) {
// We have a remote stream (working PeerConnection!) to display
},
oncleanup: function() {
// PeerConnection with the plugin closed, clean the UI
// The plugin handle is still valid so we can create a new one
},
detached: function() {
// Connection with the plugin closed, get rid of its features
// The plugin handle is not valid anymore
}
});
\endverbatim
*
* So the \c attach() method allows you to attach to a plugin, and specify
* the callbacks to invoke when anything relevant happens in this interaction.
* To actively interact with the plugin, you can use the \c Handle object
* that is returned by the \c success callback (pluginHandle in the example).
*
* This \c Handle object has several methods you can use to interact with
* the plugin or check the state of the session handle:
*
* - \c getId(): returns the unique handle identifier;
* - \c getPlugin(): returns the unique package name of the attached plugin;
* - \c send(parameters): sends a message (with or without a jsep to
* negotiate a PeerConnection) to the plugin;
* - \c createOffer(callbacks): asks the library to create a WebRTC compliant OFFER;
* - \c createAnswer(callbacks): asks the library to create a WebRTC compliant ANSWER;
* - \c handleRemoteJsep(callbacks): asks the library to handle an incoming WebRTC compliant session description;
* - \c dtmf(parameters): sends a DTMF tone on the PeerConnection;
* - \c data(parameters): sends data through the Data Channel, if available;
* - \c getBitrate(): gets a verbose description of the currently received stream bitrate;
* - \c hangup(sendRequest): tells the library to close the PeerConnection; if the optional \c sendRequest argument is
* set to \c true, then a \c hangup Janus API request is sent to Janus as well (disabled by default, Janus can usually
* figure this out via DTLS alerts and the like but it may be useful to enable it sometimes);
* - \c detach(parameters): detaches from the plugin and destroys the handle, tearing
* down the related PeerConnection if it exists.
*
* While the \c Handle API may look complex, it's actually quite straightforward
* once you get the concept. The only step that may require a little more
* effort to understand is the PeerConnection negotiation, but again, if
* you're familiar with the WebRTC API, the \c Handle actually makes it
* a lot easier.
*
* The idea behind it's usage is the following:
*
* -# you use \c attach() to create a \c Handle object;
* -# in the \c success callback, your application logic can kick in: you may
* want to send a message to the plugin (send({msg})
), negotiate
* a PeerConnection with the plugin right away ( \c createOffer followed
* by a send({msg, jsep})
) or wait for something to happen to do anything;
* -# the \c onmessage callback tells you when you've got messages from the plugin;
* if the \c jsep parameter is not null, just pass it to the library, which will take
* care of it for you; if it's an \b OFFER use \c createAnswer (followed by a
* send({msg, jsep})
to close the loop with the plugin), otherwise use
* \c handleRemoteJsep ;
* -# whether you took the initiative to set up a PeerConnection or the plugin did,
* the \c onlocalstream and/or the \c onremotestream callbacks will provide
* you with a stream you can display in your page;
* -# each plugin may allow you to manipulate what should flow through the
* PeerConnection channel: the \c send method and \c onmessage callback
* will allow you to handle this interaction (e.g., to tell the plugin
* to mute your stream, or to be notified about someone joining a virtual room),
* while the \c ondata callback is triggered whenever data is received
* on the Data Channel, if available (and the \c ondataopen callback
* will tell you when a Data Channel is actually available).
*
* The following paragraphs will delve a bit deeper in the negotiation
* mechanism provided by the \c Handle API, in particular describing
* the properties and callbacks that may be involved. To follow the approach
* outlined by the W3C WebRTC API, this negotiation mechanism is heavily
* based on asynchronous methods as well. Notice that the following paragraphs
* address the first negotiation step, that is the one to create a new
* PeerConnection from scratch: to know how to originate or handle a
* renegotiation instead (e.g., to add/remove/replace a media source, or
* force an ICE restart) check the \ref renegotiation section instead.
*
* - \c createOffer takes a single parameter, that can contain any of the
* following properties and callbacks:
* - \c media: you can use this property to tell the library which media (audio/video/data)
* you're interested in, and whether you're going to send and/or receive any of them; by default
* audio and video are enabled in both directions, while the Data Channels are disabled;
* this option is an object that can take any of the following properties:
* - \c audioSend: \c true/false (do or do not send audio);
* - \c audioRecv: \c true/false (do or do not receive audio);
* - \c audio: \c true/false (do or do not send \b and receive audio, takes precedence on the above);
* - \c audio: object with \c deviceId property (specify ID of audio device to capture, takes precedence on the above;
* devices list can be accessed with \c Janus.listDevices(callback) );
* - \c videoSend: \c true/false (do or do not send video);
* - \c videoRecv: \c true/false (do or do not receive video);
* - \c video: \c true/false (do or do not send \b and receive video, takes precedence on the above);
* - \c video: \c "lowres"/"lowres-16:9"/"stdres"/"stdres-16:9"/"hires"/"hires-16:9"
* (send a 320x240/320x180/640x480/640x360/1280x720 video, takes precedence on the above; default is \c "stdres" )
* this property will affect the resulting getUserMedia that the library will issue; please
* notice that Firefox doesn't support the \c "16:9" variants, which will fallback
* to the ones; besides, \c "hires" and \c "hires-16:9" are currently synonymous, as
* there's no 4:3 high resolution constraint as of now;
* - \c video: \c "screen" (use screensharing for video, disables audio, takes precedence on both audio and video);
* - \c video: object with \c deviceId , \c width and/or \c height properties (specify ID of video device to capture
* and optionally resolution to use, takes precedence on the above; devices list can be accessed with \c Janus.listDevices(callback) );
* - \c data: \c true/false (do or do not use Data Channels, default is false)
* - \c failIfNoAudio: \c true/false (whether a getUserMedia should fail if audio send is asked, but no audio device is available, default is false)
* - \c failIfNoVideo: \c true/false (whether a getUserMedia should fail if video send is asked, but no video device is available, default is false)
* - \c screenshareFrameRate: in case you're sharing a screen/application, allows you to specify the framerate (default=3);
* - \c trickle: \c true/false, to tell the library whether you want
* Trickle ICE to be used (true, the default) or not (false);
* - \c stream: optional, only to be passed in case you obtained a MediaStream object yourself with a \c getUserMedia
* request, and that you want the library to use instead of having it get one by itself (makes
* the \c media property useless, as it won't be read for accessing any device);
* - a set of callbacks to be notified about the result, namely:
* - \c success: the session description was created (attached as a parameter) and is ready to be sent to the plugin;
* - \c error: the session description was NOT successfully created;
* - \c customizeSdp: you can modify the sdp generated by the webrtc engine if you need;
* - \c createAnswer takes the same options as createOffer, but requires
* an additional one as part of the single parameter argument:
* - \c jsep: the session description sent by the plugin (e.g., as received
* in an \c onmessage callback) as its OFFER.
*
* Whether you use \c createOffer or \c createAnswer depending on the scenario,
* you should end up with a valid \c jsep object returned in the \c success
* callback. You can attach this \c jsep object to a message in a \c send request
* to pass it to the plugin, and have Janus negotiate a PeerConnection
* with your application.
*
* Here's an example of how to use \c createOffer, taken from the Echo Test demo page:
*
\verbatim
// Attach to echo test plugin
janus.attach(
{
plugin: "janus.plugin.echotest",
success: function(pluginHandle) {
// Negotiate WebRTC
echotest = pluginHandle;
var body = { "audio": true, "video": true };
echotest.send({"message": body});
echotest.createOffer(
{
// No media property provided: by default,
// it's sendrecv for audio and video
success: function(jsep) {
// Got our SDP! Send our OFFER to the plugin
echotest.send({"message": body, "jsep": jsep});
},
error: function(error) {
// An error occurred...
},
customizeSdp: function(jsep) {
// if you want to modify the original sdp, do as the following
// oldSdp = jsep.sdp;
// jsep.sdp = yourNewSdp;
}
});
},
[..]
onmessage: function(msg, jsep) {
// Handle msg, if needed, and check jsep
if(jsep !== undefined && jsep !== null) {
// We have the ANSWER from the plugin
echotest.handleRemoteJsep({jsep: jsep});
}
},
[..]
onlocalstream: function(stream) {
// Invoked after createOffer
// This is our video
},
onremotestream: function(stream) {
// Invoked after handleRemoteJsep has got us a PeerConnection
// This is the remote video
},
[..]
\endverbatim
*
* This, instead, is an example of how to use \c createAnswer, taken from the Streaming demo page:
*
\verbatim
// Attach to echo test plugin
janus.attach(
{
plugin: "janus.plugin.streaming",
success: function(pluginHandle) {
// Handle created
streaming = pluginHandle;
[..]
},
[..]
onmessage: function(msg, jsep) {
// Handle msg, if needed, and check jsep
if(jsep !== undefined && jsep !== null) {
// We have an OFFER from the plugin
streaming.createAnswer(
{
// We attach the remote OFFER
jsep: jsep,
// We want recvonly audio/video
media: { audioSend: false, videoSend: false },
success: function(ourjsep) {
// Got our SDP! Send our ANSWER to the plugin
var body = { "request": "start" };
streaming.send({"message": body, "jsep": ourjsep});
},
error: function(error) {
// An error occurred...
}
});
}
},
[..]
onlocalstream: function(stream) {
// This will NOT be invoked, we chose recvonly
},
onremotestream: function(stream) {
// Invoked after send has got us a PeerConnection
// This is the remote video
},
[..]
\endverbatim
*
* Of course, these are just a couple of examples where the scenarios
* assumed that one plugin would only receive (Echo Test) or generate
* (Streaming) offers. A more complex example (e.g., a Video Call plugin)
* would involve both, allowing you to either send offers to a plugin,
* or receive some from them. Handling this is just a matter of checking
* the \c type of the \c jsep object and reacting accordingly.
*
* \section renegotiation Updating an existing PeerConnection (renegotiations)
* While the JavaScript APIs described above will suffice for most of the
* common scenarios, there are cases when updates on a PeerConnection may
* be needed. This can happen whenever, for instance, you want to add a
* new media source (e.g., add video to an audio only call), replace an
* existing one (e.g., switch from capturing the camera to sharing your
* screen), or trigger an ICE restart because of a network change. All
* these actions require a renegotiation to occur, which means a new SDP
* offer/answer round to update the existing PeerConnection.
*
* Since version \c 0.2.6, renegotiations are indeed supported by Janus,
* and the \c janus.js library exposes ways to easily handle the process
* of updating a media session. More specifically, there are additional
* properties you can pass to \c createOffer and \c createAnswer for the
* purpose: most of the properties introduced in the previous section will
* still be usable, as it will be clearer in the next paragraphs.
*
* The new properties you can pass to \c media in \c createOffer and
* \c createAnswer are the following:
*
* - \c addAudio: if set, start capturing audio if you weren't (will fail
* if you're sending audio already);
* - \c addVideo: if set, start capturing video if you weren't (will fail
* if you're sending video already);
* - \c addData: if set, negotiate a datachannel if it didn't exist (is
* actually just a synonym for \c data:true );
* - \c removeAudio: if set, stop capturing audio and remove the local audio track;
* - \c removeVideo: if set, stop capturing video and remove the local video track;
* - \c replaceAudio: if set, stop capturing the current audio (remove the
* local audio track), and capture a new audio source;
* - \c replaceVideo: if set, stop capturing the current video (remove the
* local video track), and capture a new video source.
*
* Notice that these properties are only processed when you're trying a
* renegotiation, and will be ignored when creating a new PeerConnection.
*
* These properties don't replace the existing \c media properties, but go
* along with them. For instance, when adding a new video stream, or
* replacing an existing one, you can still use the video related properties
* as before, e.g., to pass a specific device ID or asking for a screenshare
* instead of a camera. Besides, notice that you'll currently have to pass
* info on the streams you want to keep as well, or they might be removed:
* this means that, if for instance you want to replace the video source,
* but want to keep the audio as it is, passing \c audio:false to the new
* createOffer will potentially disable audio.
*
* It's important to point out that, as for negotiations that result in
* the creation of a new PeerConnection in the first place, how to perform
* a renegotiation in practice will typically vary depending on the plugin
* that you're trying to do it for. Some plugins may allow you to offer
* a renegotiation, others may require you to send a different request
* instead in order to trigger a renegotiation from the plugin. As it
* will be clearer later, this is especially true for ICE restarts. As
* such, apart from the generic and core-related definitions introduced
* in this section, please refer to the documentation for each individual
* plugin for more information about how to perform renegotiations in
* specific use cases.
*
* Here's a simple example of how you can use \c removeVideo to remove
* the local video capture in a session, e.g., in the EchoTest demo:
*
\verbatim
// Remove local video
echotest.createOffer(
{
media: { removeVideo: true },
success: function(jsep) {
Janus.debug(jsep);
echotest.send({message: {audio: true, video: true}, "jsep": jsep});
},
error: function(error) {
bootbox.alert("WebRTC error... " + JSON.stringify(error));
}
});
\endverbatim
*
* This other example shows how you can add a new video stream to an-audio
* only PeerConnection instead:
*
\verbatim
// Add local video
echotest.createOffer(
{
media: { addVideo: true },
success: function(jsep) {
Janus.debug(jsep);
echotest.send({message: {audio: true, video: true}, "jsep": jsep});
},
error: function(error) {
bootbox.alert("WebRTC error... " + JSON.stringify(error));
}
});
\endverbatim
*
* Finally, this example shows how you can replace the video track, by
* also showing how you can combine this with one of the properties we
* already met in the previous section:
*
\verbatim
// Replace local video
echotest.createOffer(
{
media: {
video: {
deviceId: "44f4740bee234ce6ddcfea8e59e8ed7505054f75edf27e3a12294686b37ff6a7"
},
replaceVideo: true
},
success: function(jsep) {
Janus.debug(jsep);
echotest.send({message: {audio: true, video: true}, "jsep": jsep});
},
error: function(error) {
bootbox.alert("WebRTC error... " + JSON.stringify(error));
}
});
\endverbatim
*
* Notice that renegotiations involving media changes (both local and remote)
* will likely result in new calls to the \c onlocalstream and \c onremotestream
* application callbacks: as such, be prepared to see those callbacks called
* for the same PeerConnection more than once during the course of a media session.
*
* \section restarts ICE restarts
* While ICE restarts can be achieved with a renegotiation, they're complex
* enough to deserve a specific subsection. In fact, ICE restarts don't
* address changes in the media, but in the underlying transport itself.
* They're used, for instance, when there's a network change (e.g., the
* IP address changed, or the user switched from WiFi to 4G). In order for
* this to work, new candidates must be exchanged, and connectivity checks
* must be restarted in order to find the new optimal path.
*
* With \c janus.js, you can only force an ICE restart when sending a new
* offer. In order to do so, all you need to do is add `iceRestart:true`
* to your `createOffer` call, and an ICE restart will be requested. The
* following example shows how this can be done with the EchoTest:
*
\verbatim
echotest.createOffer({
iceRestart: true,
media: { data: true },
success: function(jsep) {
echotest.send({message: {audio: true, video: true}, jsep: jsep});
}
});
\endverbatim
*
* In this particular example, we're not asking for any change on the
* media streams, but just an ICE restart. If successful, as soon as the
* answer is received, the client and Janus will restart the ICE process
* and find a new path for the media packets.
*
* Notice that, with Janus and its plugins, you won't always be able to
* force an ICE restart by sending a new SDP offer yourself: some plugins,
* like the Streaming plugin for instance, will want to always send an
* offer themselves, which means they'll be the ones actually forcing the
* ICE restart from a negotiation perspective. In order to still allow
* users to actually originate the process, all the stock Janus plugins
* that assume they'll be sending offers for some or all of their media
* streams also expose APIs to force an ICE restart from the server side.
* You can learn more about this on a plugin level basis
* here and
* here.
* Besides, make sure you read the documentation for each of the plugins
* you're interested in using ICE restarts for, as the details for how
* to perform it properly are typically provided there.
*
* Module format (syntax) | File name | configure flag to pass |
---|---|---|
ECMAScript | janus.es.js | \c --enable-javascript-es-module |
Universal Module Definition (UMD) | janus.umd.js | \c --enable-javascript-umd-module |
CommonJS | janus.cjs.js | \c --enable-javascript-common-js-module |
Immediately Invoked Function Expression (IIFE) | janus.iife.js | \c --enable-javascript-iffe-module |
"trickle" : false
* attribute to the "jsep" object, to explicitly tell Janus you won't
* send any \c trickle candidate (by default Janus will always assume
* support for trickle).
*
* If you're going to \c trickle candidates, instead, there is an ad-hoc
* message you can use to do so which is called, unsurprisingly, \c trickle
* and which you can use to send one or more trickle candidates to Janus.
* Since such a message is related to a specific PeerConnection, it will
* need to be addressed to the right Handle just as the \c message introduced
* previously. A \c trickle message can contain three different kind of
* information:
*
* - a single trickle candidate;
* - an array of trickle candidates;
* - a null candidate or a \c completed JSON object to notify the end of the
* candidates.
*
* This is an example of a single candidate being trickled:
*
\verbatim
{
"janus" : "trickle",
"transaction" : "hehe83hd8dw12e",
"candidate" : {
"sdpMid" : "video",
"sdpMLineIndex" : 1,
"candidate" : "..."
}
}
\endverbatim
*
* This, instead, is an example of how to group more trickle candidates
* in a single request (particularly useful if you're wrapping Janus in
* your server and want to reduce the number of transactions):
*
\verbatim
{
"janus" : "trickle",
"transaction" : "hehe83hd8dw12e",
"candidates" : [
{
"sdpMid" : "video",
"sdpMLineIndex" : 1,
"candidate" : "..."
},
{
"sdpMid" : "video",
"sdpMLineIndex" : 1,
"candidate" : "..."
},
[..]
]
}
\endverbatim
*
* Finally, this is how you can tell Janus that you sent all the trickle
* candidates that were gathered:
*
\verbatim
{
"janus" : "trickle",
"transaction" : "hehe83hd8dw12e",
"candidate" : {
"completed" : true
}
}
\endverbatim
*
* Plugins may handle this requests synchronously or asynchronously. In
* the former, plugins would return a response to the request itself
* immediately; in the latter, instead, the plugin would only notify a
* successful reception of the request, which it would process later.
* Considering the asynchronous nature of the Janus API, a successful
* management of such messages within Janus would in such case result in
* a \c janus "ack" messages being sent back to the client. A logical response
* to those messages, if needed, would be provided as an event in the
* long-poll interface described previously, and clients would be able
* to match it to the original request by means of the transaction
* identifiers. It is worth noting, though, that should a WebRTC negotiation
* be involved you don't have to expect an ANSWER to your OFFER to be
* sent back in the same transaction. A plugin may decide, in its
* application logic, to not provide you with an ANSWER right away, but
* only after some internal state changes occur. It's up to your application
* to handle the negotiation state accordingly.
*
* An example of an "ack" being sent back to the client, using the previous
* sample request as a reference, is presented here:
*
\verbatim
{
"janus" : "ack",
"transaction" : "sBJNyUhH6Vc6"
}
\endverbatim
*
* If you receive this ack instead of a "success" response, you can be
* sure the plugin has received the message, and is going to process it soon.
*
* In case of an error, instead, you'll receive an error message as the one
* introduced before. This request, if issued with a POST to a valid plugin
* handle endpoint, can only fail if you miss any of the required fields
* in the request, if the plugin you tried to contact is not available in
* the server anymore, if an error occurred in the plugin when trying to
* receive the message or if the \c jsep SDP you may have provided is
* invalid.
*
* To destroy the plugin handle, instead, just send a "detach" \c janus
* request:
*
\verbatim
{
"janus" : "detach",
"transaction" : "janus-admin-protocol
* as the subprotocol, instead of the janus-protocol
of the
* regular Janus API.
*
* \section adminreq Admin API requests
* There are several different requests that this API implementents, so,
* to make this documentation easier to read and the functionality easier
* to identify, we can group requests depending on what they provide.
*
* \subsection adminreqg Generic requests
* - \c info: get the generic on the Janus instance; this returns exactly
* the same information that a Janus API \c info request would return,
* and doesn't require any secret;
* - \c ping: a simple ping/pong mechanism for the Admin API, that returns
* a \c pong back that the client can use as a healthcheck or to measure
* the protocol round-trip time; together with the \c info request introduced
* above, it's the only one that doesn't require a secret.
*
* \subsection adminreqc Configuration-related requests
* - \c get_status: returns the current value for the settings that can be
* modified at runtime via the Admin API (see below);
* - \c set_session_timeout: change the session timeout value in Janus;
* - \c set_log_level: change the log level in Janus;
* - \c set_log_timestamps: selectively enable/disable adding a timestamp
* to all log lines Janus writes on the console and/or to file;
* - \c set_log_colors: selectively enable/disable using colors in all
* log lines Janus writes on the console and/or to file;
* - \c set_locking_debug: selectively enable/disable a live debugging of
* the locks in Janus on the fly (useful if you're experiencing deadlocks
* and want to investigate them);
* - \c set_refcount_debug: selectively enable/disable a live debugging of
* the reference counters in Janus on the fly (useful if you're experiencing
* memory leaks in the Janus structures and want to investigate them);
* - \c set_libnice_debug: selectively enable/disable libnice debugging;
* - \c set_min_nack_queue: change the value of the min NACK queue window;
* - \c set_no_media_timer: change the value of the no-media timer property;
* - \c set_slowlink_threshold: change the value of the slowlink-threshold property.
*
* \subsection adminreqt Token-related requests
* - \c add_token: add a valid token (only available if you enabled the \ref token);
* - \c allow_token: give a token access to a plugin (only available if you enabled the \ref token);
* - \c disallow_token: remove a token access from a plugin (only available if you enabled the \ref token);
* - \c list_tokens: list the existing tokens (only available if you enabled the \ref token);
* - \c remove_token: remove a token (only available if you enabled the \ref token).
*
* \subsection adminreqs Session-related requests
* - \c accept_new_sessions: configure whether Janus should accept new
* incoming sessions or not; this can be particularly useful whenever, e.g.,
* you want to stop accepting new sessions because you're draining this instance;
* - \c list_sessions: list all the sessions currently active in Janus
* (returns an array of session identifiers);
* - \c destroy_session: destroy a specific session; this behaves exactly
* as the \c destroy request does in the Janus API.
*
* \subsection adminreqh Handle- and WebRTC-related requests
* - \c list_handles: list all the ICE handles currently active in a Janus
* session (returns an array of handle identifiers);
* - \c handle_info: list all the available info on a specific ICE handle;
* if a \c plugin_only property is set to \c true then only the plugin-specific
* information is returned, excluding the more verbose WebRTC info and stats;
* - \c start_pcap: start dumping incoming and outgoing RTP/RTCP packets
* of a handle to a pcap file (e.g., for ex-post analysis via Wireshark);
* - \c stop_pcap: stop the pcap dump;
* - \c start_text2pcap: same as above, but saves to a text file instead,
* to be fed to \c text2pcap in order to generate a \c .pcap or \c .pcapng file;
* - \c stop_text2pcap: stop the text2pcap dump;
* - \c message_plugin: send a synchronous request to a plugin and return a
* response; implemented by most plugins to facilitate and streamline the
* management of plugin resources (e.g., creating rooms in a conference plugin);
* - \c hangup_webrtc: hangups the PeerConnection associated with a specific
* handle; this behaves exactly as the \c hangup request does in the Janus API.
* - \c detach_handle: detached a specific handle; this behaves exactly
* as the \c detach request does in the Janus API.
*
* \subsection adminreqe Event handlers-related requests
* - \c query_eventhandler: send a synchronous request to an event handler and
* return a response; implemented by most event handlers to dynamically
* configure some of their properties;
* - \c custom_event: push a custom "external" event to notify via event handlers;
* this can be useful whenever info from a third-party application needs to be
* easily correlated to events originated by Janus, or to push information
* Janus doesn't have available (e.g., a script polling CPU usage regularly).
*
* \subsection adminreql Custom logging-related requests
* - \c custom_logline: push a custom "external" string to print on the logs;
* this can be useful whenever info from a third-party application needs to be
* injected in the Janus logs for whatever reason. The log level can be chosen.
*
* \subsection adminreqz Helper requests
* - \c resolve_address: helper request to evaluate whether this Janus instance
* can resolve an address via DNS, and how long it takes;
* - \c test_stun: helper request to evaluate whether this Janus instance
* can contact a STUN server, what is returned, and how long it takes.
*
* \section adminsyntax Admin API syntax
* Following the same spirit of the \ref rest these methods need to be
* invoked on the right path and/or providing the right \c session_id and
* \c handle_id identifiers. Specifically, the following requests must be invoked
* without any session/handle information, as they're global requests:
*
* - \c info , \c ping , \c get_status , all the configuration setters, all
* the token requests, all the event-handler related requests, all the
* helper requests, \c accept_new_sessions and \c list_sessions
*
* Here's an example of how such a request and its related response might look like:
*
\verbatim
POST /admin
{
"janus" : "list_sessions",
"transaction" : "wss://myserver/janus-ws
* or ws://myserver/janus-ws
address, and have all communication
* forwarded to and from Janus at ws://127.0.0.1:8188
.
*
* Similar configurations are probably available for other systems as well,
* so in case this is something you're interested in, we recommend you
* follow the best practices related to that made available by the web server developers.
*
* \section both Using fallback addresses
* As anticipated in the \ref JS section, you can also pass an array of servers
* to the Janus library initialization. This allows you, for instance, to
* pass a link to both the WebSockets and REST interfaces, and have the
* library try them both to see which one is reachable, e.g.:
*
\verbatim
var ws_server = "ws://" + window.location.hostname + ":8188/";
var http_server = "http://" + window.location.hostname + ":8088/janus";
var servers = [ws_server, http_server];
\endverbatim
*
* which is especially useful if you're not sure whether or not WebSockets
* will work in some specific networks. Please notice that, for the individual
* servers listed in the array, the same considerations given above (e.g.,
* in terms of relative vs. absolute linking) still apply.
*
* Such an approach can also be used when you've deployed several different
* instances of Janus, and you want the library to try some and fallback
* to others if any of them is not reachable for any reason.
*
*/
/*! \page service Janus as a daemon/service
*
* By default, Janus starts in foreground, and as such works as a server
* application that you start normally and displays output on the console.
* That said, there are several reasons why you may not want to keep
* Janus in the foreground, while still being interested in checking
* the console to see what's happening.
*
* There are different ways to "daemonize" it and have it run as a service,
* though. This page tries to summarize a few ways to do so, starting
* from "dumb" approaches like sending to background and/or using screen/tmux,
* to more sophisticated approaches involving \c systemd, \c upstart
* and others.
*
* \section daemon Running Janus as a daemon
* Since version \c 0.1.0, you can run Janus as a daemon application. To
* do so, just pass either \c -b or \c --daemon as a command line
* argument, and Janus will be daemonized. Just beware, though, that
* since this results in stdout/stdin/stderr being closed, you MUST
* specify a log file for Janus to use, either via command line (\c -L
* or \c --log-file ) or in \c janus.jcfg.
*
* \section bg Running in background
* Another simple way to run Janus in the background is to just append the
* \c & character to the command line. Anyway, this will still "flood" the console
* with output from Janus. While there are ways to handle it (e.g., as
* explained here),
* a nice and easy way to handle this is redirecting the output to a
* separate file, e.g., a dedicated log:
*
\verbatim
/opt/janus/bin/janus -d 5 -6 >/path/to/mylogfile 2>&1 &
\endverbatim
*
* This is especially useful in case you want to keep a log of what
* happened when Janus was running, and can also be used as a simple and
* effective way to watch the console "live" using \c tail:
\verbatim
tail -f /path/to/mylogfile
\endverbatim
*
* \section screen Terminal multiplexers
* Another easy way to run Janus in the background is using terminal
* multiplexers like \c screen or \c tmux. If you're not familiar with
* such applications, you can find a quick overview
* here.
*
* The following is a simple example with \c screen:
*
\verbatim
screen -S janus -d -m
screen -r janus -X stuff $'/opt/janus/bin/janus -d 5 -6\n'
\endverbatim
*
* This will create a session called "janus" and launch Janus in it with
* a few command line options (in this case, just the option to enable
* IPv6 support and set the debug to verbose). Janus will then be running
* in the background: accessing the console is just a matter of attaching
* to the "janus" screen:
*
\verbatim
screen -r janus
[CTRL+A+D to detach again]
\endverbatim
*
* Terminal multiplexers usually allow for logging the output to file
* as well, if you want to keep an history of what happened during the
* Janus lifetime.
*
* \section systemd systemd
* This section shows how you can add Janus as a service to
* systemd.
*
\verbatim
[Unit]
Description=Janus WebRTC Server
After=network.target
[Service]
Type=simple
ExecStart=/opt/janus/bin/janus -o
Restart=on-abnormal
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
\endverbatim
*
* \note Remember to adjust the path in ExecStart to match the Janus binary path.
*
* \warning Please beware that, per the default \c RateLimitInterval and
* and \c RateLimitBurst values in the default sytemd configuration, logger
* messages are dropped if they arrive faster than ~33 per second. You
* may want to configure them accordingly, or otherwise Janus log messages
* may be missing. To fix this, setting RateLimitInterval=1s
* and RateLimitBurst=2000
in
* /etc/systemd/journald.conf
is usually enough.
*
* \note systemd example provided by
* \@saghul
*
* \section upstart upstart
* This section shows how you can add Janus as a daemon to
* upstart, which is
* typically available on Ubuntu systems.
*
\verbatim
description "janus"
start on filesystem or runlevel [2345]
stop on runlevel [!2345]
limit nofile 50000 50000
limit core unlimited unlimited
respawn
respawn limit 10 5
exec /opt/janus/bin/janus
\endverbatim
*
* \note upstart example provided by
* \@ploxiln
*
* \warning In case starting Janus depends on some external conditions, you
* may need to modify the \c start and \c stop lines accordingly. Here you can
* find an example,
* provided by \@stormbkk87,
* showing how you can wait, for instance, for RabbitMQ to start before starting Janus too.
*
* \section sysvinit sysvinit
* This section shows how you can add Janus as a daemon to
* SysVinit based systems.
*
\verbatim
#!/bin/sh
### BEGIN INIT INFO
# Provides: Janus
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Janus WebRTC Server
# Description: Janus WebRTC Server
### END INIT INFO
DAEMON=/usr/bin/janus
DAEMON_NAME=janus
# Add any command line options for your daemon here
DAEMON_OPTS="-D -o"
# This next line determines what user the script runs as.
# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
DAEMON_USER=root
# The process ID of the script when it runs is stored here:
PIDFILE=/var/run/$DAEMON_NAME.pid
. /lib/lsb/init-functions
do_start () {
log_daemon_msg "Starting system $DAEMON_NAME daemon"
start-stop-daemon --start --background --no-close --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS >> /var/log/$DAEMON_NAME.log 2>&1
log_end_msg $?
}
do_stop () {
log_daemon_msg "Stopping system $DAEMON_NAME daemon"
start-stop-daemon --stop --pidfile $PIDFILE --retry 10
log_end_msg $?
}
case "$1" in
start|stop)
do_${1}
;;
restart|reload|force-reload)
do_stop
do_start
;;
status)
status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $?
;;
*)
echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}"
exit 1
;;
esac
exit 0
\endverbatim
*
* \note sysvinit example provided by
* \@saghul
*
* \section supervisor supervisor
* This section shows how you can add Janus to
* supervisor, which is
* typically available on Ubuntu systems.
*
\verbatim
[program:janus]
command=/opt/janus/bin/janus
user=root
autostart=true
autorestart=true
stderr_logfile=/var/log/janus.err.log
stdout_logfile=/var/log/janus.out.log
\endverbatim
*
* \note The above configuration file should be added to
* /etc/supervisor/conf.d/janus.conf
. Then the following commands
* should be run:
*
\verbatim
sudo supervisorctl reread
sudo supervisorctl update
\endverbatim
*
* \section Others
* TODO.
*
*/
/*! \page debug Debugging Janus
*
* In the magical world of fairies and unicorns, the sun always shines
* and everything always works smoothly and without issues. Unfortunately,
* this is not the world we live in, and so you might still encounter
* issues using Janus, e.g., unexpected crashes and the like. We always
* try and tackle bugs as soon as we spot them, but some issues may be
* always lingering in the background.
*
* Should you encounter a bug or a crash, open a new
* issue
* on GitHub. Make sure you carefully read the
* guidelines
* for contributing, or otherwise we may decide to close the issue and
* not even look at it.
*
* What's important for us to look into issues and bugs definitely is
* having enough information to do so. As such, whenever possible try to
* provide as many details and data as possible. Quite useful to us are
* GDB stacktraces and/or AddressSanitizer output. The following sections
* give a quick overview on how you can collect this information after
* a crash, but for a more detailed description of the tools you should
* refer to the related documentation pages and tutorials.
*
* \section gdb GDB
* GDB is the GNU Project Debugger
* and is an effective tool for looking at what has happened (or is
* happening) inside an application. As such, it's quite useful to spot
* bugs and the like, as it can provide information about the values of
* variables when they were used and the application crashed.
*
* When Janus crashes, you should get a core dump file somewhere. This is
* a recorded state of the application memory at the time of crashing, and
* so a backtrace of what lead to an issue can help. You can open such
* a core dump file via gdb this way:
*
\verbatim
gdb /path/to/bin/janus /path/to/coredump
gdb bt
\endverbatim
*
* The \c bt command retrieves the backtrace, and is what you should provide
* as part of your new issue.
*
* \note Please \c DON'T paste this backtrace in the issue text. Use a
* service like Gist or
* Pastebin and pass the generated
* link instead.
*
* \section sanitizer Address Sanitizer
* An even better tool for spotting issues is
* Address Sanitizer,
* a fast memory error detector. Since it can spot memory errors, it's
* very useful to find out about hidden race conditions and the like.
*
* Unlike GDB which can be used as is, though, to use Address Sanitizer
* you'll first need to recompile Janus with some new settings, as it
* requires a specific dependency on a library, libasan, which you'll need
* to install through your repository manager if needed. Besides, you'll
* need at least gcc 4.8 for this to work: older versions of gcc won't
* work.
*
* Once you've installed libasan, reconfigure Janus like this:
*
\verbatim
CFLAGS="-O1 -g3 -ggdb3 -fno-omit-frame-pointer -fsanitize=address -fno-sanitize-recover=all -fsanitize-address-use-after-scope" LDFLAGS="-fsanitize=address" ./configure --prefix=/opt/janus
\endverbatim
*
* Of course you're free to add whatever additional configuration parameter
* you were using before: the important parts are the environment variables
* before that. Once done configuring, do a \c make \c clean (to make sure
* everything is recompiled from scratch) and then a \c make and \c make \c install
* as usual.
*
* At this point, your Janus version should be Address Sanitizer compliant.
* To make sure, try using \c ldd to check whether libasan is indeed a
* dependency or not:
*
\verbatim
ldd janus | grep asan
\endverbatim
*
* If it is, you're done: whenever Janus crashes for any reason, you'll
* get additional output from Address Sanitizer automatically with details
* on what went wrong, and that's what you should provide as part of the
* issue content. Just as a side note, please beware that using Address
* Sanitizer Janus will run just a bit slower, even though not to the
* point of being unusable (as when using, e.g., valgrind).
*
* \note Please \c DON'T paste Address Sanitizer output in the issue text.
* Use a service like Gist or
* Pastebin and pass the generated
* link instead.
*
*/
/*! \page pluginslist Plugins documentation
* Out of the box, Janus comes with a set of different and heterogeneous
* media manipulation plugins. These can be used individually or composed
* together at an application level for building complex WebRTC-based
* media applications.
*
* The list of plugins currently available is the following. Since new
* plugins may become available available in the future, make sure you
* come back to this page for more information.
*
* - \ref echotest
* - \ref streaming
* - \ref videocall
* - \ref sip
* - \ref nosip
* - \ref audiobridge
* - \ref videoroom
* - \ref textroom
* - \ref recordplay
* - \ref voicemail
* - \ref lua
* - \ref duktape
*/
/*! \page eventhandlers Event handlers documentation
* Controlling and monitoring a Janus instance can be done using the
* \ref admin 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).
*
* \section evhsyntax 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 \c type and (when needed) \c 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:
\verbatim
{
"emitter" : "