DesignSpark Electrical Logolinkedin

Building a Raspberry Pi 2 WebRTC camera

title

Using Janus and gStreamer to feed video straight into the browser.

WebRTC enables browser-based Real Time Communications (RTC) via simple APIs. It is royalty free and powerful. We can use Janus, a general purpose WebRTC gateway, to stream video from a Raspberry Pi directly to browsers, without having to install any extra software on client machines.

We will use a gStreamer pipeline to take the video output from a Raspberry Pi camera module and encode the video in H.264 format before passing it on to Janus.

Hardware used:

Initial Raspberry Pi setup

To begin with we will assume that:

  • you are running the latest version of Raspbian (version 'January 2015' at time of writing).
  • you have a Raspberry Pi camera module attached.
  • the network is configured and you can SSH into the Pi.

First we will enable the Pi camera module:

  • $ sudo raspi-config
  • Choose 'Enable Camera' and press return
  • Save and quit raspi-config

Testing the camera

Now that we have enabled the camera module we can test that it is working correctly using the command line tool raspistill.

$ raspistill -o test.jpg

This should have taken a photo. Type ls to see if test.jpg has appeared in your directory.

Copy this photo over to your local machine and open it with an image viewer. If it needs rotating you can use the options -vf and -hf for vertical and horizontal flipping when taking the photo. E.g:

$ raspistill -vf -hf -o test2.jpg

Once you are happy the camera is working and you know which extra options to use we can move on to getting the camera streaming video over the network.

Setting up Janus

It is worth taking a look at the Janus GitHub repository for some background information and to assist with installation.

First make sure your Apt cache is up to date:

$ sudo aptitude update

Next we need to install build dependencies as follows:

$ sudo aptitude install libmicrohttpd-dev libjansson-dev libnice-dev libssl-dev libsrtp-dev libsofia-sip-ua-dev libglib2.0-dev libopus-dev libogg-dev libini-config-dev libcollection-dev pkg-config gengetopt libtool automake dh-autoreconf

We will not be making use of Data Channels, WebSockets or RabbitMQ so we don't need to install the optional dependencies.

Next we can clone the repository onto the Pi, build and install:

$ git clone https://github.com/meetecho/janus-gateway.git

$ cd janus-gateway

$ sh autogen.sh

$ ./configure --disable-websockets --disable-data-channels --disable-rabbitmq --disable-docs --prefix=/opt/janus

$ make

$ sudo make install

Now run a comand to install default configuration files:

$ sudo make configs

Next modify /opt/janus/etc/janus/janus.plugin.streaming.cfg (we will use nano but you may use an editor of your choice):

$ sudo nano janus.plugin.streaming.cfg

Add the following lines (and comment out the other example streams by adding a semicolon before each line)

[gst-rpwc]

type = rtp

id = 1

description = RPWC H264 test streaming

audio = no

video = yes

videoport = 8004

videopt = 96

videortpmap = H264/90000

videofmtp = profile-level-id=42e028\;packetization-mode=1

title

Save and exit the editor.

Installing gStreamer and Nginx

gStreamer is a pipeline-based multimedia framework that we will use to encode the video for streaming. To install gstreamer:

$ sudo aptitude install gstreamer1.0

Nginx is a lightweight web server that we will use to serve the Janus demos, specifically the streaming example. To install this:

$ sudo aptitude install nginx

Now copy the Janus HTML content to the Nginx server root:

$ sudo cp -r /opt/janus/share/janus/demos/ /usr/share/nginx/www/

Now start Nginx:

$ sudo service nginx start

Streaming test

title

Now open two SSH shell sessions logged into the Pi. We will run one command in each shell.

In the first shell execute the following:

$ raspivid --verbose --nopreview -hf -vf --width 640 --height 480 --framerate 15 --bitrate 1000000 --profile baseline --timeout 0 -o - | gst-launch-1.0 -v fdsrc ! h264parse ! rtph264pay config-interval=1 pt=96 ! udpsink host=127.0.0.1 port=8004

This will take video from the camera, format it and pipe it into gStreamer to be H.264 encoded, before sending it on to Janus.

In the second shell navigate to /opt/janus/bin/ and execute:

$ ./janus -F /opt/janus/etc/janus/

This starts the Janus WebRTC gateway.

On a different computer connected to the same network, ensure you running a recent version of Firefox (we are using build 37). Enter the following into the address bar:

http:///streamingtest.html

