This page contains the current bash scripts I have developed for streaming video from the Raspberry Pi camera to a Linux Laptop. I will update this page as I make improvement and additions to the scripts.
These scripts assume you have generated a ssh public key on your laptop and uploaded it onto the Pi. This will allow ssh to contact the Pi without you having to type a password every time. I’ve outlined how to do this in one of the comments below.
Script Usage
- Configure the network.conf and video.conf files
- Boot the Raspberry Pi
- Connect the laptop WiFi to the Raspberry Pi’s Wifi Access Point
- Open a terminal on the Laptop
- run the ./go script on the laptop to update the configuration files on the Pi and set the time and date.
- The go script will leave you in a ssh session on the Pi
- run the ./ustream or ./utee scripts on the Pi.
- Open a second terminal on the laptop.
- run the ./tsplay or ./uts scripts on the Laptop
- The video will start streaming.
Laptop Scripts
1. Network Configuration File
Filename: network.conf
Command line options: none
#!/bin/bash # TX_IP should contain the IP address of the Raspberry Pi. export TX_IP=192.168.42.1 export RX_IP=$(ip -o addr show wlan0 | sed -n 's/.*inet \([0-9.]*\)\/.. .*/\1/p') export TCPPORT=5000 export UDPPORT=5001 export USER=pi
2. Video Configuration File
Filename: video.conf
Command line options: none
#!/bin/sh ###### Video Settings ###### # Zero duration is continuous export DURATION=0 export WIDTH=1280 export HEIGHT=720 export FRAMERATE=48 export BITRATE=6000000
3. Upload Configuration and start a remote shell on the Pi
Filename : go
Command line options : Frame rate in frames per second. Must be suitable for the selected video resolution.
#!/bin/bash source network.conf rm remote.conf if [ "$1" != "" ] then sed "s/FRAMERATE=25/FRAMERATE=$1/" video.conf > remote.conf else cp video.conf remote.conf fi date echo "###### Network Settings ######" >> remote.conf echo export TCPPORT=$TCPPORT >> remote.conf echo export UDPPORT=$UDPPORT >> remote.conf echo export RX_IP=$RX_IP >> remote.conf echo export NOW=\"`date +%F" "%T`\" >> remote.conf #echo exit >> remote.conf chmod +x remote.conf echo Copy script to $TX_IP scp remote.conf $USER@$TX_IP:/home/pi echo Run Script ssh $USER@$TX_IP ./remote.sh ssh $USER@$TX_IP
4. Capture and play a UDP stream – Does not record the stream
Filename : tsplay
Command line options : none
#!/bin/bash source ./video.conf source ./network.conf gst-launch-1.0 -v udpsrc port=$UDPPORT \ caps='application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264' ! \ rtph264depay ! h264parse config-interval=96 ! \ avdec_h264 ! videoconvert ! autovideosink sync=false
5. Capture, play and record a UDP stream – saved file is muxed to a transmission stream (.ts) container
Filename : uts
Command line options : none
#!/bin/bash source ./video.conf source ./network.conf NOW=`date +%Y%m%d%H%M%S` FILENAME=$NOW-Rx-$FRAMERATE-$BITRATE.ts gst-launch-1.0 -v udpsrc port=$UDPPORT \ caps='application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264' ! \ rtph264depay ! h264parse config-interval=96 ! \ tee name=t ! queue ! \ video/x-h264, framerate=$FRAMERATE/1 ! avdec_h264 ! videoconvert ! autovideosink sync=false t. ! \ queue ! mpegtsmux ! filesink location=$FILENAME
Raspberry Pi Scripts
6. Stream the Camera over UDP without recording locally.
Filename : ustream
Command line options : Frame rate in frames per second. Must be suitable for the selected video resolution.
#!/bin/bash source remote.conf if [ "$1" != "" ] then export FRAMERATE=$1 fi NOW=`date +%Y%m%d%H%M%S` FILENAME=$NOW-Tx.h264 /opt/vc/bin/raspivid -t $DURATION -w $WIDTH -h $HEIGHT -fps $FRAMERATE -b $BITRATE -n -pf baseline -o - | gst-launch-1.0 -v fdsrc ! h264parse ! rtph264pay config-interval=1 pt=96 ! udpsink host=$RX_IP port=$UDPPORT
7. Stream the Camera over UDP and save local copies of the video (.h264) and the GPS trace (.gpx).
Filename : ustream
Command line options : none.
#!/bin/bash source ./remote.conf NOW=`date +%Y%m%d%H%M%S` FILENAME=$NOW-Tx-$FRAMERATE-$BITRATE.h264 gpxlogger -i 2 -f $NOW.gpx & /opt/vc/bin/raspivid -t $DURATION -w $WIDTH -h $HEIGHT -fps $FRAMERATE -b $BITRATE -n -pf baseline -o - | tee $FILENAME | gst-launch-1.0 -v fdsrc ! h264parse ! rtph264pay config-interval=1 pt=96 ! udpsink host=$RX_IP port=$UDPPORT
Hi,
First, thanks for sharing. in point 6, could you explain what are the commands -n -pf high for ?
besides that, i tried 48fps and 6000000 bitrate, as you advise, what a huge difference with crap video i got in 30fps. Thanks again ! Need to try during flight now..
Hi,
The -n switch is “No Preview”. Without it the Pi will send the video to the video out port. In my earliest tests, I found this added about 80ms to the latency. Whether it will attempt it if nothing is connected to the hdmi or composite ports, I don’t know, but better safe than sorry. Full details of the raspivid command line switches are available in the Raspberry Pi Camera Documentation
The -pf high relates to the h264 “high” profile. Essentially there are three profiles: baseline, high and main. They specify what features are available to the encoder. Baseline has the maximum compatibility. High includes features that reduce the required bandwidth, but are less compatible with some older devices. There is a good discussion at Superuser.com
i noticed that when you save video on Pi while streaming (point 7), you don’t use -pf high, is it to save cpu load ?
Also, did you try rpicamsrc element ? seems some guys get lower latency with it. I guess it would give something like gst-launch-1.0 rpicamsrc ! ‘video/x-h264, width=1280, height=720, framerate=48/1
Re: Point 7. Actually I just forgot to add it in. It’s there now.
Free time has been short of late. I haven’t followed the development of rpicamsrc. I can see some more testing coming. Thanks for the heads up.
ok thanks. Seems you use linux on your laptop, right ?
I use Lubuntu 13.10 as a more lightweight distribution with gstreamer 1.2.xx. I can’t get the 14.xx versions to work with my wifi card.
The pi capture scripts (6 and 7) have been updated to use the baseline profile, as this has shown a 3 to 4 ms reduction in latency over the high profile.
everything seems to work except when running ./go i get error
remote.conf 100% 285 0.3KB/s 00:00
Run Script
pi@192.168.1.101‘s password:
bash: ./remote.sh: No such file or directory
and it continues from there as if there was no issue until i run the ./ts play it says it is playing but i dont see anything.
help please!
You need to create a key for ssh, so that you don’t have to enter your password to login to the pi.
On the receiving end computer run ssh-keygen in a terminal. Accept all the defaults, DON’T enter a passphrase when prompted.
~ $ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/pi/.ssh/id_rsa):
Created directory '/home/pi/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/pi/.ssh/id_rsa.
Your public key has been saved in /home/pi/.ssh/id_rsa.pub.
The key fingerprint is:
09:c6:4a:7e:8c:36:4b:a3:1b:30:d8:4e:0b:b6:9a:b6 pi@PiCam
The key's randomart image is:
+--[ RSA 2048]----+
| |
| . |
| . + |
|.. o = . . |
|=.o O o S |
|.*.= = |
| .= . |
|.o o |
|+Eo |
+-----------------+
This creates a pair of files in a hidden directory .ssh
~ $ cd .ssh
~/.ssh ~ ls
id_rsa id_rsa.pub
These are your public and private key pair. You need to copy the public key to the transmitting Pi. I use this script
#!/bin/bash
source ./network.conf
scp ~/.ssh/id_rsa.pub $USER@$TX_IP:.ssh/authorized_keys
Make sure the .ssh directory exists on the pi before you run the script. You will need to enter the password to copy the script.
From here on you should be able to enter ssh pi@192.168.1.101 and get a remote shell without having to enter a password.
To get the stream running follow this sequence.
1. On the receiving machine run
./go
This will copy the configuration files across and drop you into a remote shell on the transmitting Pi.2. In the remote shell start the stream
./ustream
3. Start a new terminal on the receiving machine and run the play script
./tsplay
4. If all goes well a window should pop up showing the video.
Hi,
thanks for all that testing… lots of good stuff here…
i`ve been looking into it for a while now.. and my intent is to stream with gstreamer and open it on a webpage.
looks like i`ve found something that does it and i`d like to share.
http://tpy.tw/?p=109
and there`s also this site that may even further help with your latency problem. maybe you can give it a try when you have the time. i`d love to see the stats for it.
http://www.emlid.com/raspberry-pi-real-time-kernel/
Hi Bruno.
Thanks for the links. That real-time kernel looks interesting. I’ll definitely have to try fitting that in at some point.
nice work dude – FYI: I’m currently working on a similar solution. The difference is that I’m running a node.js server component on the Pi and I use an Android App on my mobile to control it and for video playback. Streaming is working fine so far but I’m still working on the functionality to get the telemtry data from the flight controller and to draw a HUD as an overlay on the screen.
I’ll publish the code somewhare when I’m done and let you know.
Did you have time to try this real time kernel in the meantime?
Cheers Peetie. Up to now, I’ve been concentrating on getting the latency as low as possible in what little time I have available. Today I managed to get the 5 GHz WiFi working with Pi2B, so now I can get the last couple of bench tests complete and start flight testing around other people.
I haven’t tried the real-time kernel yet. Compiling on the Pi2 has proven a challenge.
What sort of range can you get to a mobile phone?
Hi Peetie,
Could you tell which Android app are you using for viewing?
I tried AirPi but it seems that the image for the RPI side is not complete so I am looking for an alternative solution…
Thank you for your reply – did not do any range tests yet.
However I don’t assume that it’s much shorter than using a notebook. I’ll let you know when it tested the range…
Hey gary,
Ok, no news on the range front (no testing done yet), but something else which might be interesting to you as well. I thought about the command running and about eliminating buffers. Since we pipe two commands, I thought about pipe buffering and read about it:
http://linux.die.net/man/7/pipe
For sure we need to get rid of as many buffering as possible inside the system that’s why I was looking how to disable the pipe buffering. Seems like stdbuf of GNU coreutils is doing the job.
I’m currently running the following script on my Pi1B – which subjectively is a bit smoother with disabling the pipe buffer than having a pipe buffer in the system.
stdbuf -i0 -o0 -e0 raspivid -n -w 640 -h 480 -b 6000000 -fps 45 -g 1 -vf -hf -t 0 -o – | gst-launch-1.0 -v fdsrc ! h264parse ! rtph264pay config-interval=20 pt=30 ! udpsink host=$1 port=$2
If you still have your testenvironment set up, it would be great to see whether this squeezes out some more millisecons.