WebRTC

General

General

NAT traversal

  • Info
  • NAT types
    • Network address translation (wp)



    • description

      example
      cone
      use the same port numbers for internal and external IP tuples
      full cone
      allows inbound connections from any source IP address and any source port, as long as the destination tuple exists in a previously created rule.
          {NAT internal side}  |    {NAT external side}  |  {Remote machine}
                               |                         |
      1. (INT_ADDR, INT_PORT) => [ (EXT_ADDR, INT_PORT) -> (REM_ADDR, REM_PORT) ]
      2. (INT_ADDR, INT_PORT) <= [ (EXT_ADDR, INT_PORT) <- (   *    ,    *    ) ]

      port forwarding


      (address-) restricted cone





      port-restricted cone



      symmetric always use different numbers for each side of the NAT




    • STUN/TURN (NAT Types and NAT Traversal)

      • symmetric port-restricted cone
        address-restricted cone
        full cone
        symmetric
        TURN
        TURN STUN
        STUN
        port-restricted cone TURN STUN STUN STUN
        address-restricted cone STUN STUN STUN STUN
        full cone STUN STUN STUN STUN
    • Tools to determine the type of NAT
  • Eines i protocols / Tools and protocols


    • RFC
      port
      programari / software
      description



      UDP
      TCP
      TLS


      ICE
      Interactive Connectivity Establishment
      5245




      "ICE protocol provides a structured mechanism to determine the optimal communication path between two peers." (wp)
      "Coordinates the optimal method of establishing connectivity between two peers using STUN and TURN" (en)
      STUN Session Traversal Utilities for NAT 3489 (CLASSIC-STUN)
      5389 (STUN)
      3478
      5349 "The client, typically operating inside a private network, sends a binding request to a STUN server on the public Internet. The STUN server responds with a success response that contains the IP address and port number of the client, as observed from the server's perspective." (wp)
      TURN Traversal Using Relay NAT 5766
      6156
      7065



      "TURN places a third-party server to relay messages between two clients when direct media traffic between peers is not allowed by a firewall." (wp)
      "Allows an application or client to obtain IP addresses and ports from an external relay server in order to communicate with a peer" (en)
    • ICE
      • ICE (wp)
      • RFC 5245
      • Candidate transport addresses



        • host address
          host
          directly attached to a network interface
          server reflexive address
          srflx public side of a NAT (STUN)
          relay
          relay
          allocated from a TURN server

        • server reflexive (srflx)
        • peer reflexive (prflx)
        • relay
      • 2.2 Connectivity checks
        1. Sort the candidate pairs in priority order.
        2. Send checks on each candidate pair in priority order.
        3. Acknowledge checks received from the other agent.
      • ICE selects a valid pair of candidates
      • 4. Sending the Initial Offer
        • agent must:
          1. gather candidates
          2. prioritize them
          3. eliminate redundant candidates
          4. choose default candidates
          5. formulate and send the SDP offer
    • STUN
      • STUN (wp)
      • List of 267 public STUN servers from EmerCoin project. Tested 2017-08-08
      • works with NAT types (Limitations):
        • full cone NAT
        • restricted cone NAT
        • port restricted cone NAT
      • does not work with NAT types:
        • symmetric (bi-directional) NAT
      • Wireshark
        • filter: classicstun (CLASSIC-STUN) (RFC 3489)
        • stunc ... -b
          • -> Binding Request
          • <- Binding Response
      • from bash
        • How can I get my external IP address in a shell script?
        • clients
          • WebRTC samples Trickle ICE
          • stunc (Sofia-SIP)
            • stunc stun.l.google.com:19302 -b
            • stunc stun.voip.eutelia.it:3478 -b
            • NAT type
              • stunc stun.voip.eutelia.it:3478 -n
          • Stuntman
            • STUN server and client
            • Compilation
              • Dependencies
                • Mageia
                  • urpmi install lib64boost-devel
              • Steps
                • cd stunserver
                • make
            • Installation
              • Debian /Ubuntu
                • apt-get install stuntman-client
            • Ús / Usage
              • ./stunclient stun.e-fon.ch 3478
    • TURN
      • TURN (wp)
      • relays media
      • works with:
        • symmetric (bi-directional) NAT
  • Servidors / Servers
  • Debug
    • Mozilla Firefox
      • about:webrtc
        • list of candidates
  • Demos
    • AppRTC (see logs, about:webrtc)

