So I got the Raspberry Camera today and got stills working fine.

Capture an image in JPEG format:

raspistill -o image.jpg

Capture a 5-second video in H.264 format:

raspivid -o video.h264

I do not want to install any extra application as I want to leverage HTML5 that is readily available. Since Chrome/Safari has built-in decoders for H.264 I just want to point my browser to the URL and watch the stream.

How can I achieve this?

  • 1
    I'm working on this, too. I think you need to add MP4 support to nginx or something like that. Will let you know if I have a breakthrough. – recantha May 16 '13 at 5:23
  • @recantha Have you had any new breakthroughs with streaming video? – ppumkin Oct 24 '14 at 9:39
  • 2
    The best solution I've found is based on Silvan Melchoir's RaspiMJPEG. Take a look at my blog which contains a link to the Raspberry Pi Foundation's forum that explains everything. (recantha.co.uk/blog/?p=11176) – recantha Nov 1 '14 at 7:21
  • 1
    Yea that looks awesome to be able to stream to various devices. What FPS and lag do you get?? I did manage to get uv4l to work with VLC pretty well and OSD. A very short and bad demo. Will make a better one soon. Was made late at night after hours of trial and error. youtu.be/LO10Ytlauag – ppumkin Nov 1 '14 at 10:58
  • @ppumkin how can I record through a python script while RaspiMJPEG is running?It gives a start recording video but it records in .h264 format how can make a python script run on pressing start_recording? – Coderaemon May 28 '15 at 11:56

Streaming with HLS

Apple's proprietary method of streaming live video. It is called HTTP Live Streaming (HLS) and is only supported by Apple's technology. Google (Chromium / YouTube) uses its own implementation called dash mpeg and everybody else is either confused or using H.264 encapsulated in MP4.

PROS

  • Can stream HD 1080p on LAN to any device that supports .m3u8 playlists
  • Uses HTML5 semantics (but it is not standardised format)
  • Some support in third-party premium software like jwplayer 6 can be used

CONS

  • Has a delay of at least 5 seconds (in this application, but using mirroring from iPhone to AppleTv they achieve 50 ms - 500 ms somehow). So it's not good for remote controlled applications where instant reactions are required, ie robots or helicopters.
  • Have to pay for third-party software if you want to broader browser support which may flash.

m3u8

  • .m3u8 is simply a UTF-8 version of the M3U format. (.m3u files can have various encodings.) Some people claim that renaming a .m3u8 to .m3u will work as expected on all HTML5 browsers. I tried this, and it did not work for me.

The concept behind this streaming is that short segments of files, at least 5 seconds long (in this example - it possible new ways are available to speed it up) are recorded and saved to a proper file. The playlist file is updated with the new file name and the client always polls this playlist and downloads the most recent file. There are some mechanics involved to merge the video seamlessly on the client. This is why other developers do not want to implement this because it requires a a lot of effort and does not comply with HTML5 standards (even though there is no proper HTML5 standard for live streams?? Ehh, sigh).

Installing

You need to compile ffmpeg - do not use apt-get installfor FFmpeg

This can take up to 5 hours - It has to be version 1.1 or higher which supports segment streaming. You can use this to clone it and compile it.

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

cd ffmpeg
./configure
make && make install
  • Install nginx (engine-x) - nginx was specially designed for embedded devises and is the lightest and fastest PHP-enabled web server available at the moment. (Yes, it is better than bulky Apache)
  • Create a directory, for example, live in your www folder, /usr/share/nginx/www/

Make a Bash script file called something like video.sh, apply chmod +x to it and put paste this in. Change the base folder to where ever your HTTP server lives. I used nginx, /usr/share/nginx/www/

#!/bin/bash

base="/data/live"

cd $base

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 "$base/stream.m3u8" \
    -segment_list_size 720 \
    -segment_list_flags live \
    -segment_list_type m3u8 \
    "segments/%08d.ts"


trap "rm stream.m3u8 segments/*.ts" EXIT

# vim:ts=2:sw=2:sts=2:et:ft=sh

Create a HTML file that will load the playlist

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

Support

  • iPhone, opens page, but drops into QuickTime. The quality is really amazing!
  • Windows Safari, streams fine.
  • Macintosh or Windows, QuickTime. Streams fine.
  • Android 2.3.5 and did not work, but it was supposed to be supported since 2.1.x
  • Windows, Chrome - Nothing
  • Windows, Internet Explorer 10 --- Nothing (unsupported video type)
  • Windows, VLC media player - Nothing