This will load the streaming demo that is bundled with Janus. Click the 'Start' button next to the heading, choose your stream and click 'Watch or Listen' to display the video stream from the Pi directly into your browser!

title

Enclosure build

title

To complete the hardware side of the project we made a simple enclosure for the Pi and Pi camera module that can be mounted on a tripod or CCTV camera mount.

See attached for more details, including the design files for laser cutting.

With thanks to Neil Stratford and Tobias Wolf for info useful in getting Janus working.

This project is shared under - Creative Commons Attribution 3.0 Unported (CC BY 3.0)

maker, hacker, doer

Comments

0 Votes
igorkh1988

February 20, 2017 10:45

When I call 'make' - then receive an error:

CC plugins/plugins_libjanus_streaming_la-janus_streaming.lo
plugins/janus_streaming.c: In function 'janus_streaming_create_fd':
plugins/janus_streaming.c:2414:33: error: 'SO_REUSEPORT' undeclared (first use in this function)

Do you have any ideas how to fix it?

I have Raspbian GNU/Linux installed

1 Votes
AlgoRhythm

November 23, 2016 07:46

@vandan1 or anyone else with the same issue:

I found that I had to go edit /etc/nginx/sites-available/default
make sure the root is specified correctly
for this tutorial, "root /usr/share/nginx/www/;"

0 Votes
mudit

July 14, 2016 06:33

Can u Plz tell me if this works with a usb camera....it is compatible though cuz i can take images
if yes then how different would the commands be

0 Votes
smink

July 7, 2016 10:49

Here is a complete ready-to-use image for RaspberryPi which allows to entirely host Janus VideoRooms on the Rpi itself and allows many Rpi's, PC, Smartphones to interconnect in two-way audio/video conferences: http://www.linux-projects.org/rpi-video ... e-demo-os/

0 Votes
coienyp

March 17, 2016 10:37

Thanks for the great work.
May i know can if audio can be implemented both ways for Video Chat?

Please advise. Thanks

0 Votes
falcon76

March 16, 2016 21:00

Good tutorial. Big respect for doing such freat things.
Unfortunately I finished all of the steps browser (firefox) shows only error code 404 and nginx/1.6.2 name.
Any idea to display webpage correcrly?
Thanks in advance.

0 Votes
smink

March 5, 2016 00:51

For those who are interested, according to this tutorial UV4L now supports the Janus Video Room plugin:

http://www.linux-projects.org/modules/s ... #example17

I tried it. It was as easy as typing the room and username and clicking on the start button on the web interface. Perfect realtime audio & video.

0 Votes
AIMA2015

January 28, 2016 20:36

Dear stuartChilds,

Thank you for the great blog. I carefully followed your instructions on how to get Janus working; however I am getting the following:

Starting Meetecho Janus (WebRTC Gateway) v0.1.0
---------------------------------------------------

Checking command line arguments...
Debug/log level is 4
Debug/log timestamps are disabled
Debug/log colors are enabled
Adding 'vmnet' to the ICE ignore list...
Using 10.10.1.145 as local IP...
[WARN] Token based authentication disabled
Initializing ICE stuff (Full mode, ICE-TCP candidates disabled, IPv6 support disabled)
[WARN] Janus is deployed on a private address (10.10.1.145) but you didn't specify any STUN server! Expect trouble if this is supposed to work over the internet and not just in a LAN...
BUNDLE is NOT going to be forced
rtcp-mux is NOT going to be forced
ICE handles watchdog started
Fingerprint of our certificate: D2:B9:31:8F:DF:24:D8:0E:ED:D2:EF:25:9E:AF:6F:B8:34:AE:53:9C:E6:F3:8F:F2:64:15:FA:E8:7F:53:2D:38
Plugins folder: /opt/janus/lib/janus/plugins
Loading plugin 'libjanus_videocall.so'...
JANUS VideoCall plugin initialized!
VideoCall watchdog started
Loading plugin 'libjanus_echotest.so'...
JANUS EchoTest plugin initialized!
Loading plugin 'libjanus_recordplay.so'...
EchoTest watchdog started
JANUS Record&Play plugin initialized!
Loading plugin 'libjanus_voicemail.so'...
JANUS VoiceMail plugin initialized!
Loading plugin 'libjanus_sip.so'...
JANUS SIP plugin initialized!
Loading plugin 'libjanus_videoroom.so'...
JANUS VideoRoom plugin initialized!
Loading plugin 'libjanus_audiobridge.so'...
JANUS AudioBridge plugin initialized!
VideoRoom watchdog started
SIP watchdog started
Loading plugin 'libjanus_streaming.so'...
Record&Play watchdog started
VoiceMail watchdog started
AudioBridge watchdog started
JANUS Streaming plugin initialized!
Transport plugins folder: /opt/janus/lib/janus/transports
Loading transport plugin 'libjanus_rabbitmq.so'...
[WARN] RabbitMQ support disabled (Janus API)
[WARN] RabbitMQ support disabled (Admin API)
[WARN] RabbitMQ support disabled for both Janus and Admin API, giving up
Loading transport plugin 'libjanus_websockets.so'...
[ERR] [plugins/janus_streaming.c:janus_streaming_relay_thread:3415] [gst-rpwc] Error polling... 4 (Interrupted system call)
Streaming watchdog started
WebSockets server started (port 8188)...
[WARN] Secure WebSockets server disabled
[WARN] Admin WebSockets server disabled
[WARN] Secure Admin WebSockets server disabled
JANUS WebSockets transport plugin initialized!
Loading transport plugin 'libjanus_http.so'...
WebSocket (Janus API) thread started
HTTP webserver started (port 8088, /janus path listener)...
[WARN] HTTPS webserver disabled
[WARN] Admin/monitor HTTP webserver disabled
[WARN] Admin/monitor HTTPS webserver disabled
JANUS REST (HTTP/HTTPS) transport plugin initialized!
HTTP/Janus sessions watchdog started

