Skip to content

Videostream

MarkusSchmitz edited this page Jun 4, 2016 · 39 revisions

Streaming solutions overview

This page shows all the possible streaming solutions that were tested, as well as issues and statistics concerning these solutions.

name multiple observer possible problem
vlc probably needs extern software -> not in browser and not mobile
flash yes requires flash plugin -> not in mobile and depricated
jpeg no high bandwidth required
hlc yes not working with desktop browsers
uv4l yes and no There is the possibility to add more observers but the problem is the video delay is getting greater with every new observer

After all research we found out that the uv4l solution fitts best for our purposes. To set it up please find at our wiki the installing and running video stream site.


Browser-based solutions

MPEG Streaming with jsmpeg

Start Video Streaming

To start the streaming 'openstream.sh' need to be executed.

Stream Properties

Resolution: 640 x 480 Frames per Second: 24
Codec: Mpeg1
Accessible via Port: 8082

Media Player based solutions

Steaming via netcat and mplayer

Creating a peer-to-peer stream from the pi's camera to a target pc.
The delay of the camera stream was less than 1 second.
But the problem with this solution is that it's only possible to stream at exactly one pc.

On the pi:

sudo apt-get install netcat
raspivid -t 0 -o - | nc 192.168.178.20 5001

On the target pc:

sudo apt-get install mplayer netcat
nc -l -p 5001 | mplayer -fps 90 -cache 1024 -

Streaming video via VLC player

Another idea was to stream the video with vlc using RTSP.
This way didn't work either because there was a minimum delay of about 3 while playing around with different parameters.

Start the RTSP stream with vlc

raspivid -o - -t 0 -n | cvlc -vvv stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8554/}' :demux=h264

Streaming with the ffmpeg library

We also tried to create an flv or mp4 stream using the ffmpeg library as mplayer does.
But we didn't get it to work properly.
We still trying to figure out how mplayer does the encoding in time. A video can be captured from the camera to the harddrive with the following command (after having installed ffmpeg successfully) raspivid -t 0 -w 960 -h 540 -fps 25 -b 500000 -o - | ffmpeg -i - -vcodec copy myVideo.mp4

Streaming with the RPi-Cam-Web-Interface

http://elinux.org/RPi-Cam-Web-Interface#RaspiMJPEG

This project also uses MJPEG, so it transfers pictures insteas of a video stream. It works quite well on the desktop-pc, but on the mobile phone the stream isn't too fluid. Another problem with this one is, that there is no license included in the project folder.

Streaming with Icecast

https://www.tmplab.org/wiki/index.php/Streaming_Video_With_RaspberryPi

Needs a server, so no solution for our purpose (Raspberry itself is too slow), also not Html5 compatible

Streaming with Flask

http://videos.cctvcamerapros.com/raspberry-pi/how-to-setup-video-streaming-server.html

http://blog.miguelgrinberg.com/post/video-streaming-with-flask

Gives an image-stream, delay is okay. But as always, no multi-client scenario possible. Very lightweight solution, however might cause problems on mobile devices due to huge amount of data.

Streaming via RTSP-Server

https://github.com/mpromonet/h264_v4l2_rtspserver

Streams over RTSP, I can open it in VLC-Player, until now I only tried unicast.

Commands to install (you need to grab cmake first):

sudo modprobe -v bcm2835-v4l2

sudo apt-get install liblivemedia-dev liblog4cpp5-dev

git clone https://github.com/mpromonet/h264_v4l2_rtspserver.git

cd h264_v4l2_rtspserver

cmake .

make install

h264_v4l2_rtspserver -H <height> -W <width> -F <fps>

I chose the following parameters, the 15 frames per second still delivered a smooth image: h264_v4l2_rtspserver -H 480 -W 640 -F 15

After restarting the Pi, you need to execute sudo modprobe -v bcm2835-v4l2 again before starting the server.

Access the stream from VLC-media-player: Open VLC, press Ctrl + N. Now enter the adress the server printed out on start, should be something like: rtsp://192.168.0.8:8554/unicast Important: Tick the little checkbox on the bottom to get the advanced options. There put the caching value to 0 ms. This way your delay will be smaller.

Streaming Video with ffmpeg and crtmpserver

Setup

To setup the streaming with ffmpeg and crtmpserver you have to follow this manual to step 10. This manual explains how to setup and install ffmpeg and crtmpserver. To view the stream later you have also to install nginx and use the video.js player to show the stream in a html page.