Reference: http://www.raspberrypi.org/phpBB3/viewtopic.php?p=351392&sid=5b9a46f5eea2c7a0887d2efdfa7edade#p351392

Original code: https://github.com/AndyA/psips/blob/master/examples/hls.sh

  • In regards to speeding up ffmpeg's compilation In order to circumvent the low computational capacity of RPI and long compiling times for ffmpeg, I've attempted using Qemu with the Wheeze but came across some obstacle in logging in, and had to try with an Arch image. This worked. Also attempted Sqeeze on a Ubuntu image, through VirtualBo – luboP Jun 10 '13 at 20:02
  • 1
    Is there a way to automatically delete old segments? The SD card gets full after some time. I would also like them to be deleted to I can run this on a tmpfs and not ruin the SD card. – Dimme Oct 28 '13 at 16:10
  • 1
    @Dimmme If you add -segment_wrap 10 as an argument to ffmpeg it will use max 10 segment files. – gregers May 9 '14 at 17:36
  • Have anyone gotten this to work? The files are created, but seem to miss SPS/PPS info, so the video won't play in iOS Safari nor VLC. The stream.m3u8 also didn't include segments/ when pointing to the segment-files, so I dropped the segments folder. Did I misunderstand something? – gregers May 9 '14 at 17:56
  • you need to pipe the stream through the PSIPS filter binary. The newest version of raspicam was supposed to do this.. but for some reason I couldnt get it working without PSIPS – ppumkin May 9 '14 at 18:14

UV4L MMAL

Thanks to comment from @mpromonet for the update on the Linux-Projects V4L2 driver that now implements MMAL very efficiently - but it is still a work in progress.

Follow these instructions to install the linux-project repository and install the UV4L driver with extras. Then install the server and mjpeg. If you want, you can experiment with the others too.

After you install everything, you can access the HTTP server on port 8080. You should also check the /etc/uv4l/conf file and set if you want mjpeg or H.264 as it makes a difference, but you can adjust a few settings via the built-in web server.

HTML 5

This is what we were all waiting for (called WebRTC) and thanks to the new driver it works great (on a Raspberry Pi 2).

First, follow these steps, http://www.linux-projects.org/modules/sections/index.php?op=viewarticle&artid=14:

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

Then on your Raspberry Pi 2 install this the WebRTC (for a Raspberry Pi 1, read the linked site for other options)

sudo apt-get install uv4l-webrtc

Restart all the drivers and go to

http://raspberry:8080/

You now have low-latency, high-quality video streaming direct into a modern browser like Chrome or Firefox. (Maybe Safari, but I can't check because they don't do Winblows any more and Internet Explorer... eh)

MJPEG

By default, it uses mjpeg at 1080p, and it's very sluggish. I tweaked it to 800x600 framesize and using something like iSpy to process video. For security, I get about 10 fps on a crisp video. It is way better than the 3 fps at 640x480 before this driver. It works on iPhone with Safari, Android Chrome and almost everything else.

http://raspberrypi:8080/stream/video.mjpeg

This also means that motion should (I still need to test and compare) work a lot better now. Make sure to set the configuration to use v4l2_palette 8 or v4l2_palette 2

H.264

This has now been fixed for "streaming", and we don't have to go to great lengths to watch H.264 video through VLC media player. The stream is sill RAW H.264, so you need to demux it or transcode/ encapsualte if you need it to work somewhere else. You should tweak the bitrate=xxxxxx in the configuration file if you are streaming over Wi-Fi.

In VLC media player, you must tell it that you want to use the H.264 demuxer. So if you're using the GUI, then make sure to add the argument :demux=264. From command line, vlc http.../video.h264 --demux h264. Otherwise, you will just see a blank screen even though the camera LED is turned on.

http://raspberrypi:8080/stream/video.h264

Viola! HD streaming with roughly 500 ms lag (with tweaking, down to 200 ms). It is definitely much easier than using the old methods. Quality and FPS is superb, but you can't embed this in HTML5 without transcodding to MP4 or WebM. I hope this will be implemented as it will truly make this a great standalone server.

RTSP / RTMP / RTP

Not supported / implemented

http://www.linux-projects.org/uv4l/tutorials/rtsp-server/

HLS

Not supported / implemented


There is no video4linux driver availabe yet. This means that we can't use ffserver to stream data using /dev/video0 or simlar like a USB webcam.

