forked from meetecho/janus-gateway
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mainpage.dox
4443 lines (4381 loc) · 203 KB
/
mainpage.dox
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*!
* \mainpage Janus - General purpose WebRTC server
*
* \par Developer Documentation for the Janus WebRTC server
* This is the main developer documentation for the Janus WebRTC
* Server, generated with the help of
* <a href="http://www.doxygen.org">Doxygen</a>. Make sure you
* check the \ref DEPS before attempting a compilation. If you are
* interested in how to compile, install and use Janus,
* checkout the \ref README information. A \ref FAQ page is also available,
* as well as an overview on \ref CHANGELOG.
*
* \par A general purpose WebRTC server
* The Janus WebRTC Server has been conceived as a <tt>general purpose</tt>
* server. As such, it doesn't provide any functionality per se
* other than implementing the means to set up a WebRTC media communication
* with a browser, exchanging JSON messages with it, and relaying RTP/RTCP
* and messages between browsers and the server-side application logic they're attached to. Any specific
* feature/application needs to be implemented in server side plugins,
* that browsers can then contact via the Janus core to take advantage of
* the functionality they provide. Example of such plugins can be
* implementations of applications like echo tests, conference bridges,
* media recorders, SIP gateways and the like.
*
* The reason for this is simple: we wanted something that would have a
* <tt>small footprint</tt> (hence a C implementation) and that we could only
* equip with what was <tt>really needed</tt> (hence pluggable modules). That is,
* something that would allow us to deploy either a full-fledged WebRTC
* server on the cloud, or a small nettop/box to handle a specific use case.
*
* \par Architecture and APIs
* The core of the server is specified in the \ref core section. The protocols
* implemented in the Janus core are listed in the \ref protocols group
* instead. A list of plugins provided out of the box by Meetecho are
* documented in the \ref pluginslist page: these plugins can be changed
* or extended to match your requirements, or just used as a simple
* reference should you be interested in writing a new plugin from
* scratch (and you're definitely welcome to!). A \ref pluginapi to
* create new plugins, or understand how they're conceived, is documented
* as well. A documentation on the available API tranports and the
* HTTP/WebSocket JavaScript API to use Janus and the plugins it
* makes available in your web application can be found in the \ref JS
* and \ref rest pages. New API transports can be created referring to
* the \ref transportapi page. If you're interested in monitoring Janus
* resources, you can refer to the \ref admin page. Event handler
* plugins can also be used for the purpose: refer to the \ref eventhandlers
* and, for more developer oriented info, to the \ref eventhandlerapi
* page if you're interested in creating your own. For what concerns logging,
* out of the box Janus supports printing the output to \c stdout and saving
* to a local file, but logging can also be extended via additional plugins:
* refer to the \ref loggerapi for more details, and to learn how to write
* your own.
*
* Janus also supports \ref recordings out of the box, so check the
* related documentation to know more about how that works.
*
* Finally, some information on how to deploy Janus and your web
* applications that want to make use of it are provided in the \ref deploy
* page. If you're interested in starting Janus as a service/daemon rather
* than launching it normally, check the information provided in the
* \ref service page. Some additional \ref resources are also listed in
* case you're interested in talking to Janus from different languages
* and platforms.
*
* To conclude, the \ref debug page contains info on how you can help us
* fixing issues you might encounter along the road.
*
* \section copyright Copyright and author
*
* Janus WebRTC Server © 2014-2021 <a href="http://www.meetecho.com/">Meetecho</a> (http://www.meetecho.com/)
*
* \author Lorenzo Miniero <[email protected]> ( \ref CREDITS )
*
* \section license License
* This program is free software, distributed under the terms of
* the GNU General Public License Version 3. For more details and licensing
* options, including a commercial license, see the \ref COPYING page.
*
*/
/*! \page DEPS Dependencies
*
* The application and the plugins depend on the following open source
* software and libraries, so make sure you install the related development
* versions before attempting a compilation:
*
* - \b GLib: http://library.gnome.org/devel/glib/
* - \b pkg-config: http://www.freedesktop.org/wiki/Software/pkg-config/
* - \b gengetopt: http://www.gnu.org/software/gengetopt/ (command line)
* - \b Jansson: http://www.digip.org/jansson/ (JSON)
* - \b libconfig: https://hyperrealm.github.io/libconfig/ (configuration files)
* - \b libnice: https://libnice.freedesktop.org/ (ICE/STUN/TURN, at least v0.1.16 suggested, master recommended)
* - \b OpenSSL: http://www.openssl.org/ (DTLS, at least v1.0.1e)
* - \b libsrtp: https://github.com/cisco/libsrtp (SRTP, at least v2.x suggested)
* - \b usrsctp: http://code.google.com/p/sctp-refimpl/ (\c optional, Data Channels)
* - \b libmicrohttpd: http://www.gnu.org/software/libmicrohttpd/ (\c optional, v0.9.59, Web server)
* - \b libwebsockets: https://libwebsockets.org/ (\c optional, WebSockets)
* - \b rabbitmq-c: https://github.com/alanxz/rabbitmq-c (\c optional, v1.0.4, RabbitMQ)
* - \b paho.mqtt.c: https://eclipse.org/paho/clients/c (\c optional, v1.1.0 for MQTT v3.1 & v3.1.1 or v1.3.0 for MQTT v5)
* - \b nanomsg: https://nanomsg.org/ (\c optional, Nanomsg)
* - \b Sofia-SIP: http://sofia-sip.sourceforge.net/ (\c optional, only needed for the SIP plugin)
* - \b libopus: http://opus-codec.org/ (\c optional, only needed for the bridge plugin)
* - \b libogg: http://xiph.org/ogg/ (\c optional, only needed for the voicemail plugin)
* - \b libcurl: https://curl.haxx.se/libcurl/ (\c optional, only needed for the TURN REST API,
* RTSP support in the Streaming plugin and the sample Event Handler plugin)
* - \b zlib: https://zlib.net/ (gzip compression utility)
* - \b Lua: https://www.lua.org/download.html (\c optional, only needed for the Lua plugin)
* - \b npm: https://docs.npmjs.com/ (\c optional, used during build for generating JavaScript modules)
*
*/
/*! \page JS JavaScript API
* Janus exposes, assuming the HTTP transport has been compiled, a
* pseudo-RESTful interface, and optionally also WebSocket/RabbitMQ/MQTT/Nanomsg/UnixSockets
* interfaces as well, all of which based on JSON messages. These
* interfaces are described in more detail in the \ref plainhttp \ref WS
* \ref rabbit \ref apimqtt \ref apinanomsg and \ref unix documentation respectively, and all allow clients to
* take advantage of the features provided by Janus and the functionality
* made available by its plugins. Considering most clients will be web browsers,
* a common choice will be to rely on either the REST or the WebSockets
* interface for the purpose. To make things easier for web
* developers, a JavaScript library (\c janus.js) is available that can
* make use of both interfaces using exactly the same API. This library
* eases the task of creating sessions with the Janus core, attaching WebRTC
* users to plugins, send and receive requests and events to the plugins
* themselves and so on. For real examples of how this library can be
* used, check the demos in the \b html folder of this package. Notice
* that the \c janus.js library makes use of the features made available
* by the <a href="https://github.com/webrtc/adapter">webrtc-adapter</a>
* shim, which means that your web application should always include it
* as a dependency. For instance, all the demos link to it externally via
* <a href="https://cdnjs.com/">cdnjs.com</a>.
*
* \note The current \c janus.js library allows you to provide custom implementations of
* certain dependencies, in order to make it easier to integrate with other JavaScript
* libraries and frameworks. Using this feature you can ensure \c janus.js does not (implicitly)
* depend on certain global variables. Two implementations are included in \c janus.js itself:
*
* -# \ref js-default-deps which relies on native browser APIs,
* which in turn require somewhat more modern browsers
* -# \ref js-old-deps which uses jQuery (http://jquery.com/) instead,
* and should provide equivalent behaviour to previous versions of \c janus.js
*
* By default \ref js-default-deps will be used, but you can override this
* when initialising the Janus library and pass a custom dependencies object instead.
* For details, refer to: \ref js-dependencies
*
* In general, when using the Janus features, you would normally do the following:
*
* -# include the Janus JavaScript library in your web page;
* -# initialize the Janus JavaScript library and (optionally) passing its dependencies;
* -# connect to the server and create a session;
* -# create one or more handles to attach to a plugin (e.g., echo test and/or streaming);
* -# interact with the plugin (sending/receiving messages, negotiating a PeerConnection);
* -# eventually, close all the handles and shutdown the related PeerConnections;
* -# destroy the session.
*
* The above steps will be presented in order, describing how you can use
* the low level API to accomplish them. Consider that in the future we might
* provide higher level wrappers to this API to address specific needs, e.g.,
* a higher level API for each plugin: this would make it even easier to use
* the server features, as a high level API for the streaming plugin, for
* instance, may just ask you to provide the server address and the ID of
* the \c <video> element to display the stream in, and would take care of all the
* above mentioned steps on your behalf. Needless to say, you're very welcome
* to provide wrapper APIs yourself, if you feel a sudden urge to do so! :-)
*
* \section janusjs Using janus.js
*
* As a first step, you should include the Janus library in your project.
* Depending on your needs you can either use \c janus.js or one of the generated
* JavaScript module variants of it. For available module syntaxes and how to build the
* corresponding variants, see: \ref js-modules
*
\verbatim
<script type="text/javascript" src="janus.js" ></script>
\endverbatim
*
* The core of the JavaScript API is the \c Janus object. This object needs
* to be initialized the first time it is used in a page. This can be done
* using the static \c init method of the object, which accepts the
* following options:
*
* - \c debug: whether debug should be enabled on the JavaScript console, and what levels
* - \c true or \c "all": all debuggers enabled (Janus.trace, Janus.debug, Janus.log, Janus.warn, Janus.error)
* - array (e.g., <code>["trace", "warn"]</code>): 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 typically 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 a 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=<b>true</b>) and after it is completed (parameter=<b>false</b>); 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 <b>true</b> value
* when the PeerConnection associated to a handle becomes active (so ICE, DTLS and
* everything else succeeded) from the Janus perspective, while <b>false</b> 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 <b>false</b> 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=<b>audio</b> and
* on=<b>true</b> 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=<b>video</b> and on=<b>false</b> 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=<b>true</b> means
* you notified several missing packets from Janus, while uplink=<b>false</b>
* 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 (<code>send({msg})</code>), negotiate
* a PeerConnection with the plugin right away ( \c createOffer followed
* by a <code>send({msg, jsep})</code>) 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
* <code>send({msg, jsep})</code> 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
* <a target="_blank" href="https://github.com/meetecho/janus-gateway/pull/753">here</a> and
* <a target="_blank" href="https://github.com/meetecho/janus-gateway/pull/1099">here</a>.
* 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.
*
* <hr>
*
* This is it! For more information about the API, have a look at the
* demo pages that are available in the \b html folder in this package.
*
*/
/*!\page js-modules Using janus.js as JavaScript module
*
* To facilitate integration of \c janus.js within modular JavaScript code bases,
* you can instruct the build system(s) to generate a modular variants of \c janus.js.
* Generated modules may then be copied to your own JavaScript projects and seamlessly integrated with your own project's build system.
*
* Building the modules can be done in two ways:
*
* -# As part of a regular build of the Janus WebRTC Server, using \c make, by enabling the integrated support via \c configure
* -# By running NPM commands manually. This may be useful if you are looking to build just the JavaScript modules without
* incurring the overhead of a full build of Janus.
*
* As an alternative to generating the module and copying it to your project, you can also tweak
* your module bundler to use \c janus.js directly from the official Janus repository. See more
* details (including concrete instructions for Webpack): \ref js-webpack
*
* \section auto-build-js-modules Building modules using make
* Each supported variant may be enabled by passing a corresponding \c --enable-javascript-*-module flag
* (with or without a \c =yes directive) to \c configure before invoking \c make to build Janus.
* Please note: if you do not pass any such flag, by default no modules will be built.
*
* The following table provides a summary of available module formats and their corresponding \c configure options:
*
* <table class="table table-striped">
* <tr><th>Module format (syntax)</th><th>File name</th><th>configure flag to pass</th></tr>
* <tr><td>ECMAScript</td><td>janus.es.js</td><td>\c --enable-javascript-es-module</td></tr>
* <tr><td>Universal Module Definition (UMD)</td><td>janus.umd.js</td><td>\c --enable-javascript-umd-module</td></tr>
* <tr><td>CommonJS</td><td>janus.cjs.js</td><td>\c --enable-javascript-common-js-module</td></tr>
* <tr><td>Immediately Invoked Function Expression (IIFE)</td><td>janus.iife.js</td><td>\c --enable-javascript-iffe-module</td></tr>
* </table>
*
* The \c --enable-all-js-modules shortcut is available, in case you want to enable and build them all.
*
* When built and installed, these module variants may be found in the \c $PREFIX/share/janus/javascript
* folder, alongside the \c janus.js file itself (assuming \c $PREFIX the installation directory passed to \c configure).
*
* \note Building the JavaScript modules still requires NPM and may involve an \c install which means \c npm must be able
* to download dependencies. By default \c configure will attempt to auto-detect available \c npm on your PATH, but
* if you have installed NPM outside the PATH you can override this by passing the (full) path to your \c npm executable, e.g.:
*
\verbatim
./configure NPM=/path/to/my/custom/npm --enable-javascript-es-module=yes
\endverbatim
*
* \section manual-build-modules Building modules manually with NPM
* You can also opt to build modules by invoking \c npm manually. The \c npm subdirectory contains the necessary
* configuration files to get you started:
*
\verbatim
cd ./npm
npm install
npm run rollup -- --o /path/to/desired/output/file-name.js --f cjs # or es, iffe, umd, amd, ...
\endverbatim
*
* Using \c npm directly is useful if you want to build the JavaScript modules only, without building Janus itself
* or if you are looking for advanced customisation options or alternative formats which are not integrated in \c configure yet.
* As you may have surmised from the example command, the actual build consists mostly of invoking \c rollup with the
* correct parameters. For more information on available parameters, please refer to the \c rollup documentation:
*
* -# https://rollupjs.org/#command-line-flags
* -# https://rollupjs.org/#configuration-files
*
* \section js-webpack Using janus.js directly with Webpack and other bundlers
*
* Generating a converted version of \c janus.js and copying it to your project is not always the best
* solution. In many situations it may be prefered to let your JavaScript module bundler (e.g.
* <a href="https://webpack.js.org">Webpack</a>) grab the file directly from the official Janus repository.
* Doing that you can manage \c janus.js just like any other dependency coming from Github or the npm Registry,
* getting rid of the manual copy step and letting the bundler take care of version management, updates
* and downloads.
*
* Of course, the first step is to include the official Janus repository as a dependency in your
* project by adding it to your \c packages.json file.
*
\verbatim
{
"dependencies": {
"janus-gateway": "git://github.com/meetecho/janus-gateway.git"
}
}
\endverbatim
*
* That will automatically drag in the dependency on the appropriate version of the
* <a href="https://www.npmjs.com/package/webrtc-adapter">WebRTC Adapter</a> from the npm Registry.
* But \c janus.js expects such adapter to be available as a global variable.
* So we have to make that happen for it to work properly. In the case of Webpack, is as easy as
* adding this to your \c webpack.config.js file.
\verbatim
const webpack = require('webpack');
module.exports = {
plugins: [
// janus.js does not use 'import' to access to the functionality of webrtc-adapter,
// instead it expects a global object called 'adapter' for that.
// Let's make that object available.
new webpack.ProvidePlugin({ adapter: 'webrtc-adapter' })
]
}
\endverbatim
*
* On the other hand, \c janus.js defines the \c Janus object globally. So a small tweak is also
* needed to serve such object via \c export. That can be done using
* <a href="https://webpack.js.org/loaders/exports-loader/">exports-loader</a> and adding this to
* \c webpack.config.js
\verbatim
module.exports = {
module: {
rules: [
// janus.js does not use 'export' to provide its functionality to others, instead
// it creates a global variable called 'Janus' and expects consumers to use it.
// Let's use 'exports-loader' to simulate it uses 'export'.
{
test: require.resolve('janus-gateway'),
loader: 'exports-loader',
options: {
exports: 'Janus',
},
}
]
}
}
\endverbatim
*
* With that extra configuration, the official \c janus.js can be used directly in any modular
* JavaScript code base without any previous transformation of the file. That means you can simply
* do this to access to the Janus API from your modular code.
\verbatim
import { Janus } from 'janus-gateway';
\endverbatim
* For more detailed or updated documentation check the
* <a href="https://webpack.js.org/guides/shimming/">Webpack shimming guide</a> or the equivalent
* documentation for your bundler of choice.
*/
/*!\page js-dependencies Working with custom janus.js dependencies
*
* Certain dependencies of \c janus.js may be passed during library initialization as
* a property list containing the following keys:
*
* -# \c newWebSocket: a function which given WebSockets server and protocol arguments
* should return a new WebSocket (or something that acts like it)
* -# \c webRTCAdapter: an \c adapter object such as provided by the
* <a href="https://github.com/webrtc/adapter">webrtc-adapter</a> library
* -# \c isArray: a function which tests if a given argument is a JavaScript array
* -# \c checkJanusExtension: a function which tests if the Janus Screensharing extension
* for Chrome is installed/available. This can be done by testing whether or not an element
* with an \c id attribute value of \c janus-extension-installed is present.
* -# \c httpAPICall: a function which given an url and options argument performs an
* HTTP API request to Janus. This function is not as straightforward to implement,
* see the section on \ref js-http-apicall below for details.
*
* Depending on your needs you do not have to provide all these dependencies, e.g.
* you do not need to implement the \c httpAPICall function if your application relies
* exclusively on WebSockets to access the Janus API.
*
* Two implementations of the dependencies object are provided by \c janus.js:
*
* -# \c Janus.useDefaultDependencies
* -# \c Janus.useOldDependencies
*
* In turn, each of these implementations accept their dependencies as arguments or fallback on
* certain global variables. Below follows an overview:
*
* \section js-default-deps Janus.useDefaultDependencies
* The \c Janus.useDefaultDependencies method relies on the following native browser APIs:
*
* -# \c Promise: support for \c Promises as standardised in ES 6 (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises)
* -# \c fetch: support for the \c fetch API (https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
* -# \c WebSocket: support for the \c WebSocket API (https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)
* -# \c document.querySelector: support for the \c document.querySelector API (https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)
*
* Additionally the \c adapter object from the <a href="https://github.com/webrtc/adapter">webrtc-adapter</a> library is also required.
* These dependencies may either be passed explicitly to the function as a property list with keys of the same name, or
* if omitted the function will fallback to relying on global variables of that name instead.
*
* Example:
\verbatim
var customDependencies = Janus.useDefaultDependencies({
fetch: myCustomFetchImplementation // myCustomFetchImplementation should provide a compatible fetch() API
});
var relyingOnGlobalsEntirely = Janus.useDefaultDependencies();
\endverbatim
*
* Being able to passe dependencies like this is especially useful in the context of modern ES modules:
*
\verbatim
import adapter from 'webrtc-adapter';
// other imports elided
const setupDeps = () => Janus.useDefaultDependencies({
adapter,
// other dependencies elided
});
export const initialiseJanusLibrary = () => Janus.init({dependencies: setupDeps()});
\endverbatim
*
* \section js-old-deps Janus.useOldDependencies
* The \c Janus.useOldDependencies method relies on:
*
* -# \c jQuery: the JQuery library (http://jquery.com/)
* -# \c WebSocket: support for the \c WebSocket API (https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)
* -# \c adapter: the \c adapter object from the <a href="https://github.com/webrtc/adapter">webrtc-adapter</a> library
*
* This function provides a simple upgrade path for existing applications which are heavily
* tied to jQuery (especially since previous versions of \c janus.js depended on it).