Live Video Streaming with Raspberry Pi camera module

From JMK Wiki
Jump to navigation Jump to search

Installing required software

Raspberry Pi side

Gstreamer is a great way to pass video stream over the network to a streaming media server.

Prerequisites

Raspbian packages

  • gstreamer1.0-tools
  • gstreamer1.0-plugins-bad?
  • gstreamer1.0-plugins-base
  • gstreamer1.0-plugins-good?
  • libgstreamer1.0-dev
  • libgstreamer-plugins-base1.0-dev
  • python3-pip

Python packages

  • meson
  • ninja

Install the necessary packages

root@localhost ~ # apt install gstreamer1.0-tools gstreamer1.0-plugins-bad gstreamer1.0-plugins-base gstreamer1.0-plugins-good python3-pip
root@localhost ~ # pip3 install ninja

GStreamer element for the Raspberry Pi camera module

To be able to use the Raspberry PI camera module, download and compile the GStreamer element for the Raspberry Pi camera module (optional).

user@localhost ~ $ mkdir -p /usr/local/src
user@localhost ~ $ cd /usr/local/src
user@localhost /usr/local/src $ git clone https://github.com/thaytan/gst-rpicamsrc.git
user@localhost /usr/local/src $ cd gst-rpicamsrc
user@localhost /usr/local/src/gst-rpicamsrc $ make

Install the GStreamer element for the Raspberry Pi camera module

root@localhost /usr/local/src/gst-rpicamsrc # make install

OpenMAX IL GStreamer wrapper

For hardware accelerated video encoding, download and compile the OpenMAX IL GStreamer wrapper (optional)

user@localhost ~ $ mkdir -p /usr/local/src
user@localhost ~ $ cd /usr/local/src
user@localhost /usr/local/src $ git clone https://gitlab.freedesktop.org/gstreamer/gst-omx.git
user@localhost /usr/local/src $ cd gst-omx
user@localhost /usr/local/src $ git checkout 1.14.4
user@localhost /usr/local/src/gst-omx $ meson builddir -Dwith-omx-target=rpi
user@localhost /usr/local/src/gst-omx $ make
user@localhost /usr/local/src/gst-omx $ ./autogen.sh --prefix=/usr --sysconfdir=/etc --with-omx-header-path=/opt/vc/include/IL --with-omx-target=rpi
user@localhost /usr/local/src/gst-omx $ make

Install the OpenMAX IL GStreamer wrapper

root@localhost ~ # make install

NGINX (optional)

To install NGINX the rtmp use flag needs to be unmasked

root@localhost ~ # mkdir -p /etc/portage/profile
root@localhost ~ # echo -rtmp >> /etc/portage/profile
root@localhost ~ # echo www-servers/nginx rtmp >> /etc/portage/package.use
root@localhost ~ # emerge -av nginx

Set up rtmp live streaming with NGINX

rtmp {
    server {
        listen 1935;

        application live {
            live on;
        }
    }
}

Streaming server side (optional)

A more serious streaming media server can be used for streaming the video. The following is the most simple example of using Red5 Media Server, which is a free and open source media server, but Wowza, or the Adobe Media Server can be used as well, possibly others.

  • Download the latest stable (or whatever) version (direct link to Red5 1.0.6 Release for Linux and Windows)
  • extract the archive
  • start the server with default settings using the red5.sh (on Linux) or red5.bat (on Windows) startup script.

Web server side

A flash video player needs to be installed on the web server. Here's a simple example for Adobe's Flash Builder. Replace red5.yourdomain.com with the actual address of the media server.

<?xml version="1.0" encoding="utf-8"?>
<s:Application width="960" height="540" xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:s="library://ns.adobe.com/flex/spark">
    <s:layout>
        <s:VerticalLayout/>
    </s:layout>
    <s:VideoDisplay width="100%" height="100%">
        <s:source>
            <s:DynamicStreamingVideoSource host="rtmp://red5.yourdomain.com/live/livestream"streamType="live">
                <s:DynamicStreamingVideoItem streamName="livestream"/>
            </s:DynamicStreamingVideoSource>
        </s:source>
    </s:VideoDisplay>
</s:Application>

Build and export the application, and copy it somewhere on the web server.

Setting up the Raspberry Pi camera module

Boot settings

To be able to use the Raspberry Pi camera module the updated GPU firmware needs to be used and the GPU memory needs to be set to a minimum of 128MB by adding the following lines to the /boot/config.txt

start_file=start_x.elf
fixup_file=fixup_x.dat
gpu_mem=128

User access

To make sure, non-root users can access the camera, create a file named /etc/udev/rules.d/10-vchiq-permissions.rules with the following content

root@localhost ~ # mkdir -p /etc/udev/rules.d
root@localhost ~ # echo "SUBSYSTEM==\"vchiq\",GROUP=\"video\",MODE=\"0660\"" > /etc/udev/rules.d/10-vchiq-permissions.rules