As you can see I am getting an error at [plugins/janus_streaming.c:janus_streaming_relay_thread:3415] . Can you please help me figure out what can be possibly wrong? Any help would be greatly appreciate it.

Thanks a lot.

0 Votes
smink

January 15, 2016 08:46

Hi,

I tried UV4L at http://linux-projects.org. It can now also stream H264 720p video (together with audio optionally) at full speed, *NO LATENCY* and minimal CPU consumption. It does that with WebRTC in Firefox and no gstreamer sauce is needed. Would it be possible to integrate it with Janus?

0 Votes
dukelec

January 7, 2016 03:11

Could you test the video latency in microseconds?
Test method reference:
https://www.raspberrypi.org/forums/view ... 3&start=26
Thanks.

0 Votes
richard the boffin

December 3, 2015 23:49

Just had a go at this.

gstreamer1.0 isn't found any more, apparently it's part of epiphany now?

I did need to get the gstreamer-tools though.

I also found that the streamer demo is actually in a demos subfolder: http://192.168.1.69/demos/streamingtest.html

So after that I now jet the Janus page up, but still no sign of the video stream. Any clues as to what to check next?

0 Votes
gilles13

December 2, 2015 11:20

Hi stuartChilds,

Thanks a lot for your reply.

I have managed to solve the "freeze" issue, quite simply really: I just added a keyframe refresh rate in the command line, such as -g 4, which is pretty frequent but it does the job. I believe the default is 30 (1 per second at 30 fps) but this is way too slow when the subject or the camera moves a lot.

As for using Chrome with H264, I am still stuck, Chrome is now supposed to support H264. I have found where, in janus.js, it fails, but it does not help. I'll try re-encoding the stream to VP8 before feeding it to the server, and see if it's encoding related or browser related.

0 Votes
stuartChilds

November 30, 2015 11:17

Thanks all for the comments.
@ gilles13 We had problems with Chrome, too - it seems Firefox is simply better at supporting some things than Chrome!

Regarding the video freezing, it's not something I have seen but sounds like an issue that could affect plenty of people. It may be some something to do with the video subsystem on the Pi or an issue with Janus, so it would be worth contacting either/both of these communities with suitable amounts of debug information to see if they can help. It would be interesting to see/hear if this has been replicated by other people, or if the same thing happens with a different LAN host / setup.

0 Votes
JohnRMenard

November 28, 2015 11:16

I followed your instructions.

I had to install GStreamer from this link http://www.onepitwopi.com/raspberry-pi/ ... pberry-pi/ though.

I ran your gstreamer command line by cutting and pasting it.

I then ran the Janus command line. The output looked exactly like yours apart from the last line "[gst-rpwc] New video stream..." (which was missing):

JANUS EchoTest plugin initialized!
Loading plugin 'libjanus_streaming.so'...
EchoTest watchdog started
JANUS Streaming plugin initialized!
Streaming watchdog started
Transpor plugins folder: /opt/janus/lib/janus/transports
Loading transport plugin 'libjanus_http.so'...
HTTP webserver started (port 8088, /janus path listener)...
[WARN] HTTPS webserver disabled
[WARN] Admin/monitor HTTP webserver disabled
[WARN] Admin/monitor HTTPS webserver disabled
JANUS REST (HTTP/HTTPS) transport plugin initialized!
HTTP/Janus sessions watchdog started
Sessions watchdog started