Starting the live stream

If the setup is done as described in the manual you could start the stream with the shell script which was created at the manual or with the following command:

raspivid -t 0 -w 960 -h 540 -fps 25 -b 500000 -o - | ffmpeg -i - -vcodec copy -an -f flv -metadata streamName=myStream tcp://0.0.0.0:6666

This command starts the video stream and crtmpserver will grap the flash stream which is created by ffmpeg and send it to port 6666 as configured before in crtmpserver config.

Accessing th RTMP stream

It is possible to access the live stream in multiple ways. For instance you could use the vlc player or you could use ffplay from ffmpeg:

    ffplay -an "rtmp://<IP-ADDRESS/HOSTNAME OF PI>/flvplayback/myStream live=1"

Using Video.js player to view the stream on an html page

In the last step you could create a new html page on your running webserver, for example in nginx. Here are the content of the file I created to view the stream:

 <!DOCTYPE html>
  <head>
    <link href="http://vjs.zencdn.net/5.9.2/video-js.css" rel="stylesheet">

  </head>
  
  <body>
    <video id="my-video" class="video-js" controls preload="auto" width="640" height="264" data-setup="{}">
      <source src="rtmp://<IP-ADDRESS/HOSTNAME OF PI>/flvplayback/myStream" type='rtmp/flv'>
      <p class="vjs-no-js">
        To view this video please enable JavaScript, and consider upgrading to a web browser that
        <a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
      </p>
    </video>
  
    <script src="http://vjs.zencdn.net/5.9.2/video.js"></script>
  </body>
 </html>

If you now open the webpage in your browser you should be able to see the pi's video stream with a delay of about 1.5 seconds.

Conclusion

The big problem with this solution is that we are using an flv flash stream. This method is working for almost all webbrowsers which are supporting flash video. But as you might know flash videos are not playable on mobile devices.

Streaming Video with gstreamer and nginx

We've tried ffmpeg, vlc, raspivid, nc, uv4l, crtmpserver ... might as well try gstreamer too! Gstreamer provides hardware accelerated video encoding on the Pi (via OpenMAX).

Setup

First, install gstreamer-1.0 from the Raspbian repositories. Be sure to install gstreamer 1.0, not 0.10 as the latter version does not provide hardware acceleration.

If you have nginx already installed, you have to remove it before installing it from source code:

sudo apt-get remove nginx nginx-common
sudo apt-get purge nginx nginx-common
sudo apt-get autoremove

Next, we need to install nginx with the rtmp-server add-on. Unfortunately, the packaged version of nginx in the Raspbian repositories does not come with the add-on. So we need to compile it manually. For this step, please refer to the official manuals for nginx-rmtp.

To access the camera as /dev/video0 you also have to run this command:

sudo modprobe bcm2835-v4l2

Configuration

After make && sudo make installing nginx, I used this config file /etc/nginx/nginx.conf.

Start nginx. It should now be listening for a video transmission from localhost on port 1935. It is possible that port 1935 is already in use for another service at your device. So you have to choose another available port. Be aware that you have to replace the port in the nginx.conf and in the command below. To provide the video stream we can use the following video pipeline:

gst-launch-1.0 v4l2src device=/dev/video0 ! "video/x-raw,format=I420,width=640,height=480,framerate=30/1" ! decodebin ! queue ! videoconvert ! omxh264enc ! "video/x-h264,stream-format=byte-stream,profile=baseline,low-latency=true,control-rate=variable,target-bitrate=5000000" ! h264parse ! flvmux streamable=true name=mux ! rtmpsink location="rtmp://localhost:1935/example/live live=1"

Note the use of the encoder omxh264enc for hardware acceleration.

Accessing the RTMP stream

I manage to view the stream in VLC by opening rtmp://<raspberrypi-hostname>/example/live. Unfortunately I experienced a delay of approximately 6 seconds.

Using DASH (theoretical approach)

If you read the nginx configuration above, you should notice that nginx is set up to provide DASH video. DASH allows live streaming to HTML5 enabled browsers that run a Javascript application.

I set up an example HTML file that utilizes the Dash.js project:

<!DOCTYPE html5>
<script src="http://cdn.dashjs.org/latest/dash.all.min.js"></script>
<style>
    video {
       width: 640px;
       height: 360px;
    }
</style>
<body>
   <div>
       <video data-dashjs-player autoplay src="http://raspberrypi2.local/dash/live.mpd" controls></video>
   </div>
</body>