Janus

  • Info
  • Dependències / Dependencies
    • CentOS
      • yum install epel-release
        yum install libmicrohttpd-devel jansson-devel openssl-devel libsrtp-devel glib-devel opus-devel libogg-devel libsoup-devel pkgconfig gengetopt libtool autoconf automake
        libnice-devel
        yum install doxygen graphviz
    • Mageia
    • Nice
      • WARNING: package provided by CentOS EPEL repositories (libnice-0.1.3-4.el7.x86_64) is too old and will give problems
      • from tar file:
      • from git:
        • GitLab:
          • git clone https://gitlab.freedesktop.org/libnice/libnice.git
        • GitHub:
          • git clone https://github.com/libnice/libnice.git
        • cd libnice
      • compilació / compilation
        • ./configure
          make
          sudo make install
    • Sofia-SIP
      • Files
      • wget http://downloads.sourceforge.net/project/sofia-sip/sofia-sip/1.12.11/sofia-sip-1.12.11.tar.gz
        tar xvzf sofia-sip-1.12.11.tar.gz
        cd sofia-sip-1.12.11
        ./configure
        make
        sudo make install # will install it in /usr/local/lib

        sudo ldconfig
    • libsrtp
    • libusrsctp (needed when compiling Janus with --enable-data-channels)
      • git clone https://github.com/sctplab/usrsctp
        cd usrsctp
        ./bootstrap
        ./configure
        make
        sudo make install
        sudo ldconfig
    • libwebsockets (needed when compiling Janus with no --disable-websockets)
      • git clone https://libwebsockets.org/repo/libwebsockets
        cd libwebsockets
        # If you want the stable version of libwebsockets, uncomment the next line
        # git checkout v2.4-stable
        mkdir build
        cd build
        # See https://github.com/meetecho/janus-gateway/issues/732 re: LWS_MAX_SMP
        cmake -DLWS_MAX_SMP=1 -DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_C_FLAGS="-fpic" ..
        make && sudo make install

  • Janus compilation
    • # activate /usr/local/lib (nice, sofia-sip) for pkg-config
      export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/

    • git clone https://github.com/meetecho/janus-gateway
      cd janus-gateway
      git checkout v0.4.1
      sh autogen.sh
      ./configure --disable-websockets --disable-data-channels --disable-rabbitmq --prefix=/usr --sysconfdir=/etc --localstatedir=/var
      make
      sudo make install 
    • websockets
      • install libwebsockets
      • ./configure --disable-data-channels --disable-rabbitmq --prefix=/usr --sysconfdir=/etc --localstatedir=/var
      • WebSockets API
    • install config files in /etc/janus
      • sudo make configs
    • Eclipse
      • New / C Project: GNU Autotools / Empty project
    • Forks
    • Problemes / Problems
      • /usr/include/jansson.h:53:3: error: conflicting types for 'json_t'
        • Mageia: jansson-devel-2.4-4.1.mga5
        • Solució / Solution
          • /usr/include/jansson.h
            • typedef struct json_t {
                  json_type type;
                  size_t refcount;
              } json_t;

  • Service
    • Janus as a daemon/service
    • janus.service (/usr/lib/systemd/system/janus.service)
      • [Unit]
        Description=Janus WebRTC Gateway
        Wants=network.target
        After=syslog.target network.target remote-fs.target nss-lookup.target cloud-init.service

        [Service]
        Type=simple
        ExecStart=/usr/local/bin/janus
        #User=janus
        #Group=janus
        Restart=on-failure
        LimitNOFILE=65536

        [Install]
        WantedBy=multi-user.target
    • manage service
      • sudo systemctl status janus.service
      • sudo systemctl start janus.service
      • sudo systemctl stop janus.service
  • Configuració / Setup
    • /etc/janus/janus.cfg
      • debug
        • [general]
          log_to_file = /var/log/janus/janus.log
          debug_level = 7                         ; Debug/logging level, valid values are 0-7
          debug_timestamps = yes

          [nat]
          # maybe nice debug messages are only available when janus is called from command line, with:
          # export NICE_DEBUG=all
          # export G_MESSAGES_DEBUG=all
          # https://nice.freedesktop.org/libnice/libnice-Debug-messages.html
          nice_debug = true
      • nat (these values are for Janus itself. For final clients, modify the variable iceServers in javascript)
        • [nat]
          stun_server = stun.voip.eutelia.it
          stun_port = 3478
          turn_server =
          turn_port =
          turn_type =
          turn_user =
          turn_pwd =
          nice_debug = true
      • DTLS
        • ; Certificate and key to use for DTLS.
          [certificates]
          cert_pem = /usr/share/janus/certs/mycert.pem
          cert_key = /usr/share/janus/certs/mycert.key

          [media]
          ;dtls_mtu = 1200
      • admin
        • [general]
          admin_secret = mysecret
      • NACK
        • [media]
          max_nack_queue = 500
    • /etc/janus/janus.transport.http.cfg
      • CORS
        • [cors]
          allow_origin = https://<your_demos_server>:<your_demos_port> # e.g. https://192.168.1.100:8080

      • enable HTTPS on port 8089
        • [general]
          https = yes                    ; Whether to enable HTTPS (default=no)
          secure_port = 8089            ; Web server HTTPS port, if enabled

          ; Certificate and key to use for HTTPS.
          [certificates]
          cert_pem = /usr/share/janus/certs/mycert.pem
          cert_key = /usr/share/janus/certs/mycert.key
        • Let's Encrypt certificates
          • ; Certificate and key to use for HTTPS.
            [certificates]
            cert_pem = /etc/letsencrypt/live/www.example.org/fullchain.pem
            cert_key = /
            etc/letsencrypt/live/www.example.org/privkey.pem
          • Problemes / Problems
            • /var/log/janus/janus.log
              • Couldn't start secure webserver on port 8089...
              • Manually start janus as user janus, with high debug level
                • sudo -i
                • systemctl stop janus.service
                • su janus -s /bin/bash -c "/bin/janus -d 7"
              • Check that your user has access to certificate file:
                • su janus -s /bin/bash -c "ls -l /etc/letsencrypt/live/www.example.org/fullchain.pem"
              • Solució / Solution
                • check that the user that is running the service has permission to access dirs: /etc/letsencrypt/live, /etc/letsencrypt/archive
                • Non-root access to Letsencrypt certificates
                • install latest versions of: sofia_sip, libnice, libsrtp, libmicrohttpd (I don't know which of them solves the problem)
      • admin
        • [admin]
          admin_http = yes
          admin_port = 7088
          admin_https = yes
          admin_secure_port = 7889
    • Amazon AWS EC2
      • echo test demo needs a libnice version >0.1.14 (e.g. master 28th June 2018 from git)
      • you need to specify NAT-1-1 with the public IP address (STUN server for Janus is not needed):
      • open ports in security group
        • TCP: 8088-8089
        • UDP: ... (same ports as defined in [media] rtp_port_range, to avoid problems with mobile networks)
        • demos
          • TCP: 8080
        • admin
          • TCP: 7088
          • TCP: 7889
  • Debug
    • Configuració / Setup
    • logs
      • tail -n 200 -f /var/log/janus/janus.log
    • admin
      • Understanding the Janus admin API
      • Admin/Monitor API
      • Configuració / Setup
        • open port 7088 in firewall (and/or AWS security group)
        • /etc/janus/janus.cfg
          • [general]
            admin_secret = mysecret

        • /etc/janus/janus.transport.http.cfg
          • [admin]
            admin_http = yes
            admin_port = 7088
        • systemctl restart janus.service
      • Ús / Usage
        • curl -X POST -H 'Content-Type: application/json' --data-binary '{"janus":"list_sessions","transaction":"1234","admin_secret":"mysecret"}' http://<janus_server_ip_address>:7088/admin
        • curl -X POST -H 'Content-Type: application/json' --data-binary '{"janus":"list_handles","transaction":"1234","admin_secret":"mysecret"}' http://<janus_server_ip_address>:7088/admin/<session>
        • curl -X POST -H 'Content-Type: application/json' --data-binary '{"janus":"handle_info","transaction":"1234","admin_secret":"mysecret"}' http://<janus_server_ip_address>:7088/admin/<session>/<handle>
      • Resposta / Response
        • Header
          info
          • janus
          • session_id
          • plugin



          Plugin specific

          plugin_specific
          ...


          Handle flags

          flags



          SDPs

          sdps



          PeerConnection

          streams
          Header
          • id
          • ready




          SSRC
          ssrc




          ICE components
          components
          • state: connecting, ready, disconnected, failed
          • local-candidates
          • remote-candidates
          • selected-pair
          • dtls
          • in-stats
          • out-stats

    • Troubleshooting

      processing




      succeeded





      server

      client


      server

      client



      admin
      tshark
      wireshark
      chrome://webrtc-internals about:webrtc
      admin
      tshark
      wireshark
      chrome://webrtc-internals about:webrtc
      ICE
      streams/components/
      • state: connecting

      filter: stun
      iceconnectionstatechange: checking

      streams/components/
      • state: ready
      • connected: xxxxx




      DTLS
      streams/components/dtls/
      • dtls-state: created
      • valid: false
      • ready: false

      filter: dtls


      streams/components/dtls/
      • dtls-state: connected
      • valid: true
      • ready: true





  • Janus plugins
    • For old custom plugins, use v0.1.x (instead of v0.2.x)
    • v0.1.x
      • include janus/plugin.h
    • v0.2.x
      • include janus/plugins/plugin.h
      • Migration from v0.1.x to v0.2.x:
        • ...
    • 3rd party plugins
    • Included plugins
      • streaming
        • janus.plugin.streaming.c (github)
          • Streaming API
            • CURL examples

            • request
              js
              request json
              response json
              event
              janus_...c
              synchronous
              (immediate response)
              • list
              • create
              • destroy
              • recording
              • enable
              • disable

              {
                "transaction": "21bGZvoTdbG8Ab6X",
                "janus": "message",
                "body":
              • {"request": "list"}
              • {"request": "create",
                "type": "rtp",
                "description": "First test",

                "audio_port": 8006,
                "video_port": 8004
                ...}

              }
              {
                "janus": "success",
                "session_id": 8566092198416479,
                "sender": 6220156789031370,
                "transaction": "21bGZvoTdbG8Ab6X",
                "plugindata": {
                  "plugin": "janus.plugin.streaming",
                  "data":

              • {"streaming": "list",
                      "list": [
                        {
                          "id": 1,
                          "description": "Opus/VP8 live stream coming from gstreamer",
                          "type": "live",
                          "audio_age_ms": 66673351,
                          "video_age_ms": 66673351
                        },
                        ...
                       ]
                }
              • {"streaming": "created",
                      "created": "3346122389194671",
                      "permanent": false,
                      "stream": {
                        "id": 3346122389194671,
                        "description": "First test",
                        "type": "live",
                        "is_private": false,
                        "audio_port": 8006,
                        "video_port": 8004
                      }
                }
              • ...
              }
              -
              asynchronous
              (response in an event)
              • watch
              • start
              • pause
              • switch
              • stop
              startStream
              {
                "transaction": "21bGZvoTdbG8Ab6X",
                "janus": "message",

                "body":
                  {"request": "watch",
                   "id": ...}

              • preparing
              • starting
              • started
              • stopped

              onmessage: function(msg, jsep) {
                if(jsep !== undefined && jsep !== null) {
                  streaming.createAnswer
              (...)
              },

              {
                "janus": "event",
               
              "session_id": 8566092198416479,
                "sender": 6220156789031370,
                "transaction": "21bGZvoTdbG8Ab6X",
                "plugindata": {
                  "plugin": "janus.plugin.streaming",
                  "data": {
                    "streaming": "event",
                    "result": {"status": "preparing"}
                  }
                "jsep": {
                  "type": "offer",
                  "sdp": "..."
                }
              }

              {
                "transaction": "21bGZvoTdbG8Ab6X",
                "janus": "message",
                "body":
              {"request": "start"}
                "jsep": {"type": "answer",
                         "sdp": "..."}



              onmessage: function(msg, jsep) {
                var result = msg["result"];
                if(result != undefined && result != null) {...
              }
              },

              {
                "janus": "event",...
                "plugindata": {
                  "plugin": "janus.plugin.streaming",
                  "data": {
                    "streaming": "event",
                   
              "result": {"status": "starting"}


              {
                "janus": "event",...
                "plugindata": {
                  "plugin": "janus.plugin.streaming",
                  "data": {
                    "streaming": "event",
                   
              "result": {"status": "started"}

              onremotestream: function(stream) {
                $('#videoremote').append('<video  id="remotevideo" width=320 height=240 autoplay/>');
                Janus.attachMediaStream($('#remotevideo').get(0), stream);
              },




        • config
          • /etc/janus/janus.plugin.streaming.cfg

          • config file
            streamer
            browser notes

            /etc/janus/janus.plugin.streaming.cfg
            Chrome
            Firefox
            VP8 / Opus
            [opus-vp8-multicast]
            type = rtp
            id = 20
            description = Opus/VP8 live multicast stream
            audio = yes
            video = yes
            audioport = 5002
            audiomcast = 232.3.4.5
            audiopt = 111
            audiortpmap = opus/48000/2
            videoport = 5004
            videomcast = 232.3.4.5
            videopt = 100
            videortpmap = VP8/90000

            ok
            ok
            H.264
            [h264-multicast]
            type = rtp
            id = 10
            description = H.264 live multicast stream
            audio = no
            video = yes
            videoport = 8004
            videomcast = 232.6.7.8
            videopt = 126
            videortpmap = H264/90000
            videofmtp = profile-level-id=42e01f\;packetization-mode=1

            • ffmpeg -re -f lavfi -i "testsrc=size=320x180:rate=24" -c:v libx264 -b:v 700k -pix_fmt yuv420p -profile:v baseline -level:v 31 -an -f rtp -payload_type 126 rtp://232.6.7.8:8004 -sdp_file /tmp/h264.sdp
            • ffmpeg -re -i sintel.mp4 -an -c copy -bsf:v h264_mp4toannexb -f rtp -payload_type 126 rtp://232.6.7.8:8004 -sdp_file /tmp/sintel.sdp
            ok
            if profile.level-id is not specified, Firefox interprets offered sdp as: a=fmtp:126 profile-level-id=420010;level-asymmetry-allowed=0;packetization-mode=1
            and Firefox response only contains VP8:
            a=rtpmap:120 VP8/90000
            It does not work.
      • videoroom
      • plain RTP
  • DTLS
    • janus.cfg
      • ; Certificate and key to use for DTLS.
        [certificates]
        cert_pem = /usr/share/janus/certs/mycert.pem
        cert_key = /usr/share/janus/certs/mycert.key

        [media]
        ;dtls_mtu = 1200
    • Problems with DTLS
  • Problemes / Problems
  • Accés des de client / Access from client
    • Info
    • API
      • with curl
        • general values

          janus_url_base=http://192.168.1.130:8088
          janus_url_base=https://192.168.1.130:8089
          janus_url=${janus_url_base}/janus
          cookies_options='-b galetes.txt -c galetes.txt'
          touch galetes.txt
          origin_url=
          https://192.168.1.130:8080
          origin_header="-H 'Origin: ${origin_url}'"
          headers=${origin_header}
          cookies_options='-b galetes.txt -c galetes.txt'
          # accept self-signed certificates
          cert_options='-k'
          transaction=1234567890
          get info

          curl -i -X GET ${cert_options} ${janus_url}/info
          check CORS

          curl -i -X OPTIONS ${cert_options} ${cookies_options} "$headers" "${janus_url}"
          get a new session

          response=$(curl -X POST ${cert_options} ${cookies_options} "$headers" -H 'Content-Type: application/json' --data "{\"janus\":\"create\",\"transaction\":\"${transaction}\"}" "${janus_url}" )
          cat galetes.txt
          session_id=$(echo "$response" | jq '.data.id')
          echo "session_id: $session_id"
          session
          _url="${janus_url_base}/janus/${session_id}"
          attach to a plugin
          (e.g.: janus.plugin.streaming)

          plugin_name="janus.plugin.streaming"
          response=$(curl -X POST ${cert_options} ${cookies_options} "$headers" -H 'Content-Type: application/json' --data "{\"janus\":\"attach\",\"plugin\":\"${plugin_name}\",\"transaction\":\"${transaction}\"}" "${session_url}" )
          plugin_session_id=$(echo "$response" | jq '.data.id')
          plugin_url="${session_url}/${plugin_session_id}"

          send a message to the plugin
          e.g. list of existing mountpoints (available streams) in janus.plugin.streaming message_body="{\"request\":\"list\"}"
          create new mountpoint in janus.plugin.streaming [id=...]
          admin_key=... # defined in janus.plugin.streaming.cfg: [general] admin_key
          message_body="{\"request\":\"create\",\"
          type\":\"rtp\",\"id\":99,\"description\":\"stream_description\",\"audio\":true,\"video\":true,\"audioport\":1111,\"audiopt\":111,\"audiortpmap\":\"opus/48000/2\",\"videoport\":2222,\"videopt\":100,\"videortpmap\":\"VP8/90000\",\"permanent\":false,\"admin_key\":\"${admin_key}\"}"
          destroy mountpoint in janus.plugin.streaming id=99
          admin_secret="adminpwd"
          message_body="{\"request\":\"destroy\",\"id\":${id},\"secret\":\"${admin_secret}\"}"


          curl -i -k -X POST -H 'Content-Type: application/json' --data-binary "{\"janus\":\"message\", \"transaction\":\"${transaction}\", \"body\":${message_body} }" "${plugin_url}"
          keep session active.
          If not called, the session will expire after value specified in janus.cfg session_timeout (default: 60 seconds)

          rid=$(date +%s%03N)
          get_url="${session_url}?rid=${rid}&maxev=1"
          echo "url: $url"
          curl -v -i -X GET ${cert_options} ${cookies_options} "$headers" "${get_url}"
          cat galetes.txt
          close session

          curl -i -X POST ${cert_options} ${cookies_options} "$headers" -H 'Content-Type: application/json' --data "{\"janus\":\"destroy\",\"transaction\":\"${transaction}\"}" "${session_url}"
          cat galetes.txt

      • with Javascript
        • janus.js
          • Janus.init
            • debug: ...
            • dependencies: Janus.useDefaultDependencies
            • callback: function(){...}
            • var janus = new Janus({...})
              • server: ...
              • iceServers: ...
              • ipv6: ...
              • withCredentials: ...
              • max_poll_events: ...
              • destroyOnUnload: ...
              • token: ...
              • apisecret: ...
              • success: function() {...}
              • error: function(cause) {...}
              • destroyed: function() {...}
            • janus.getServer()
            • janus.isConnected()
            • janus.getSessionId()
            • janus.attach({...})
              • plugin: ...
              • opaqueId: ...
              • success: function(pluginHandle) {...}
                • pluginHandle.getId()
                • pluginHandle.getPlugin()
                • pluginHandle.send({...})
                  • message: ...
                  • ...
                • pluginHandle.createOffer(callbacks)
                  • media: {...}
                    • audioSend: true/false
                    • audioRecv: true/false
                    • audio: true/false
                    • audio: {...}
                      • deviceId: ...
                    • videoSend: true/false
                    • videoRecv: true/false
                    • video: true/false
                    • video: "lowres"/"lowres-16:9"/"stdres"/"stdres-16:9"/"hires"/"hires-16:9"
                      // 320x240/320x180/640x480/640x360/1280x720
                    • video: "screen"
                    • video: {...}
                      • deviceId: ...
                        // Janus.listDevices(callback)
                      • width: ...
                      • height: ... 
                    • data: true/false
                    • failIfNoAudio: true/false
                    • failIfNoVideo: true/false
                    • screenshareFrameRate: ...
                  • trickle: true/false
                  • stream: ...
                  • success: function(jsep) {...}
                    // got sdp
                  • error: function() {...}
                • pluginHandle.createAnswer(callbacks)
                  • (same as CreateOffer)
                  • jsep: ...
                • pluginHandle.handleRemoteJsep(callbacks)
                • pluginHandle.dtmf(parameters)
                • pluginHandle.data(parameters)
                • pluginHandle.getBitrate()
                • pluginHandle.hangup(sendRequest)
                • pluginHandle.detach(parameters)
              • error: function(cause) {...}
              • consentDialog: function(on) {...}
              • webrtcState: function() {...}
              • iceState: function() {...}
              • mediaState: function() {...}
              • slowLink: function() {...}
              • onmessage: function(msg, jsep) {...}
              • onlocalstream: function(stream) {...}
              • onremotestream: function(stream) {...}
              • ondataopen: function() {...}
              • ondata: function() {...}
              • oncleanup: function() {...}
              • detached: function() {...}
            • janus.destroy({...})
              • ...
            Janus.debug(...)
          • Exemples / Examples
            • basic session creation
              • <!doctype html>

                <head>
                  <meta charset="utf-8"/>
                  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/6.0.0/adapter.min.js"></script>
                  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
                  <script type="text/javascript" src="janus.js"></script>

                  <script type="text/javascript">
                   var server = "http://192.168.1.128:8088/janus";

                   $(document).ready(function() {
                       Janus.init({
                           debug: true,
                           dependencies: Janus.useDefaultDependencies(), // or: Janus.useOldDependencies() to get the behaviour of previous Janus versions
                           callback: function() {
                               // init completed

                               // create gateway session
                               var janus = new Janus(
                                   {
                                       server: server,
                                       withCredentials: true,
                                       success: function() {
                                           // gateway session created

                                           Janus.debug("---- is connected: " + janus.isConnected() );
                                           Janus.debug("---- session id: " + janus.getSessionId() );
                                       },
                                       error: function(cause) {
                                           // error when creating gateway session
                                       },
                                       destroyed: function() {
                                           // gateway session destroyed
                                       }
                                   });
                               Janus.debug("---- server: " + janus.getServer() );
                           }
                       });
                   });
                  </script>

                </head>

                <body>
                Janus minimal example.
                </body>
            • basic attach to a plugin
              • <!doctype html>

                <head>
                  <meta charset="utf-8"/>
                  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/6.0.0/adapter.min.js"></script>
                  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
                  <script type="text/javascript" src="janus.js"></script>

                  <script type="text/javascript">
                   /**
                    * This script could be placed in a file.
                    */
                   var plugin_client = function(params) {

                       var PLUGIN_PACKAGE = "janus.plugin.streaming";
                       var janus = null;
                       var myPluginHandle = null;

                       this.start = function() {
                           Janus.init({
                               debug: true,
                               dependencies: Janus.useDefaultDependencies(), // or: Janus.useOldDependencies() to get the behaviour of previous Janus versions
                               callback: function() {
                                   // init completed

                                   // create gateway session
                                   janus = new Janus(
                                       {
                                           server: params.server,
                                           withCredentials: true,
                                           success: function() {
                                               // gateway session created
                                               Janus.log("Janus session id: " + janus.getSessionId() );

                                               // attach to plugin
                                               janus.attach(
                                                   {
                                                       plugin: PLUGIN_PACKAGE,
                                                       success: _onAttachSuccess,
                                                       error: _onError,
                                                       onmessage: _onMessage,
                                                       onlocalstream: _onLocalStream,
                                                       onremotestream: _onRemoteStream,
                                                       oncleanup: _onCleanUp
                                                   });
                                           },
                                           error: function(cause) {
                                               // error when creating gateway session
                                           },
                                           destroyed: function() {
                                               // gateway session destroyed
                                           }
                                       });
                                   Janus.debug("Janus server: " + janus.getServer() );
                               }
                           });
                       };

                       this.stop = function() {
                           if (janus) {
                               janus.destroy();
                               janus = null;
                           } 
                       };

                       function _onAttachSuccess(pluginHandle) {
                           myPluginHandle = pluginHandle;
                           Janus.log("Plugin attached: " + myPluginHandle.getPlugin() + ", id=" + myPluginHandle.getId() );
                       }

                       function _onError(message) {
                           Janus.error(message);
                       }
                      
                       function _onMessage(msg, jsep) {
                           Janus.debug("Got a message");
                           Janus.debug(JSON.stringify(msg));
                       }

                       function _onLocalStream(stream) {
                           Janus.debug("Got a local stream");
                           Janus.debug(JSON.stringify(stream));
                       }
                      
                       function _onRemoteStream(stream) {
                           Janus.debug("Got a remote stream");
                           Janus.debug(JSON.stringify(stream));
                       }
                      
                       function _onCleanUp() {
                           Janus.log("Got a cleanup notification");
                       }
                      

                   };
                  </script>


                  <script type="text/javascript">
                   var janus_server = "http://192.168.1.128:8088/janus";

                   $(document).ready(function() {
                       client = new plugin_client(
                           {
                               server: janus_server
                           }
                       );
                       client.start();
                   });
                  </script>

                </head>

                <body>
                Janus minimal example.
                </body>
  • Demos (test web server)
    • Install NodeJS via nvm, and then:
      • install http server
        npm install -g http-server
    • configure firewall
      • sudo systemctl start firewalld.service
        sudo firewall-cmd --permanent --zone=public --add-port=8080/tcp
        sudo firewall-cmd --reload

    • install html dir into /usr/share/janus/demos/
      • cd janus-gateway
        sudo make install html

    • non-secure
      • run http-server
        • nvm use default
          http-server /usr/share/janus/demos

      • check it:
        • http://<your_demos_server_ip>:8080/
        • http://<your_demos_server_ip>:8080/demos/
    • secure
      • server
        • nvm use default
          http-server --ssl --cert /usr/share/janus/certs/mycert.pem --key /usr/share/janus/certs/mycert.key /usr/share/janus/demos
      • client
      • Problemes / Problems
        • Probably a network error, is the gateway down?: [object Object]
          • Solució / Solution:
            • Des del navegador, accepteu manualment el certificat autosignat / From your browser, manually accept self-signed certificate in
              • https://<your_janus_server_ip>:8089/
            • Reviseu l'apartat [cors] del fitxer /etc/janus/janus.cfg

UV4L

  • Installation for ARM (Raspberry Pi)
    1. curl http://www.linux-projects.org/listing/uv4l_repo/lrkey.asc | sudo apt-key add -
    2. /etc/apt/sources.list
      • deb http://www.linux-projects.org/listing/uv4l_repo/raspbian/ jessie main
    3. sudo apt-get update
    4. sudo apt-get install uv4l uv4l-raspicam
    5. sudo apt-get install uv4l-raspicam-extras
    6. sudo service uv4l_raspicam restart
      • /etc/uv4l/uv4l-raspicam.conf
    7. Test
      • dd if=/dev/video0 of=snapshot_$(date '+%Y-%m-%dT%H%M%SZ' --utc).jpeg bs=11M count=1
      • gpicview snapshot_...jpeg
    8. pkill uv4l
    9. optional
  • Usage
    • uv4l [ uv4l-options ] [ –enable-server option ] [ –server-option ‘option=value’ [ … ] ]

    • needed packages
      command
      service
      config file
      client
      core
      uv4l
      uv4l [ uv4l-options ]


      raspicam
      uv4l-raspicam


      /etc/uv4l/uv4l-raspicam.conf
      uv4l-raspicam-extras
      (/etc/init.d/uv4l_raspicam)
      sudo systemctl start uv4l_raspicam.service
      sudo service uv4l_raspicam start


      streaming server (RESTful API)
      uv4l-server
      • uv4l [ uv4l-options ] --enable-server=yes [--server-option ‘option=value’ [ … ] ]
      • uv4l --driver raspicam --enable-server=yes --auto-video_nr=yes
      • /usr/bin/uv4l -k --sched-fifo --mem-lock --config-file=/etc/uv4l/uv4l-raspicam.conf --driver raspicam --driver-config-file=/etc/uv4l/uv4l-raspicam.conf --enable-server=yes --server-option=--editable-config-file=/etc/uv4l/uv4l-raspicam.conf


      http://<raspberrypi>:8080/
      http://<raspberrypi>:8080/stream
      http://<raspberrypi>:8080/stream/webrtc
      • create a self-signed certificate
      • uv4l --driver=raspicam --auto-video_nr=yes --server-option=--use-ssl=yes --server-option=--ssl-private-key-file=/home/pi/192.168.1.139.key --server-option=--ssl-certificate-file=/home/pi/192.168.1.139.crt


      https://<raspberrypi>:8080/
  • debug
    • tail -f /var/log/syslog
  • WebRTC extension (two-way audio/video)
  • Janus Gateway (join a room with Janus)

http://www.francescpinyol.cat/webrtc.html
Primera versió: / First version: 10.XI.2017
Darrera modificació: 12 de desembre de 2018 / Last update: 12th December 2018

Valid HTML 4.01!

Cap a casa / Back home