I think that I started gstreamer correctly. The output was:

raspivid --verbose --nopreview -hf -vf --width 640 --height 480 --framerate 15 --bitrate 1000000 --profile baseline --timeout 0 -o - | gst-launch-1.0 -v fdsrc ! h264parse ! rtph264pay config-interval=1 pt=96 ! udpsink host=127.0.0.1 port=8004
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
/GstPipeline:pipeline0/GstH264Parse:h264parse0.GstPad:src: caps = "video/x-h264\,\ width\=\(int\)640\,\ height\=\(int\)480\,\ framerate\=\(fraction\)0/1\,\ parsed\=\(boolean\)true\,\ stream-format\=\(string\)avc\,\ alignment\=\(string\)au\,\ level\=\(string\)4\,\ profile\=\(string\)baseline\,\ codec_data\=\(buffer\)01428028ffe1000d2742802895a0280f680789135001000528ce025c80"
/GstPipeline:pipeline0/GstRtpH264Pay:rtph264pay0.GstPad:src: caps = "application/x-rtp\,\ media\=\(string\)video\,\ clock-rate\=\(int\)90000\,\ encoding-name\=\(string\)H264\,\ sprop-parameter-sets\=\(string\)\"J0KAKJWgKA9oB4kTUA\\\=\\\=\\\,KM4CXIA\\\=\"\,\ payload\=\(int\)96\,\ ssrc\=\(uint\)4183066236\,\ timestamp-offset\=\(uint\)1221893287\,\ seqnum-offset\=\(uint\)18618"
/GstPipeline:pipeline0/GstUDPSink:udpsink0.GstPad:sink: caps = "application/x-rtp\,\ media\=\(string\)video\,\ clock-rate\=\(int\)90000\,\ encoding-name\=\(string\)H264\,\ sprop-parameter-sets\=\(string\)\"J0KAKJWgKA9oB4kTUA\\\=\\\=\\\,KM4CXIA\\\=\"\,\ payload\=\(int\)96\,\ ssrc\=\(uint\)4183066236\,\ timestamp-offset\=\(uint\)1221893287\,\ seqnum-offset\=\(uint\)18618"
/GstPipeline:pipeline0/GstRtpH264Pay:rtph264pay0.GstPad:sink: caps = "video/x-h264\,\ width\=\(int\)640\,\ height\=\(int\)480\,\ framerate\=\(fraction\)0/1\,\ parsed\=\(boolean\)true\,\ stream-format\=\(string\)avc\,\ alignment\=\(string\)au\,\ level\=\(string\)4\,\ profile\=\(string\)baseline\,\ codec_data\=\(buffer\)01428028ffe1000d2742802895a0280f680789135001000528ce025c80"
/GstPipeline:pipeline0/GstRtpH264Pay:rtph264pay0: timestamp = 1221893287
/GstPipeline:pipeline0/GstRtpH264Pay:rtph264pay0: seqnum = 18618
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock

0 Votes
gilles13

November 20, 2015 18:06

Hello,

I have just installed janus and nginx on my raspberry pi 2 as per you instructions and got it working without problem on my LAN, which by the way is hosted on the Pi.
I am now able to broadcast whatever my raspicam is capturing to several opened browser windows, with minimal lag. These are the good news !!!
I am experiencing 2 issues:

1- I cannot get it to work on Chrome, just on Firefox. I have installed the nanoStream Live Encoder to play H264 video on chrome and this allows me to stream video from the raspicam to chrome using UV4Lwebrtc. I wonder why the stream from janus is not recognized.

