WebRTC
Seccions d'aquesta pàgina 6
01General#
- General
- NAT traversal
- Gateway
- Janus
- Info
- Dependències / Dependencies
- Compilació / Compilation
- Servei / Service
- Configuració / Setup
- Plugins
- DTLS
- Problemes /
Problems
- Client
- Servidor / Server
- Accés des
de client / Access from client
- Info
- API
- CURL
- Javascript
- Demos (test web server)
- Janus
02General#
- WebRTC
- Is WebRTC ready yet?
- A Year Building a WebRTC Application: Lessons in Startup Engineering
- html5rocks
- W3C
- WebRTC: Plugin-free
realtime communication (slides) (Google developers)
(Google I/O 2013)
- STUN and TURN (#44)
- TURN (#50)
- adapter.js: same code in all browsers
- webrtcH4cKS
- Temasys
- Advanced WebRTC Architecture
- Streaming protocols and ultra-low latency including #webrtc
- WebRTC Course
- Developers
- comparison of webrtc frameworks (video at xx:xx)
- Developers
- Info
- WebRTC Full Course & More (yt) (first hour)
- Retransmissions (NACK)
- NACK in Janus
- How
are retransmissions implemented in WebRTC
- Sent over RTCP Receiver Report
- Receiver side
- ...
- Sender side
- ...
- Resolució de problemes / Troubleshooting
- Test WebRTC Connectivity! (Netscan service)
- Firewall setup (in router) when
receiving audio/video from Janus streaming plugin:
- Outbound (only big corporations have closed outbound
traffic) ports that have to be open:
- 19302 / UDP (STUN for WebRTC)
- 20000-20100 / UDP (audio/video WebRTC) (Janus: range in janus...cfg file)
- Inbound
- ...
- Outbound (only big corporations have closed outbound
traffic) ports that have to be open:
- Summary
-
main tasks
main JavaScript APIs
functions
example
acquiring audio and video
(Capturing Audio & Video in HTML5)
MediaStream (aka getUserMedia)
- Navigator.MediaDevices.getUserMedia() (Navigator.getUserMedia())
- navigator.mediaDevices.enumerateDevices() (MediaStreamTrack.getSources())
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<video autoplay></video>
<script>
const constraints = {
video: true
};
const video = document.querySelector('video');
function handleSuccess(stream) {
video.srcObject = stream;
}
function handleError(error) {
console.error('Reeeejected!', error);
}
navigator.mediaDevices.getUserMedia(constraints).
then(handleSuccess).catch(handleError);
</script>
</body>
</html>
communicating audio and video
RTCPeerConnection
communicating arbitrary data
RTCDataChannel
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
-
- Clients
- Gstreamer
- >=1.14.0
- GStreamer has grown a WebRTC implementation (feb 2018)
- gstwebrtc-demos
- gst-examples / webrtc
- Navegadors / Browsers
- See also: Janus streaming plugin config
- Firefox
- Firefox 55 and Janus (hangup bug solved)
about:webrtc- Media/WebRTC
- WebRTC API
- H.264
- Frames of type B are not
supported
- Solution
- Do not use B-frames
- Use baseline profile (does not allow b-frames)
- Solution
- Codecs used by WebRTC
- Constraints
- IMPORTANT: in order to have it working in Firefox, second byte in profile-level-id cannot be 00 (not constrained); it must be e0 (constrained)
- Firefox not accepting SDPs for H264 that contain profile-level-id 420029
- RTSP camera / Firefox-edge-safari problems
- Problems with H.264 PPS, SPS on RTP
- Checking H264 Capability on Firefox #425
-
about:config
value
info
media.peerconnection.video.h264_enabled
true
media.navigator.video.preferred_codec97
set preferred codec to: H.264, packetization mode 0
126
set preferred codec to: H.264, packetization mode 1
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- Frames of type B are not
supported
- Problemes / Problems
- In offer sdp, the profile-level-id must be specified
- Chrome
- WebRTC: Switch camera
chrome://webrtc-internals- Problemes / Problems
- Frames of type B are not supported
- H.264 PPS, SPS on RTP
- Android / MS Windows
- Janus streaming plugin from an RTP
generated by gstreamer/ffmpeg
- Video does not show on client
- Solució / Solution
- check that NAL units of type 9 (Access Unit Delimiters) are not generated:
- Janus streaming plugin from an RTP
generated by gstreamer/ffmpeg
- Safari
- OpenWebRTC
(Ericsson Research) (based on Gstreamer)
- Is it possible to create a webrtc application without browser using Openwebrtc #403
- Instal·lació / Installation
- Compilació / Compilation
- Building OpenWebRTC with Cerbero
- OLD
BUILD
SCRIPTS Building OpenWebRTC
git clone https://github.com/EricssonResearch/openwebrtc.gitcd openwebrtc...
- tests
- test_client.py
- Install PyGObject
(Gnome)
- from packages
- Mageia
urpmi python-gi
- Mageia
- compile from source
- Dependencies
- Mageia
urpmi gnome-commonurpmi gobject-introspection-1.0 >= 1.46.0
- Mageia
pip install "git+https://git.gnome.org/browse/pygobject@3.22.0"
- Dependencies
- from packages
export GI_TYPELIB_PATH=/opt/openwebrtc-0.3/lib/girepository-1.0/
export LD_LIBRARY_PATH=/opt/openwebrtc-0.3/lib/
- Install PyGObject
(Gnome)
- test_client.c
- test_client.py
- WebRTC Native Code (for browser developers) (Google)
- webrtc without a browser (Python)
- UV4L on RPI WebRTC with Janus Gateway ICE error
- NodeJS
- UV4L (RaspberryPi)
- Gstreamer
- Gateway
- Web conferencing
- Simulcast
- MCU / SFU
- WebRTC Media Servers – SFUs vs MCUs (webRTC.ventures)
- WHIP, WHEP, WHAP
03NAT traversal#
- Info
- General
- NAT Types and NAT Traversal (Kurento)
- An Intro to WebRTC’s NAT/Firewall Problem
- WebRTC in the real world: STUN, TURN and signaling
- Am I
behind a Symmetric NAT?
stunc ... -n
- A STUN and TURN server that work under 3G/4G Network
- WebRTC and ICE. When thing don't work (slides)
- WebRTC TURN: Why you NEED it and when you DON’T need it
- Tests
- WebRTC
Troubleshooter
- Network latency (5 minutes)
- webrtc / testrtc
- WebRTC
samples
Trickle ICE
- WebRTC
samples
Trickle ICE (Temasys)
- check STUN and TURN servers from your browser
- WebRTC
samples
Trickle ICE (Temasys)
- WebRTC Leak Test
- WebRTC
Troubleshooter
- Proxy
- Web Real-Time Communication Use Cases and Requirements (RFC 7478)
- RTCWEB Considerations for NATs, Firewalls and HTTP proxies (draft-hutton-rtcweb-nat-firewall-considerations-03)
- WebRTC behind the proxy on Ubuntu using coturn and NodeJS
- RTCTunnel: Building a WebRTC Proxy with Go
- Use HTTP proxy for WebRTC ICE-TCP, TURN/TCP, TURN/TLS (mozilla.org)
- How is STUN able to bypass a proxy?
- Network firewall or proxy server settings for Zoom
- Janus
- Does
Janus
need stun or turn server?
- "For now just use the STUN server and then start considering TURN if some users can't connect."
- WebRTC
using
Janus with ISP which puts its users in NAT/SNAT
- "If you're behind a symmetric NAT, and Janus is NATted too, you'll need to configure a TURN server as well (only in JavaScript, not Janus)."
- Does
Janus
need stun or turn server?
- General
- 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
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- 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 Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
-
- Tools to determine the type of NAT
- Original
NAT
characterization algorithm of RFC 3489. (wp)
stunc ... -n- PySTUN
- PySTUN (Kurento)
git clone https://github.com/konradkonrad/pystun.git pystun-konrad
cd pystun-konrad/
git checkout research
mv README.md README.rst
sudo python setup.py install
pystun
- Original
NAT
characterization algorithm of RFC 3489. (wp)
- Eines i protocols / Tools and protocols
-
RFC
port
programari / software
description
UDP
TCP
(D)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 - List of 267 public STUN servers
- Stuntman (server and client)
"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
- coTURN
- Free numb server (viagenie)
"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)
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- 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
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- server reflexive (srflx)
- peer reflexive (prflx)
- relay
-
- 2.2
Connectivity
checks
- Sort the candidate pairs in priority order.
- Send checks on each candidate pair in priority order.
- Acknowledge checks received from the other agent.
- ICE selects a valid pair of candidates
- 4.
Sending the Initial Offer
- agent must:
- gather candidates
- prioritize them
- eliminate redundant candidates
- choose default candidates
- formulate and send the SDP offer
- agent must:
- STUN
- STUN (wp)
- List of 267 public STUN servers from EmerCoin project. Tested 2017-08-08
- STUN DTLS
- 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
- If you test a STUN server, it works if you can gather a candidate with type "srflx".
- If you test a TURN server, it works if you can gather a candidate with type "relay".
- stunc (Sofia-SIP)
stunc stun.l.google.com:19302 -bstunc stun.voip.eutelia.it:3478 -b- NAT type
stunc stun.voip.eutelia.it:3478 -n
- TLS
- on server, TCP/3478 must be open
- Stuntman
- STUN server and client
- Compilation
- Dependencies
- Mageia
- urpmi install lib64boost-devel
- Mageia
- Steps
cd stunservermake
- Dependencies
- Installation
- Debian /Ubuntu
apt-get install stuntman-client
- Debian /Ubuntu
- Ús / Usage
./stunclient stun.e-fon.ch 3478
- WebRTC
samples
Trickle ICE
- TURN
- TURN (wp)
- RFC 8656 (5766)
- extension to STUN
- relays media
- works with:
- symmetric (bi-directional) NAT
- Info
-
Node, address, traffic, transport.
TURN
clientclient
host
transport addressNAT client
server-reflexive
transport address- TURN commands: ALLOCATION, ...
- TURN message: application data
TURN
server
transport addressTURN
serverrelayed
transport address- application data
peer
transport addressPEER
- UDP
- TCP
- TLS over TCP
- DTLS over UDP
local candidate:
- relay-udp
- [relay-tcp (RFC 6062)]
- UDP
- [TCP (RFC 6062)]
remote candidate
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- Servidor / Server
- config
- Janus server (only if Janus itself is behind a firewall)
- /etc/janus/...
turn_server =
turn_port =
...
- TCP
- from client to server:
- RFC 8656 (RFC 5766: 2.1 Transports)
- from server to peer (relay):
- RFC 6062
?transport=tcp- this will also force TCP between TURN client and TURN server
- TCP
and TLS transport support for TURN
- "There is an extension to TURN, RFC 6062, that defines the "full" TCP support: the data "after" TURN can be relayed over TCP (not TLS). The connection between the client and the TURN server must be TCP or TLS if we want the traffic to be relayed over TCP."
- What happens when WebRTC shifts to TURN over TCP
- from client to server:
- Autenticació / Authentication
- TURN REST Server API (pdf)
- Ús / Usage
- Janus clients
- Using TURN server with Janus
- echotest.js
janus = new Janus({
iceServers: [{urls: "turn:myturnserver:5349", username: "guest", credential: "somepassword"},
{urls: "turn:myturnserver:5349?transport=tcp", username: "guest", credential: "somepassword"}],
})
- verify with
about:webrtc(Firefox):iceServers:
- force TURN (relay)
- How to force TURN ? (so Safari works fine)
- echotest.js
iceTransportPolicy: "relay",- not working with Chrome?
- Janus clients
-
- Servidors / Servers
- rfc5766-turn-server
- coTURN
- Instal·lació / Installation
- How to create and configure your own STUN/TURN server with coturn in Ubuntu 18.04
- TURN/STUN Server (Red5 Pro Server)
- from repo
- Ubuntu 22.04
sudo apt-get install coturn
- CentOS
8 (EPEL) (4.5.2)
sudo dnf install epel-release
sudo dnf install coturn
- ...
- Ubuntu 22.04
- Codi font / Source
- coturn / coturn
-
AWS coturn config test from client
security group /etc/coturn/turnserver.conf protocol stunc (sofia) turnutils (coturn) TrickleICE non secure TCP, UDP 3478
STUN stunc myturnserver -bturnutils_stunclient myturnserver
- STUN or TURN URI: stun:myturnserver
user=guest:somepasswordTURN
turnutils_uclient -v -u guest -w somepassword -p 3478 myturnserver- STUN or TURN URI: turn:myturnserver
- TURN username: guest
- TURN password: somepassword
secure TCP, UDP 5349 #tls-listening-port=5349
cert=/etc/letsencrypt/live/toto.org/fullchain.pem
pkey=/etc/letsencrypt/live/toto.org/privkey.pemSTUN stunc myturnserver:5349 -bturnutils_stunclient -p 5349 myturnserver- STUN or TURN URI: stun:myturnserver:5349
#tls-listening-port=5349user=guest:somepassword
cert=/etc/letsencrypt/live/toto.org/fullchain.pem
pkey=/etc/letsencrypt/live/toto.org/privkey.pemTURN
turnutils_uclient -v -u guest -w somepassword -p 5349 myturnserver- STUN or TURN URI: turn:myturnserver:5349
- TURN username: guest
- TURN password: somepassword
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- Config
- Transport between TURN client and TURN server (RFC
8656):
Note: on server, use
client
turnserver.conf
turnutils_uclient test.webrtc.org Firefox
no-udp
no-dtls
no-tcp
no-tls
about:webrtc UDP turn:myturnserver:3478
listening-port=3478 -
[-p 3478] Network: UDP enabled
DTLS over UDP turns:myturnserver:5349 tls-listening-port=5349
-
-p 5349 Network: UDP enabled
TCP turn:myturnserver:3478 listening-port=3478
-
[-p 3478] -t Network: TCP enabled
TLS over TCP turns:myturnserver:5349 tls-listening-port=5349
-
-p 5349 -t Network: TCP enabled
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
ss -tulpn | grep turnto check open ports.
Gathered candidates (relayed transport address) can be UDP, even if transport between TURN client and TURN server is established over TCP. - Transport between TURN server and peer (candidate
of type relay) (RFC
6062): (is transport=tcp also needed to
specify tcp transport between TURN client and TURN
server?)
client turnserver.conf
turnutils_uclient Firefox
no-udp-relay
(also disables udp, tcp communication between client/server,
even if, according to ss, ports are available)no-tcp-relay
(not working?)
about:webrtc
local candidate UDP (RFC 8656) turn:myturnserver:...[?transport=udp] -
x.x.x.x:p/udp (relay-udp) DTLS over UDP turns:myturnserver:...[?transport=udp]
x.x.x.x:p/udp (relay-tls) TCP (RFC 6062) turn:myturnserver:...?transport=tcp
- -T (implies -t) x.x.x.x:p/udp (relay-tcp) TLS over TCP (RFC 6062) turns:myturnserver:...?transport=tcp
x.x.x.x:p/udp (relay-tls) Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- activate TLS/DTLS
- /etc/coturn/turnserver.conf
#tls-listening-port=5349
cert=/etc/letsencrypt/live/toto.org/fullchain.pem
pkey=/etc/letsencrypt/live/toto.org/privkey.pem
- check from server
tail -n 200 /var/log/coturn/turnserver.logss -tulnp
- check from remote client
stunc turn.watchity.net:5349 -bturnutils_stunclient -p 5349 myturnserver- TrickleICE
- STUN or TURN URI: stun:myturnserver:5349
- Gather candidates:
- srflx udp <my_external_ip_address>
- /etc/coturn/turnserver.conf
- non default ports (e.g. 443 for TLS)
- coturn.service
[Service]
AmbientCapabilities=CAP_NET_BIND_SERVICE
...
- After update of coturn can not connect to 443 #421
- without
AmbientCapabilities, you will see, in /var/log/coturn/turnserver.logERROR: Fatal final failure: cannot bind DTLS/UDP listener socket to addr 127.0.0.1:443
- coturn.service
- add a user/password
- option 1 (these credentials will not work with
-u and -w options in turnutils_uclient):
- /etc/coturn/turnserver.conf
user=guest:somepassword
- /etc/coturn/turnserver.conf
- option 2:
sudo turnadmin -a -r mycompany.org -u convidat -p contrasenya
- check from remote client
turnutils_uclient -v -p 5349 -u convidat -w contrasenya myturnserver- TrickleICE
- STUN or TURN URI: turns:myturnserver:5349
- TURN username: guest
- TURN password: somepassword
- Gather candidates:
- relay udp <turn_server_ip_address>
- ...
- option 1 (these credentials will not work with
-u and -w options in turnutils_uclient):
- dynamic credentials:
- /etc/coturn/turnserver.conf
#lt-cred-mech
use-auth-secret
static-auth-secret=north
- somewhere (e.g. a completely different
server), generate temporary credentials,
calculated using the shared secret:
- usercombo -> "timestamp_when_password_will_expire:userid"
turn_user -> usercombo
turn_password -> base64(hmac_sha1(secret, usercombo))
- usercombo -> "timestamp_when_password_will_expire:userid"
- put them when accessing the coturn server
(e.g. from Janus echotest.js):
iceServers: [{urls: "turn:myturnserver:5349", username: turn_user, credential: turn_password},
- test with TrickleICE:
- STUN or TURN URI: turns:myturnserver:5349
- TURN username:
turn_user - TURN password:
turn_password - Gather candidates (you can also filter by
"relay" only):
- relay udp <turn_server_ip_address>
- /etc/coturn/turnserver.conf
- logs
# sudo mkdir -p /var/log/coturn
# sudo chown turnserver.turnserver /var/log/coturn
log-file=/var/log/coturn/turnserver.log
#syslog
# Enable full ISO-8601 timestamp in all logs
new-log-timestamp
- Transport between TURN client and TURN server (RFC
8656):
- AWS EC2
- security group
- TCP, UDP: 3478
- TCP, UDP: 5349
- For
Amazon
EC2 users (/etc/coturn/turnserver.conf)
external-ip=<external-ip>/<internal-ip>
- turnserver-4.5.0.5-amazon-aws-ec2-x86_64.txt
- AWS Turn Server Not Connecting #91
- security group
- Servidor / Server
sudo systemctl enable coturn.servicesudo systemctl start coturn.servicesudo systemctl status coturn.service
- Debug and logs
- /var/log/coturn/turnserver.log
- Utils and test (turnutils)
- Instal·lació / Installation
- from source
- ...
- CentOS
sudo dnf install coturn-utils
- from source
- Ús / Usage
- coturn/examples/scripts
- turnadmin
- man turnutils
- turnutils_natdiscovery
- turnutils_oauth
- turnutils_peer
- turnutils_stunclient
turnutils_stunclient myturnserver
- turnutils_uclient
- Instal·lació / Installation
- Instal·lació / Installation
- Debug
- Mozilla Firefox
- about:webrtc
- Mozilla Firefox
- Demos
- AppRTC (see logs, about:webrtc)
04Programari /Software#
- Top 13 open-source WebRTC projects to build Video conferencing and calling apps
- Gateway
- Kurento
- Kurento vs mediasoup
- OpenVidu
- Ant-Media-Server
- mediasoup
05Janus#
- Info
- What is a WebRTC Gateway anyway? (Lorenzo Miniero)
- Documentation (1.x "multistream")
- Documentation
(0.x "legacy")
- Plugins
- Config
- jcfg
- libconfig
- 6
Other Bindings and Implementations
- Bourne shell
- Compilació / Compilation
- Dependències / Dependencies
- Mageia
urpmi texinfo
- CentOS
sudo yum install ...
- Mageia
- Passos / Steps
autoreconf./configuremakesudo make install- cd contrib/ls-config
- make
- Dependències / Dependencies
- Ús / Usage
- get variable value:
ls-config -f janus.jcfg --get=general.admin_secret
- set variable value:
ls-config --file=janus.jcfg --set=general.log_to_file --data=/var/log/janus/janus.log --type=string
- get variable value:
- 6
Other Bindings and Implementations
- New
configuration file format (using libconfig)
#1180
janus-cfgconv
- libconfig
- jcfg
- Deploy
- API
- Meetecho blogs
- Community
(Google groups)
- single-thread HTTP (>=0.9.2)
- Echotest demo not working on AWS EC2
- WebRTC
to
plain RTP
- Videoroom plugin: rtp forward
- Escalabilitat / Scalability
- Issues
(github)
- Minimum version for jansson should be specified #1077
- Streaming plugin UDP multicast socket bind option to `SO_REUSEADDR` #1066
- Plugins
- janus.js
should
not depend on JQuery #879
- janus.nojquery.js
$.ajax() -> fetch().then(onsuccess, onerror)$() -> document.querySelector()jQuery.noop()
- janus.nojquery.js
- Lightweight, Live Video in a Webpage with GStreamer and WebRTC
- Projectes relacionats / Related projects
- Dependències
/ Dependencies
- Ubuntu
- ...
- CentOS
yum install epel-release git gcc
yum install libmicrohttpd-devel jansson-devel openssl-devel libsrtp-devel glib-devel opus-devel libogg-devel libsoup-devel pkgconfig gengetopt libtool autoconf automakelibnice-devel
yum install doxygen graphviz
- Mageia
- Mageia 6
urpmilibmicrohttpd-develgnutls-devel gengetoptjansson-devel lib64lus-devel
- Mageia 5
urpmilibmicrohttpd-develgnutls-devel gengetopt- Jansson
- to compile Janus >=v0.2.5 do not use jansson-devel package version 2.4, as it has an error in /usr/include/jansson.h
- Compilation:
wget http://www.digip.org/jansson/releases/jansson-2.10.tar.gztar xvzf jansson-2.10.tar.gzcd jansson-2.10./configuremakemake checksudo make installsudo ldconfig
- Mageia 6
- libmicrohttpd
- version >=0.9.59 is needed by Janus >=0.9.2
- IMPORTANT: check that no system libmicrohttpd-devel is
installed
- from tar file:
wget https://ftp.gnu.org/gnu/libmicrohttpd/libmicrohttpd-0.9.71.tar.gztar xvf libmicrohttpd-0.9.71.tar.gzcd libmicrohttpd-0.9.71./configuremakesudo make install
- Nice
- WARNING: package provided by CentOS EPEL repositories (libnice-0.1.3-4.el7.x86_64) is too old and will give problems
- Dependències / Dependencies
- CentOS
sudo yum install glib2-devel
- CentOS
- from tar file:
- Release downloads
wget https://nice.freedesktop.org/releases/libnice-0.1.16.tar.gz
tar xvf libnice-0.1.17.tar.gz
cdlibnice-0.1.17
- from git:
- GitLab:
git clone https://gitlab.freedesktop.org/libnice/libnice.git
- GitHub:
git clone https://github.com/libnice/libnice.git
cd libnice
- GitLab:
- 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
- Files
- libsrtp
- Releases
- v2
- 2.3.0
wget https://github.com/cisco/libsrtp/archive/v2.3.0.tar.gz
tar xvzf v2.3.0.tar.gz
cd libsrtp-2.3.0
./configure --enable-openssl
make
sudo make install
- 2.3.0
- v1
wget https://github.com/cisco/libsrtp/archive/v1.5.4.tar.gz
tar xvzf v1.5.4.tar.gz
cd libsrtp-1.5.4
./configure
make
sudo make install
- libusrsctp (needed when compiling
Janus with
--enable-data-channels)- Dependències / Dependencies
- CentOS
sudo yum install libtool
- CentOS
git clone https://github.com/sctplab/usrsctp
cd usrsctp
./bootstrap
./configure
make
sudo make install
sudo ldconfig
- Dependències / Dependencies
- libwebsockets (needed when
compiling Janus with no
--disable-websockets)- Dependències / Dependencies
- CentOS
sudo yum install cmake openssl-devel
- CentOS
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
- Dependències / Dependencies
- libconfig (needed to have bash tool ls-config)
- Dependències / Dependencies
- CentOS
sudo yum install texinfo flex gcc-c++ bison
- CentOS
...
autoreconf
./configure
make
sudo make install
- Dependències / Dependencies
- Ubuntu
- 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.9.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
- when compiling with --enable-post-processing
postprocessing/pp-h264.c: In function ‘janus_pp_h264_create’:
postprocessing/pp-h264.c:99:29: error: assignment of member ‘video_codec’ in read-only object
fctx->oformat->video_codec = codec->id;
^- Solució / Solution
- check for different installed versions of
ffmpeg (e.g. from ffmpeg compilation and
gstreamer compilation)
- compare:
- ffmpeg -version
- grep "define LIBAVCODEC_VERSION_" /usr/local/include/libavcodec/version.h
- reinstall ffmpeg after gstreamer compilation
- compare:
- check for different installed versions of
ffmpeg (e.g. from ffmpeg compilation and
gstreamer compilation)
- Solució / Solution
- /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;
- /usr/include/jansson.h
- when compiling with --enable-post-processing
- 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.servicesudo systemctl start janus.servicesudo systemctl stop janus.service
- Configuració / Setup
- /etc/janus/janus.jcfg
- debug
general: {
log_to_file = "/var/log/janus/janus.log" # Whether to use a log file or not
debug_level = 5 # Debug/logging level, valid values are 0-7
...
}
- debug
- /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
- debug
- /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.logCouldn't start secure webserver on port 8089...- Manually start janus as user janus,
with high debug level
sudo -isystemctl 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)
- check that the user that is
running the service has permission
to access dirs:
- admin
[admin]
admin_http = yes
admin_port = 7088
admin_https = yes
admin_secure_port = 7889
- CORS
- Amazon AWS
EC2
- Janus >=v0.4.4
- echo test demo needs a libnice version >0.1.14 (e.g. 0.1.16 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):
- when launching janus (ICE
failed Video Room Plugin #441)
janus --nat-1-1=1.2.3.4
- in janus.jcfg
nat_1_1_mapping = "1.2.3.4"
- when launching janus (ICE
failed Video Room Plugin #441)
- 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
- /etc/janus/janus.jcfg
- 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/admincurl -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
janussession_idplugin
Plugin specific
plugin_specific
...
Handle flags
flags
SDPs
sdps
PeerConnection
streams
Header
idready
SSRC
ssrc
ICE components
components
state: connecting, ready, disconnected, failedlocal-candidatesremote-candidatesselected-pairdtlsin-statsout-stats
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
-
- 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
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- tshark
- server
- get destination port:
- client: from Firefox about:webrtc "Remote candidate"
- server /var/log/janus/janus.log: a=candidate
tshark -d udp.port==<destination_port>,rtp udp port <destination_port>- 8857
14.757747410 192.168.0.101 -> 192.168.0.108
RTP 153 PT=DynamicRTP-Type-109,
SSRC=0xDE951CF3, Seq=61918, Time=1643530196
8862 14.779327125 192.168.0.101 -> 192.168.0.108 RTP 1126 PT=DynamicRTP-Type-120, SSRC=0xC0C0D699, Seq=31111, Time=617518567
...
- 8857
14.757747410 192.168.0.101 -> 192.168.0.108
RTP 153 PT=DynamicRTP-Type-109,
SSRC=0xDE951CF3, Seq=61918, Time=1643530196
- ...
- get destination port:
- server
- 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
}
}- ...
-
- if(!strcasecmp(request_text, "list"))
- if(!strcasecmp(request_text, "create"))
- ...
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);
},
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- Streaming API
- config
- /etc/janus/janus.plugin.streaming.cfg
-
config file config file
streamer
browser notes
/etc/janus/
janus.plugin.streaming.jcfg/etc/janus/janus.plugin.streaming.cfg (OBSOLETE)
Chrome
Firefox
VP8 / Opus
[gstreamer-sample]
type = rtp
id = 1
description = Opus/VP8 live stream coming from gstreamer
audio = yes
video = yes
audioport = 5002
audiopt = 111
audiortpmap = opus/48000/2
videoport = 5004
videopt = 100
videortpmap = VP8/90000
secret = adminpwd- plugins/streams/test_gstreamer_1.sh
- streaming RTP VP8/Opus with Gstreamer
- streaming
RTP VP8/Opus with ffmpeg
ffmpeg -re -f lavfi -i "testsrc=size=320x180:rate=24" -f lavfi -i "sine=frequency=440:sample_rate=48000, aformat=channel_layouts=stereo" -c:v vp8 -b:v 700k -an -f rtp -payload_type 100 rtp://127.0.0.1:5004 -c:a opus -strict -2 -b:a 64k -vn -f rtp -payload_type 111 rtp://127.0.0.1:5002 -sdp_file /tmp/vp8_opus_unicast.sdp
[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
- streaming RTP VP8/Opus with Gstreamer
- streaming
RTP VP8/Opus with ffmpeg
ffmpeg -re -f lavfi -i "testsrc=size=320x180:rate=24" -f lavfi -i "sine=frequency=440:sample_rate=48000, aformat=channel_layouts=stereo" -c:v vp8 -b:v 700k -an -f rtp -payload_type 100 rtp://232.3.4.5:5004-c:a opus -strict -2 -b:a 64k -vn -f rtp -payload_type 111 rtp://232.3.4.5:5002?pkt_size=1400-sdp_file /tmp/vp8_opus_multicast.sdp?pkt_size=1400
ok
ok
H.264
(unicast)h264-sample: {
type = "rtp"
id = 10
description = "H.264 live stream coming from gstreamer"
audio = false
video = true
videoport = 8004
videopt = 126
videocodec = "h264"
videofmtp = "profile-level-id=42e01f;packetization-mode=1"
#secret = "adminpwd"
}
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://127.0.0.1:8004 -sdp_file /tmp/h264.sdp- gst-launch-1.0 -v videotestsrc ! videoconvert ! x264enc ! video/x-h264,profile=baseline ! rtph264pay config-interval=10 pt=126 ! udpsink host=127.0.0.1 port=8004
- gst-launch-1.0
-v videotestsrc !
video/x-raw,width=1280,height=720
! videoconvert ! x264enc !
video/x-h264,profile=baseline
! rtph264pay config-interval=10
pt=126 ! udpsink host=127.0.0.1
port=8004
janus.plugin.streaming.jcfg
# All browsers also support H.264, often through Cisco's OpenH264 plugin.
# The only profile that is definitely supported is the baseline one, which
# means that if you try a higher one it might or might not work. No matter
# which profile you encode, though, you can put a custom one in the SDP if
# you override the fmtp SDP attribute via 'videofmtp'. The following is an
# example of how to create a simple H.264 mountpoint: you can feed it via
# an x264enc+rtph264pay pipeline in gstreamer, an ffmpeg script or other.
#
h264-sample: {...
IMPORTANT: in order to have it working in Firefox, second byte cannot be 00 (not constrained); it must be e0 (constrained)profile-level-id ffmpeg Chrome Firefox 42e01f-profile:v baseline -level:v 31ok ok 4d0033-profile:v main -bf 0 -level:v 51ok not ok 4de033
-profile:v main -bf 0 -level:v 51ok
ok
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
H.264
(multicast)
[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.sdpffmpeg -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?pkt_size=1400
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.
H.264 / Opus
[h264-opus-multicast]
type = rtp
id = 4246246658112756
description = h264_opus_multicast
audio = yes
audioport = 8002
audiomcast = 232.3.4.5
audiopt = 111
audiortpmap = opus/48000/2
audiofmtp = sprop-stereo=1
video = yes
videoport = 8004
videomcast = 232.6.7.8
videopt = 126
videortpmap = H264/90000
videofmtp = packetization-mode=1\;profile-level-id=42e01f
data = noffmpeg -re -f lavfi -i "testsrc=size=320x180:rate=24"-f lavfi -i "sine=frequency=440:sample_rate=48000, aformat=channel_layouts=stereo"-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?pkt_size=1400-c:a opus -strict -2 -b:a 64k -vn -f rtp -payload_type 111 rtp://232.3.4.5:8002-sdp_file /tmp/h264_opus_multicast.sdp?pkt_size=1400
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- Problemes / Problems
- Tallafoc / Firewall
- Chrome no mostra el vídeo / Chrome does not show video
- Video no fluid / Video is not fluent
- NACKs
- janus.plugin.streaming.c
(github)
- videoroom
- janus.plugin.videoroom.c (github)
- Video Room API (VideoRoom
plugin documentation)
-
request
event
synchronous
- create
- destroy
- edit
- exists
- list
- allowed
- kick
- listparticipants
-
asynchronous
- join
- joinandconfigure
- configure
- publish
- unpublish
- start
- pause
- switch
- stop
- add
- remove
- leave
- ...
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
-
- Video Room API (VideoRoom
plugin documentation)
- Problemes / Problems
- janus.plugin.videoroom.c (github)
- plain RTP
- streaming
- 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
- janus.cfg
- Problemes / Problems
- Compilació / Compilation
- AWS EC2
- Plugins
- Accés des de client / Access from client (Javascript
console)
- Javascript console
hangup_media(plugin.h) not called in Firefox- solucionat a
Firefox 55 / solved in Firefox 55
- Media/WebRTC/ReleaseNotes/55
- WebRTC:Networking:
- bug 1303867 Missing DTLS alert on PeerConnection.close()
- WebRTC:Networking:
- Media/WebRTC/ReleaseNotes/55
- meetecho-janus Google groups: hangup, destroy_session, DTLS-SRTP
- solucionat a
Firefox 55 / solved in Firefox 55
WebRTC error... {"name":"InternalError","message":"Starting video failed"}(Firefox)
WebRTC error... {"name":"NotReadableError","message":"Could not start video source"}(Chrome)- Solució / Solution
- No podeu fer servir alhora la mateixa webcam des de dos navegadors diferents / You cannot use the same webcam from two browsers (Firefox/Chrome) at the same time
- Solució / Solution
- iOS
- Demos
- Echo test not working (always spinning)
- check admin
response
- components
- state: connecting
- dtls
- valid: false
- components
- check admin
response
- Echo test not working (always spinning)
- Browser debug logs
[...:WARNING:nack_module.cc(237)] Sequence number xxxx removed from NACK list due to max retries.- ...
- Javascript console
- Missatges al servidor / Messages on server
(/var/log/janus/janus.log)
[ERR] [dtls.c:janus_dtls_srtp_incoming_msg:923] ... Oops, error creating inbound SRTP session for component 1 in stream 1??
[ERR] [dtls.c:janus_dtls_srtp_incoming_msg:924] ... -- 1 (srtp_err_status_fail)- Oops, error creating inbound SRTP session for component 1 in stream 1 #2024
- Solució / Solution
- enable openssl (
--enable-openssl) or nss (--enable-nss) when compiling libsrtp:./configure--enable-openssl
- enable openssl (
Not video and not audio? dropping (SSRC...)- (debug_level = 5)
Retransmitted ... packets due to NACK (video stream #0)- when using streaming plugin
- Issue
with
streaming plugins: tons of video NACK
- janus.cfg
max_nack_queue = 500
- janus.cfg
- everytime at the same point in video (video
freezes for a short time), you get some NACK
retransmissions
- Solution: reduce the size of rtp packet of
the source that feeds the mountpoint. E.g.
if using ffmpeg:
ffmpeg ... -f rtp rtp://230.15.129.230:10956?pkt_size=1400
- Solution: reduce the size of rtp packet of
the source that feeds the mountpoint. E.g.
if using ffmpeg:
- Issue
with
streaming plugins: tons of video NACK
- when using streaming plugin
Waiting for candidates-done callback...- Only visible when:
- janus.cfg
debug_level = 5
- janus.cfg
- Debug
nat
libnice-stun-DEBUG: STUN transaction retransmitted (timeout 397ms).
libnice-stun-DEBUG: STUN transaction retransmitted (timeout 793ms).
libnice-stun-DEBUG: STUN transaction retransmitted (timeout 3194ms).
libnice-stun-DEBUG: STUN transaction retransmitted (timeout 6389ms).
libnice-stun-DEBUG: STUN transaction retransmitted (timeout 12784ms).
libnice-DEBUG: Agent 0x7fe068009050 : bind discovery timed out, aborting discovery item.
- Solucions / Solutions
- do NOT use the following settings:
- janus.cfg
[nat]
stun_port = 19302
stun_server = stun3.l.google.com
- janus.cfg
- if you have more than one network device
- If you have a network device with no internet connection (e.g. mcd in aws), add it to the black list:
- janus.cfg
ice_ignore_list = vmnet,172.16.
- do NOT use the following settings:
- Only visible when:
[ERR] [ice.c:janus_ice_cb_component_state_changed:1383] [3053596813] ICE failed for component 1 in stream 1...- Getting ICE Failed when working over NAT (but works in local network) #412
- check that nice is working (no message "nice_agent_set_port_range unavailable, port range disabled" in /var/log/messages)
- check ports really used
[ERR] [ice.c:janus_ice_check_failed:1548] [5472388112306727] ICE failed for component 1 in stream 1...- Debug
Janus
- problems
with DTLS
- dtls alert error #582
- Implemented new OpenSSL BIO filter to fix fragmentation issue in DTLS… #254
- DTLS error when using 4096 key/cert #252
- DTLS1_READ_BYTES:tlsv1 alert decrypt error #136
- DTLS
failure
in 0.2.2
- MTU
[WARN] [...] Still waiting for the DTLS stack for component 1 in stream 1...- ...
- problems
with DTLS
- ICE
Failed #90
- DTLS certificates
- Chrome debug
- public TURN servers
- ICE failed Video Room Plugin #441
- Debug
Janus
[WARN] [janus.transport.http]: Error in GNU libmicrohttpd daemon.c:1826: close failedor
[Wed May 16 10:32:21 2018] [WARN] [janus.transport.http]: Error in GNU libmicrohttpd daemon.c:3092: Close socket failed.
[Wed May 16 10:32:21 2018] [WARN] [janus.transport.http]: Error in GNU libmicrohttpd daemon.c:3028: Failed to lock mutex.
[Wed May 16 10:32:21 2018] [WARN] [janus.transport.http]: Error in GNU libmicrohttpd daemon.c:3101: Failed to unlock mutex.
[Wed May 16 10:32:21 2018] [WARN] [janus.transport.http]: Error in GNU libmicrohttpd daemon.c:3081: Failed to remove FD from epoll set[WARN] nice_agent_set_port_range unavailable, port range disabled- [ERR] [ice.c:janus_ice_cb_component_state_changed:643:] ICE failed for handle 1716821054... #112
- Solució / Solution
- do not use package libnice in repository. Compile it yourself instead
Transport plugins folder: /usr/lib/janus/transports
Loading transport plugin 'libjanus_pfunix.so'...
[WARN] Unix Sockets server disabled (Janus API)
[WARN] Unix Sockets server disabled (Admin API)
[WARN] No Unix Sockets server started, giving up...
[WARN] The 'janus.transport.pfunix' plugin could not be initialized
[FATAL] [janus.c:main:4167] No Janus API transport is available... enable at least one and restart Janus- Solució / Solution
- install package libmicrohttpd
- Solució / Solution
routines:dtls1_read_bytes:tlsv1 alert protocol version- janus error:1410242E:SSL routines:dtls1_read_bytes:tlsv1 alert protocol version #1560
- with Chrome version >=87.0
- Solució / Solution
- install a recent version of Janus (e.g. 0.10.2 is working fine)
- Accés des de client / Access
from client
- Info
- http://127.0.0.1:8088/janus/info
- https
- Problemes / Problems
- Sense reposta / No response
- Solucions / Solutions
- Check firewall
- Check open ports
- ...
- Solucions / Solutions
- Sense reposta / No response
- API
- with curl
-
curl using janus.js
(either from html or an intermediate js)general values
janus_url_base=http://192.168.1.130:8088janus_url_base=https://192.168.1.130:8089janus_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
var server = "http://192.168.1.128:8088/janus";Janus.init({...})
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}"var janus = new Janus({...})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}"
janus.attach({...})send a message to the plugin
(e.g.: janus.plugin.streaming)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}\"}"
(send message_body)
curl -i -k -X POST -H 'Content-Type: application/json' --data-binary "{\"janus\":\"message\", \"transaction\":\"${transaction}\", \"body\":${message_body} }" "${plugin_url}"pluginHandle.send({...})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
janus.destroy({...})Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
-
- with
Javascript
- janus.js
-
Janus.init()debug: ...dependencies: Janus.useDefaultDependenciescallback: 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/falseaudioRecv: true/falseaudio: true/falseaudio: {...}deviceId: ...
videoSend: true/falsevideoRecv: true/falsevideo: true/falsevideo: "lowres"/"lowres-16:9"/"stdres"/"stdres-16:9"/"hires"/"hires-16:9"
// 320x240/320x180/640x480/640x360/1280x720video: "screen"video: {...}deviceId: ...
// Janus.listDevices(callback)width: ...height: ...
data: true/falsefailIfNoAudio: true/falsefailIfNoVideo: true/falsescreenshareFrameRate: ...
trickle: true/falsestream: ...success: function(jsep) {...}
// got sdperror: 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(...)
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- Exemples / Examples
- basic session creation (all inside the
document ready function)
<!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 (function
plugin_client, called from document ready)
<!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>
- multiple player from streaming 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 streaming = null;
// visible players
var number_feeds = 6;
var feeds = [];
// available mountpoints in Janus streaming plugin
var mountpoints = [];
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) {
streaming = pluginHandle;
Janus.log("## Plugin attached: " + streaming.getPlugin() + ", id=" + streaming.getId() );
updateStreamsList();
}
function _onError(message) {
Janus.error(message);
}
function _onMessage(msg, jsep) {
Janus.debug("## Got a message");
Janus.debug(msg);
if(jsep !== undefined && jsep !== null) {
Janus.debug("## Handling SDP as well...");
Janus.debug(jsep);
}
}
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");
}
function updateStreamsList() {
// get list of available mountpoints in streaming plugin
var body = { "request": "list" };
streaming.send(
{
"message": body,
success: function(result) {
if(result === null || result === undefined) {
bootbox.alert("Got no response to our query for available streams");
return;
}
if(result["list"] !== undefined && result["list"] !== null) {
mountpoints = result["list"];
Janus.debug(mountpoints);
populateAll(mountpoints);
}
}
});
}
function populateAll (mountpoints) {
// start a player for each mountpoint
Janus.log("######## [populateAll]");
for(var m in mountpoints) {
var mountpoint_id = mountpoints[m]["id"];
var type = mountpoints[m]["type"];
var description = mountpoints[m]["description"];
newRemoteFeed(mountpoint_id, type, description);
}
}
function newRemoteFeed(mountpoint_id, type, description) {
// start a player
Janus.log("######## [newRemoteFeed] mountpoint_id: "+ mountpoint_id + "; type: " + type + "; description: " + description );
var remoteFeed = null;
janus.attach(
{
plugin: "janus.plugin.streaming",
success: function(pluginHandle) {
remoteFeed = pluginHandle;
Janus.log("######## [newRemoteFeed] Plugin attached! (" + remoteFeed.getPlugin() + ", id=" + remoteFeed.getId() + ")");
// assign a player
for(var i=1;i<6;i++) {
if(feeds[i] === undefined || feeds[i] === null) {
feeds[i] = remoteFeed;
remoteFeed.rfindex = i;
break;
}
}
// send watch request
var body = { "request": "watch", "id": mountpoint_id };
remoteFeed.send({"message": body});
},
error: function(error) {},
onmessage: function(msg, jsep) {
// received a message
Janus.debug("######## [newRemoteFeed.onmessage] Got a message (mountpoint_id: " + mountpoint_id + ")");
Janus.debug(msg);
// regular message
var result = msg["result"];
if(result != undefined && result != null) {
Janus.debug(result);
if(result["status"] !== undefined && result["status"] !== null) {
var status = result["status"];
if(status === 'starting')
Janus.debug("######## [newRemoteFeed.onmessage] Starting, please wait...");
else if(status === 'started')
Janus.debug("######## [newRemoteFeed.onmessage] Started");
else if(status === 'stopped')
Janus.debug("######## [newRemoteFeed.onmessage] Stopped");
} else if(msg["streaming"] === "event") {
// Is simulcast in place?
var substream = result["substream"];
var temporal = result["temporal"];
if((substream !== null && substream !== undefined) || (temporal !== null && temporal !== undefined)) {
if(!simulcastStarted) {
simulcastStarted = true;
addSimulcastButtons();
}
// We just received notice that there's been a switch, update the buttons
updateSimulcastButtons(substream, temporal);
}
}
} else if(msg["error"] !== undefined && msg["error"] !== null) {
Janus.error("######## [newRemoteFeed] Error: ", msg["error"]);
}
// message with an offer sdp
if(jsep !== undefined && jsep !== null) {
Janus.debug("######## [newRemoteFeed.onmessage] Received an offer sdp (mountpoint_id: " + mountpoint_id + ")");
Janus.debug(jsep);
// create an answer with an sdp
remoteFeed.createAnswer(
{
jsep: jsep,
media: { audioSend: false, videoSend: false }, // We want recvonly audio/video
success: function(jsep) {
Janus.debug("######## [newRemoteFeed.onmessage] Sending an answer sdp (mountpoint_id: " + mountpoint_id + ")");
Janus.debug(jsep);
var body = { "request": "start" };
remoteFeed.send({"message": body, "jsep": jsep});
//$('#watch').html("Stop").removeAttr('disabled').click(stopStream);
},
error: function(error) {
Janus.error("WebRTC error:", error);
bootbox.alert("WebRTC error... " + JSON.stringify(error));
}
});
}
},
onremotestream: function(stream) {
// a remote stream is available
Janus.debug("######## [newRemoteFeed.onremotestream] Remote stream is available (mountpoint_id: " + mountpoint_id + ")");
// first time?
if($('#remotevideo'+remoteFeed.rfindex).length > 0) {
// Been here already: let's see if anything changed
Janus.debug("######## [newRemoteFeed.onremotestream] Been there already");
var videoTracks = stream.getVideoTracks();
if(videoTracks && videoTracks.length > 0 && !videoTracks[0].muted) {
Janus.debug(videoTracks);
//$('#novideo'+remoteFeed.rfindex).remove();
//if($("#remotevideo"+remoteFeed.rfindex).get(0).videoWidth)
// $('#remotevideo'+remoteFeed.rfindex).show();
}
return;
}
// create the html5 player
$('#videoremote' + remoteFeed.rfindex).append( '<h2>' + description + '</h2> <video class="rounded centered" id="remotevideo' + remoteFeed.rfindex + '" width=320 height=240 controls autoplay/><hr>');
// attach the remote stream to the html5 video player
Janus.attachMediaStream($('#remotevideo' + remoteFeed.rfindex).get(0), stream);
},
oncleanup: function() {}
}
);
}
};
</script>
<script type="text/javascript">
// var janus_server = "https://192.168.1.114:8089/janus";
var janus_server = null;
if(window.location.protocol === 'http:')
janus_server = "http://" + window.location.hostname + ":8088/janus";
else
janus_server = "https://" + window.location.hostname + ":8089/janus";
$(document).ready(function() {
client = new plugin_client(
{
server: janus_server
}
);
client.start();
});
</script>
</head>
<body>
<h1>Multiple streams</h1>
<div id="logs"></div>
<div id="videoremote1"></div>
<div id="videoremote2"></div>
<div id="videoremote3"></div>
<div id="videoremote4"></div>
<div id="videoremote5"></div>
<div id="videoremote6"></div>
</body>
- basic session creation (all inside the
document ready function)
-
- janus.js
- with curl
- Info
- Demos (test web server)
- Available demos
- Streaming
- Problemes / Problems
- llista buida al desplegable «Stream list»
- Solució / Solution
- restart janus service
- ...
- http-server (NodeJS)
- Install NodeJS via nvm, and then:
- install http server
npm install -g http-server
- install 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/
- run http-server
- 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
https://<your_demos_server_ip>:8080/https://<your_demos_server_ip>:8080/demos/- Screen sharing
- 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
- Des del navegador, accepteu manualment
el certificat autosignat / From your
browser, manually accept self-signed
certificate in
- Solució / Solution:
- server
- Install NodeJS via nvm, and then:
- nginx
- server
- Janus through Nginx
- Deploying Janus behind a web frontend
- /etc/nginx/default.d/janus.conf
# janus (webrtc server)
location /janus {
proxy_pass http://127.0.0.1:8088/janus;
}
- SELinux
setsebool -P httpd_can_network_connect 1- chcon -u system_u -t httpd_config_t /etc/nginx/default.d/janus.conf
- access to demos
- /etc/nginx/default.d/janus_demos.conf
# janus demos (webrtc server)
location /demos {
root /usr/share/janus;
}
- SELinux
- chcon -u system_u -t httpd_config_t /etc/nginx/default.d/janus_demos.conf
- /etc/nginx/default.d/janus_demos.conf
- demos must point to Janus through nginx (instead
of ports 8088/8089):
cd /usr/share/demossed -i '/var janus = null;/ i var server = "/janus";' *.js
- https
- generate
self-signed certificate and key
(/etc/pki/nginx/server.crt,
/etc/pki/nginx/private/server.key)
mkdir -p /etc/pki/nginx/privatecd /etc/pki/nginxopenssl req -new -nodes -keyout private/server.key -sha256 -x509 -out server.crt
- /etc/nginx/conf.d/ssl_8080.conf
# Settings for a TLS enabled server.
server {
listen 8080 ssl http2 default_server;
listen [::]:8080 ssl http2 default_server;
server_name _;
root /usr/share/nginx/html;
ssl_certificate "/etc/pki/nginx/server.crt";
ssl_certificate_key "/etc/pki/nginx/private/server.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
- SELinux
- chcon -u system_u -t httpd_config_t /etc/nginx/default.d/ssl_8080.conf
- generate
self-signed certificate and key
(/etc/pki/nginx/server.crt,
/etc/pki/nginx/private/server.key)
sudo systemctl start nginx.service
- Janus through Nginx
- client
https://<your_demos_server_ip>/janus/info- Problemes / Problems
- on server logs:
connect() to 127.0.0.1:8088 failed (13: Permission denied) while connecting to upstream, client: ...Solució / Solution
- on server logs:
- Problemes / Problems
https://<your_demos_server_ip>/demos
- server
- Available demos
06UV4L#
- Installation
for
ARM (Raspberry Pi)
curl http://www.linux-projects.org/listing/uv4l_repo/lrkey.asc | sudo apt-key add -- /etc/apt/sources.list
deb http://www.linux-projects.org/listing/uv4l_repo/raspbian/ jessie main
sudo apt-get updatesudo apt-get install uv4l uv4l-raspicamsudo apt-get install uv4l-raspicam-extrassudo service uv4l_raspicam restart/etc/uv4l/uv4l-raspicam.conf
- Test
dd if=/dev/video0 of=snapshot_$(date '+%Y-%m-%dT%H%M%SZ' --utc).jpeg bs=11M count=1gpicview snapshot_...jpeg
pkill uv4l- optional
- Streaming server
- sudo apt-get install uv4l-server
- drivers
-
module
sudo apt-get install ...
description
uv4l-raspicam
uv4l-raspicam-extras
Raspberry Pi CSI Camera Boards and
TC358743 HDMI to MIPI converter chipset
uv4l-uvcUSB video class
uv4l-xscreenany portion of X screen
uv4l-mjpegstreamMJPEG stream: IP camera, UV4L streaming server...
uv4l-dummyfake
uv4l-raspidispRaspberry Pi HDMI-out
Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
-
- Streaming server
- 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-serveruv4l [ 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/ Aquesta taula continua cap a la dreta — desplaça-la o gira el mòbil.
- debug
tail -f /var/log/syslog
- WebRTC extension (two-way audio/video)
- Janus
Gateway (join a room with Janus)
- RPi VideoConference Demo OS
- UV4L
with
Janus instances on AWS
server-option = --webrtc-rtcp-mux-policy=1
http://www.francescpinyol.cat/webrtc.html
Primera versió: / First version: 10.XI.2017
Darrera modificació: 26 de gener de 2024 / Last update: 26th July
2024