This is where our luck is over. The file /dash/live.mpd exists and contains stream information (you can investigate it using curl). However, Dash.js cannot play any video 😢

Using Video.js player to view the rtmp/mp4 stream on an html page

The gstreamer solution is also working within the video.js player. You could use the html webside from the ffmpeg and crtmpserver solution. The only change you have to make is the video type (rtmp/mp4) and the source url.

Conclusion

This approach has the same problems as streaming via ffmpeg and crtmpserver. It doesn't work on the mobile devices.

Streaming video with HLS

After only getting desktop pc's streaming solutions to work we tried another solution which supports mobile devices web browsers.

Setup

First you have to build and install ffmpeg from source code like the ffmpeg and crtmpserver solution. If you already installed ffmpeg over the raspbian repository you have to remove it.

cd /usr/src
git clone git://source.ffmpeg.org/ffmpeg.git

cd ffmpeg
./configure
make && make install

The next step is to install the webserver of your choice. We for instance used nginx.

Starting the video stream

Whit the following command the video stream is started:

raspivid -n -w 720 -h 405 -fps 25 -vf -t 86400000 -b 1800000 -ih -o - | ffmpeg -y -i - -c:v copy -map 0:0 -f ssegment -segment_time 4 -segment_format mpegts -segment_list ./stream.m3u8 -segment_list_size 720 -segment_list_flags live -segment_list_type m3u8 "%08d.ts"

This approach is creating segments of the live stream with a specific time set by the -segment_time tag and a .m3u8 stream file where the segments are listed. Be aware that you have to remove the segments *.ts and the *.m3u8 files after your video stream session.

Embedding the .m3u8 playlist in a webpage

To view the stream we created a simple html page:

<html>
    <head>
        <title>PiVid</title>
    </head>
    <body>
        <video controls width="1280" height="720" >
            <source src="stream.m3u8" type="application/x-mpegURL" />
        </video>
    </body>
</html>

Conclusion

This solution was tested with an iPhone and an iPad and was showing the live stream in the browser. The disavantages of this solution are that the video stream has a minimum delay of 6 seconds and doesn't work with Firefox and Google Chrome on Ubuntu.

Streaming video with UV4L MMAL

This approach is streaming with the MJPEG library and is using the raspberry pi's camera driver to access the image information.

Setup

First you have to install the camera driver and some other additional packages:

curl http://www.linux-projects.org/listing/uv4l_repo/lrkey.asc | sudo apt-key add -

Add the following line to the file /etc/apt/sources.list
// deb http://www.linux-projects.org/listing/uv4l_repo/raspbian/ wheezy main

sudo apt-get update
sudo apt-get install uv4l uv4l-raspicam

sudo apt-get install uv4l-raspicam-extras

sudo apt-get install uv41-webrtc

After installing the packages you have to configure the uv4l-raspicam settings at /etc/uv4l/uv4l-raspicam.conf. Please search the following keys and edit them in the file:

server-option = --max-streams=15

encoding = mjpeg
width = 800
height = 600
framerate = 25

If you like to you could also use your customized encoding, width, height and framerate but you have to edit the server-option max streams because the default value is limited to 3 clients.

After you applied your settings you have to restart the uv4l-raspicam service:

sudo service uv4l_raspicam restart

Accessing the video stream

If the setup is done you can access the stream by visiting <IP-Address of your Pi>:8080/stream. Now youl should see the MJPEG stream in your browser.

Embbeding the MJPEG image inside a webpage

For embdding the "video stream" we used the follwing html webpage:

<!DOCTYPE HTML>
<head>
	<title>Pi Live Stream</title>
</head>
<body>
	<img src="<IP-Address of your Pi>:8080/stream/video.jpeg" style="width: 800px; height: 600px;" />
</body>

Conclusion

This solution is working on desktop pc's as well as on mobile devices. The problem with this solution is that the delay increases with more connected clients.

Hybrid solution with uv4l and gstreamer

We tried to make a hybrid solution with the purpose to spilt the desktop browser and the mobile browser traffic. The idea was to use the above described uv4l solution as a poster in the html video tag and show it if the browser couldn't open the rtmp/mp4 stream. To get this solution to work we tried to install v4l2loopback so we could access the camera output multiple times. The problem with the solution was that we were not able to build the v4l2loopback because there were no linux headers for the current raspian jessie available. Therefore we tried to build the current linux headers from source and we also tried to downgrade the kernel version but this also didn't solve our problem.

Clone this wiki locally