2- The video stream tends to freeze, whenever the raspicam moves too much (or the subject it's filming). This happens at any window size (on both sender and receiver sides), at any bitrate (I tried 1000000 to 5000000), the number of clients does not change things either. The LAN is wifi but the bandwidth is very large. I know it should not freeze, because the same stream with UV4Lwebrtc on the same LAN does not freeze at all.

I am just hoping you would have an idea as to how the latter issue can be addressed.
Thanks for the great work anyway.

0 Votes
Hasanga

November 12, 2015 18:17

@vandan1,
If you can't load the streamingtest.html page but get the nignx welcome page instead, then do the folliwing to change the nignx default public folder -

sudo nano /etc/nginx/sites-enabled/default

then change the root folder from -

location / {
root /var/www/nginx-default;

to the following folder -

location / {
root /usr/share/nginx/www/;

0 Votes
Andrew Back

October 7, 2015 09:20

vandan1 wrote:
> I have followed all the steps, there is no error at any step. After i type my ip
> address in the web browser , it simply says "welcome to nginx". Please help me out..
>
> Im using a raspberry pi 2.

Sounds like you missed the step out:

"Now copy the Janus HTML content to the Nginx server root:

$ sudo cp -r /opt/janus/share/janus/demos/ /usr/share/nginx/www/"

If the Janus content is in place it should get served up. Or else perhaps you're not using the full URL:

http:///streamingtest.html

0 Votes
vandan1

October 7, 2015 06:37

I have followed all the steps, there is no error at any step. After i type my ip address in the web browser , it simply says "welcome to nginx". Please help me out..

Im using a raspberry pi 2.

0 Votes
jlauer12

April 6, 2015 15:05

I just got WebRTC working on my Pi 2 and dishing video up to Chrome using the link below. I could not get Chrome to work using Janus and Gstreamer. Apparently uv4l just added this capability on March 22nd, 2015 so about 14 days ago which means it's an alternate to Gstreamer and Janus now.

http://www.linux-projects.org/modules/s ... e&artid=14

0 Votes
redfox74

April 2, 2015 08:05

Is possible to have an image of your sd card for test it ?
What revision of OS are you using ?
best
Roberto

0 Votes
redfox74

April 2, 2015 07:28

I follow the tutorial but streaming don't work .
WebRTC error... "Failed to set remote offer sdp: Session error code: ERROR_CONTENT. Session error description: Failed to set video send codecs.."

All work on raspberry camera and streaming infact if i use gstreamer client udp on an other pc i recive the video on the screen ...
I'm using Googe Chrome as web browser on my pc.
best
Roberto

0 Votes
Stupiduser

March 27, 2015 06:05

I get hung up at the GStreamer1.0 install. Says no such file exists. Gives me many other files that contain GStreamer. I tried to find another build that included the needed file but no luck.

0 Votes
Glenn Holt

March 17, 2015 01:25

Is the extra horsepower of the Pi2 needed for the video transcoding, or will this work with a PiB?

0 Votes
jlauer12

March 16, 2015 15:24

I got this to work, so thank you. I've been looking for a Raspberry Pi WebRTC solution for about 6 months and this is the first time I've ever seen it work for the RaspiCam and from the command line. It does work from Ice Weasel, but you have to be in X windows.

The problem with this solution is its streaming H264 which Chrome does not support in WebRTC yet. Having this only work in Firefox isn't that useful as most of the web is using Chrome. So, how do you convert the stream using Gstreamer to VP8 so that Chrome browsers can also view this live video feed?

Here's an alternate Gstreamer command I modified from a stack overflow at http://stackoverflow.com/questions/2730 ... 264-to-vp8, but I couldn't get it to work either:

raspivid --verbose --nopreview -hf -vf --width 640 --height 480 --framerate 15 --bitrate 1000000 --profile baseline --timeout 0 -o - | gst-launch-1.0 -v fdsrc ! "application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, sprop-parameter-sets=(string)\"Z2QAKK2EBUViuKxUdCAqKxXFYqOhAVFYrisVHQgKisVxWKjoQFRWK4rFR0ICorFcVio6ECSFITk8nyfk/k/J8nm5s00IEkKQnJ5Pk/J/J+T5PNzZprQFAeyA\,aO48sA\=\=\", payload=(int)96, ssrc=(guint)2498431066, clock-base=(guint)297251943, seqnum-base=(guint)34949" \
! rtph264depay ! queue ! ffdec_h264 ! ffmpegcolorspace ! videoscale ! queue \
! vp8enc bitrate=256000 speed=2 max-latency=1 error-resilient=true \
! rtpvp8pay ! udpsink host=127.0.0.1 port=8005

Here's the version of Gstreamer I'm using from compiling it myself:
gst-launch-1.0 version 1.4.5
GStreamer 1.4.5
http://www.linuxfromscratch.org/blfs/view/svn/

0 Votes
fatjoni

March 16, 2015 12:51

Sir please can you let me know how can i change this code in order to make it work with a stun server? I dont have a public ip so i want to find a getaround way to stream trhough my raspberry.
I need native code streaming from raspberry via a stun server in order to be accessed from webbrowsers.
Thank you very much in advance