That is why it is so difficult to find proper live streaming for HTML5 browsers.

  • Now there is video4linux driver the official V4L2 driver bcm2835-v4l2 and the userspace V4L2 driver [linux-projects.org/modules/sections/… – mpromonet Oct 11 '14 at 22:35
  • Is a real v4l driver or is it just that wrapper around raspivid that gives terrible performance? – ppumkin Oct 12 '14 at 21:17
  • 1
    The official driver use the MMAL interface, see source code [github.com/raspberrypi/linux/blob/rpi-3.12.y/drivers/media/…. Performance seems correct. – mpromonet Oct 19 '14 at 20:17
  • I have been playing with this for 3 days now. The mjpeg encodding is definalty much more stable and can view 800x600@10fps on iPhone,Android or iSpy, reliably. h264 is great at 1080p 30fps and we can view this in vlc using the --demux h264 flag. We still need to transcode this for use on mobile or embedding as mp4/webm on webpages. But it is really great move forward in efficiently and quality. Dont confuse with the "other" UV4L non linux-project driver thing that is rubbish. – ppumkin Oct 24 '14 at 7:50
  • Note that adding :demux=264 in the H264 method is for vlc server, not the vlc client. So the command line to start the streaming on the raspberry to get compatibilty with vlc in smartphones is: /usr/bin/cvlc v4l2:///dev/video0 --v4l2-width 800 --v4l2-height 400 --v4l2-chroma h264 --sout '#standard{access=http,mux=ts,dst=0.0.0.0:8080}' :demux=264 – Jaime M. May 7 '15 at 19:56

Streaming with MJPEG

U4VL

A kernel interface with a build in HTTP(S) server.

http://www.linux-projects.org/uv4l/tutorials/streaming-server/

Raspberry Pi Cam Web interface

A nice project by silvanmelchior that deploys a web server, dvr like, multi target streaming server. Needs more information

https://github.com/silvanmelchior/RPi_Cam_Web_Interface

Legacy method

Streaming with mjpg is supported by almost all browsers, including Internet Explorer 6. A lot of cameras used before H.264 used hardware mjpg, which essentially dumped JPEG files as fast as possible into a folder while mjpg read the file into a buffer and deleted them. Some devices could achieve up to 25 fps and even if you had a bad connection you would get at least 1 fps.

Support for mjpg was dropped in HD cameras because the JPEG file just got too large to stream over the Internet and H.264 is a much faster and better quality protocol.

Since we have no way to broadcast H.264 using the camera module nativly this seems like a viable fallback...

It is pretty much instant, but don't expect to get more than 1.5 fps. This is down to raspistill being extremely SLOOOW! Using the time-lapse function set to 100 ms which should give us 10 fps does not work because raspistill just chokes up and has serious performance issues within itself.

  1. Change /tmp to use RAM for speed /etc/default/tmpfs - change RAMTMP=yes (This is an effort to increase fps, but raspistill just cannot keep with its self.)
  2. Reboot
  3. apt-get install git
  4. apt-get install libjpeg8-dev
  5. apt-get install libv4l-dev
  6. apt-get install imagemagick
  7. cd /usr/src, mkdir mjpg-streamer, cd mjpg-streamer ...
  8. git clone https://github.com/engine12/mjpg-streamer.git
  9. make USE_LIBV4L2=true clean all
  10. OPTIONAL If you have errors
  11. sudo ln -s /usr/include/libv4l1-videodev.h /usr/include/linux/videodev.h
  12. sudo ln -s /usr/include/lib4l2.h /usr/include/linux/lib4l2.h
  13. Inside the makefile, comment out all the plugins except for input_file and output_http and do make again. I had a lot of issues here.
  14. Copy the binary, mjpg_streamer and its plugins input_*.so and output_*.so to /usr/local/bin. Otherwise, run it direct from the src directory.
  15. Optional end
  16. mkdir /tmp/stream
  17. raspistill -w 640 -h 480 -q 5 -o /tmp/stream/pic.jpg -tl 100 -t 9999999 -th 0:0:0 &
  18. LD_LIBRARY_PATH=./ ./mjpg_streamer -i "input_file.so -f /tmp/stream" -o "output_http.so -w ./www" (run this where the binary and plugins are)
  19. Goto http://<IP-address>:8080
  20. Here are a few option, enjoy "live" streaming the old fashioned way ... supported by most browsers - modern, old and experimental.

I struggled to compile it for about for 5 hours... sigh, but I think I will use this as I can access the stream from any phone and any browser. I just have to wait till we get better drivers... Another year or two. :(

No matter what quality I try, I get no faster or no slower than 1 fps using stream. I used 720p and 1080p and only image quality gets better, but fps is no difference on LAN. I suppose smaller settings will help with WAN/3G or other radio transmissions.

raspistill writes the image to a single file. This could be a bottleneck. It writes the file, mjpg strreamer reads it and deletes it causing a blocking I/O, so raspistill cannot write to the file.

The only thing I can think of is using raspivid piped into FFmpeg that will create JPEG files for us - I need to try this and possibly it's much faster than usign raspistill. I managed to get 25 fps at a shocking quality, and it was delayed about 10 seconds... Tweaking the settings got me about 3 fps, but 100% CPU. No hardware is being used to process the video stream...

raspivid -w 640 -h 480 -fps 25 -vf -t 86400000 -b 1800000 -o -  \
ffmpeg -i - \
    -f image2(?) \
    -c:v mjpeg \
    stream%d.jpg

I was also reading and found that we can use %d in the raspistill output file name. I wonder if that will boost the fps. Also JPG encoding is hardware accelerated in raspistill, so I am really struggling to figure out why it's so slow...

I got a staggering 2 FPS using %d in the filename. For some reason, writing the JPEG file is horribly slow from raspistill. Sigh.

As of 2017 (or perhaps earlier) raspivid is no longer the preferred method, with the Pi devs recommending people use V4L2 instead.

So this method allows you to stream H264 via RTP using V4L2 instead of raspivid. I noticed this method results in fewer dropouts and allows a higher bitrate:

#!/bin/sh

# Use V4L2 (preferred) instead of raspivid
# exposure_dynamic_framerate=1 (raspivid --fps 0) - reduce framerate/increase exposure in low light
# scene_mode=8 (raspivid --exposure night) - allow framerate reduction to increase exposure
v4l2-ctl -v width=1296,height=972,pixelformat=H264 \
        --set-ctrl=exposure_dynamic_framerate=1 \
        --set-ctrl=video_bitrate=5000000 \
        --set-ctrl=scene_mode=8

exec ffmpeg -f h264 -probesize 32 -r 30 -i /dev/video0 -vcodec copy -an -f rtp_mpegts udp://224.0.1.2:5004

This script multicasts the video, and it can be viewed on another machine on the LAN with a command like this:

ffplay -sync ext -an -fast -framedrop -probesize 32 -window_title "Raspberry Pi" -an udp://224.0.1.2:5004

-sync ext causes the video to be played as fast as possible so it will run in real time, as opposed to running it at a fixed framerate and lagging if the Pi is capturing frames faster than this. There's still some lag with this method, but no worse than the other raspivid methods.

(Tip: if you're plugged into a router or switch that supports IGMP, make sure 224.0.0.0/4 is not firewalled on your machine, otherwise when the router asks your PC whether it wants any multicast traffic the PC will never respond and you'll never see any video.)

Recording to disk

As I mentioned recording in the comments below, I'll expand on that here. You can use a command like this to record the network stream to disk:

ffmpeg -y -i udp://224.0.1.2:5004 -c copy \
  -f segment -segment_atclocktime 1 -segment_time 900 \
  -reset_timestamps 1
  -strftime 1 /path/to/storage/pi-%wT%H%M.mkv

Look at man strftime for the meanings of the % symbols in the filename. The ones in this example use the day number (0=Sunday, 1=Monday, etc.) followed by a T and then the time. It starts a new file every 15 minutes.

Just to be clear, this recording command is meant to be run on a remote PC (not on the Pi itself) although it will probably work on the Pi too (untested).

Since you get a new file every 15 minutes with the day and time in the filename, it means that after one week you'll start to get filenames generated that have already been used, causing the oldest files to get overwritten. In other words, you'll end up with a rolling loop of the previous week's worth of footage. This is ideal for a security camera where you will rarely need to go back more than a week.

As a side note this produces about 500GB worth of files, so you may want to adjust the bitrate, resolution, or overwrite the files sooner (say every 24 hours) if you don't want them taking up so much space.

  • Cool - Thanks for sharing this. Can you explain why the use of multicast is necessary here though? From what I have learnt is that multicast is rarely used - so I was wondering what it brings to the table here? Still - The script looks great and I am sure it will help allot of people. Thanks +1 – ppumkin Mar 20 '17 at 12:31
  • 1
    Multicast is optional - you can just substitute a normal IP address if you wish - but you will need to change the command to use ffserver or some other server system if you want more than one machine to display the feed. Then after maybe 2-3 clients (depending on the video bitrate) the Pi's USB Ethernet adapter will run out of bandwidth. With multicast there's no need to run a server (client machines just choose whether to listen to the traffic or ignore it) so you can have thousands of machines displaying the video with no impact on the Pi, which only ever sends out a single video stream. – Malvineous Mar 20 '17 at 23:58
  • Thanks for explaining - But multicast only works on internal networks? If an ISP gets a multicast packet they usually just strip it- So it's not like you can just broadcast to everybody in the internet. I suppose if you got a large internal network, mulit casting a massive stream may also impact your network? But yea.. just for me to view a stream I would just UDP to a selected IP.. but I like the multicast option anyway :D Will try and do it this weekend just because I never did it before. :) Thanks – ppumkin Mar 21 '17 at 11:37
  • 1
    Yes multicast is mainly for internal networks. It's supposed to work better with IPv6 but I think it will still need cooperation from the ISP. I use it because it means I don't have to run a server on the Pi, and I can view the streams from two different machines plus record it to disk without changing the Pi's configuration, or overloading the Pi's network bandwidth. If your internal network is large then you will probably be using IGMP-capable switches which are designed to only send multicast traffic where it's needed to make the impact no different to normal. – Malvineous Mar 22 '17 at 0:17
  • 1
    Thanks for explaining.. I can now see many benefits of using multicast with minor caveats that won't even impact home users really. I will definitely give this a try. It is the simple and obvious things sometimes that need to be pointed out to make sense. And looking at your update.. the recording bit is actually really,really cool! – ppumkin Mar 22 '17 at 13:13

I managed to stream from my Raspberry Pi to a web server with the compiled-in module nginx-rtmp.

To save hassles with ffmpeg, I recommend a rolling distribution like Arch Linux Arm.

raspivid -vf -t 0 -fps 25 -b 2000000 -o - |
ffmpeg -i - -vcodec copy -an -r 25 -f flv rtmp://x220/myapp/mystream

Some notes:

So on this basis, I think live streaming from a Raspberry Pi might be OK for a temporary broadcast, but not for an always-on Web cam since it's too bandwidth-hungry. You will not get audio and if you do, it will a mission to sync.

You can record audio more efficiently separately at the same time as recording video. Then later perhaps mux the audio feed in later and convert it to WebM and put it on your httpd as a static file with an HTML video tag. The workflow is pretty awkward, though it's the best I can think of for an efficient broadcast that will work painlessly across browsers.

  • 1
    You can control the bandwidth and resolution though. If its local LAN streaming for CCTV use then thats not even a problem. Broadcasting over internet might need to be on demand and/or a much lower resolution. But its another way of doing it. Thanks +1 – ppumkin Aug 5 '13 at 8:28
  • and how does it suppose to work? it doesnt for me... FFMPEG says "RTMP_Connect0, failed to connect socket. 111 (Connection refused)" – Flash Thunder Jul 3 '15 at 14:33

UV4L now supports live Audio & Video Streaming with WebRTC and HTML5.

  • just read the link above... – Strunz Mar 30 '15 at 15:41
  • Works really well! – ppumkin Apr 8 '15 at 17:37
  • How? The link to its example page is broken... – Cerin Feb 20 '16 at 21:27
  • I have been through those tutorials and I can confirm they do not work – Quintin Balsdon Jul 10 '17 at 10:22
  • I can confirm it does work as I have tried it.. instructables.com/id/Raspberry-Pi-Video-Streaming – Tia Dec 30 '17 at 11:05

UV4L now supports live audio & video broadcasting to Jitsi Meet Rooms over the Web. No special configuration is required. It's as easy as filling your name, room and clicking on Start.

  • which browser are you using? Jitsi only support Chrome, Chromium, Opera, and Firefox NIghtly, of which only Chromium is available on the Pi. But Chromium give me a webkitRTCPeerConnection is not defined error. I normally use IceWeasel for WebRTC, but that is not supported for Jitsi. – modulitos Sep 17 '15 at 10:28
  • 1
    on the PI there is no browser supporting WebRTC , except an almost broken support in IceWeasel. The way I am using it is : Pi->Jitsi Server on the Cloud -> my PC elsewhere – prinxis Sep 17 '15 at 20:44
  • 1
    UV4L supports hardware-encoded H264 live streaming with no latency. – prinxis Jan 14 '16 at 21:36

protected by ppumkin May 8 '15 at 7:31

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.