This will grant rw access to the video group on the camera device.

The desired user needs to be added to the video group (user is the name of the user, and group1,group2 can be a comma separated list of any additional groups)

root@localhost ~ # usermod -G group1,group2,video user

These changes require a reboot to take effect.

Test the camera

Enter the following command to check if the camera works. It should display a live feed for 5 seconds.

user@localhost ~ $ /opt/vc/bin/raspivid -d

Start the camera

Start feeding the stream to the media server with issuing the following command on the Raspberry PI

Raspberry Pi camera module

user@localhost ~ $ gst-launch-1.0 rpicamsrc bitrate=2097152 preview=false rotation=180 sensor-mode=5 ! video/x-h264,width=1280,height=720,framerate=25/1,profile=high ! h264parse ! flvmux ! rtmpsink location=rtmp://red5.yourdomain.com/live/livestream

Raspberry Pi camera module with PiP and stats

Similar to the previous but the preview is displayed Picture-in-Picture style. Also the date, time and frame number is displayed.

user@localhost ~ $ gst-launch-1.0 rpicamsrc bitrate=2097152 preview-opacity=127 preview-x=0 preview-y=0 preview-w=480 preview-h=270 fullscreen=false rotation=180 sensor-mode=5 annotation-mode=0x020c ! video/x-h264,width=1280,height=720,framerate=25/1,profile=high ! h264parse ! flvmux ! rtmpsink location=rtmp://red5.yourdomain.com/live/livestream

Raspivid with pipe

In case you don't have gst-rpicamsrc

user@localhost ~ $ raspivid -t 0 -b 2097152 -rot 180 -n -o - | gst-launch-1.0 fdsrc ! video/x-h264,width=1280,height=720,framerate=25/1,profile=high ! h264parse ! flvmux ! rtmpsink location=rtmp://red5.yourdomain.com/live/livestream

Raspivid with pipe with PiP

user@localhost ~ $ raspivid -t 0 -b 2097152 -rot 180 -w 1280 -h 720 -p '0,0,480,270' -op 127 -o - | gst-launch-1.0 fdsrc ! video/x-h264,width=1280,height=720,framerate=25/1,profile=high ! h264parse ! flvmux ! rtmpsink location=rtmp://red5.yourdomain.com/live/livestream

V4L Camera

In case you're using an USB camera

user@localhost ~ $ gst-launch-1.0 v4l2src ! video/x-raw,width=1280,height=720,framerate=25/1 ! omxh264enc target-bitrate=2097152 control-rate=variable ! video/x-h264,width=1280,height=720,framerate=25/1,profile=high ! h264parse ! flvmux ! rtmpsink location=rtmp://red5.yourdomain.com/live/livestream

Explanation

Raspivid
-t 0 arguments tells raspivid not to stop the video after 5 seconds
-b 2097152 sets the bitrate of the video to 2Mbps
-rot 180 rotates the image 180 degree (my camera is upside down...don't ask) clockwise (or counter-clockwise, it doesn't matter)
-w sets the video width
-h sets the video height
-n turns off the preview
-p turns on the preview, optionally <'x,y,w,h'> sets the the preview position and size
-op opacity (0-255)
-o - sends the encoded output to STDOUT (or in this case directly to Gstreamer through a pipe)
Gstreamer
rpicamsrc reads from the Raspberry Pi camera module (requires gst-rpicamsrc)
bitrate=2097152 sets the birtate to 2Mbps
preview=false disables the preview (obviously you either need this one or the following four - using all five doesn't make sense)
preview-opacity=127 sets the preview 50% opaque
preview-x=0 preview-y=0 sets the preview position to the top left corner
preview-w=480 preview-h=270 sets the preview size 480*270
fullscreen=false disables full screen preview
rotation=180 rotates the image 180 degree (my camera is upside down...don't ask) clockwise (or counter-clockwise, it doesn't matter)
sensor-mode=5 sets the sensor to the following mode: 1296x730 16:9 1-49fps
annotation-mode=0x020c adds date, time, and frame counter
fdsrc reads from STDIN (or in this case from raspivid through the pipe)
v4l2src reads from the a v4l2src source
video/x-raw,width=1280,height=720,framerate=25/1 sets the dimensions and the frame rate of the raw video (1280*720@25)
omxh264enc target-bitrate=2097152 control-rate=variable encodes the video with a target bitrate of 2Mbps using the hardware encoder (requires gst-omx)
video/x-h264,width=1280,height=720,framerate=25/1,profile=high sets the dimensions, the frame rate and the profile of the H.264 video (1280*720@25 - high)
h264parse parses the H.264 stream
flvmux muxes the video stream into an FLV stream
rtmpsink sends FLV content to a server defined by the location via RTMP. Remember to replace red5.yourdomain.com with the actual address of the media server. The /live path tells the server that it's a live stream, and /livestream is the name of the stream. These can change when using different media servers and usually broadcasting more than one stream is allowed.