Skip to content

Instantly share code, notes, and snippets.

@russfeld
Last active April 1, 2024 14:50
Show Gist options
  • Save russfeld/0878b1f8eaf7409136b9125ce5e1458f to your computer and use it in GitHub Desktop.
Save russfeld/0878b1f8eaf7409136b9125ce5e1458f to your computer and use it in GitHub Desktop.
Stream Raspberry Pi Camera to Twitch
#!/bin/bash
# =================================================================
# Stream configuration file for Raspberry Pi Camera
#
# @author Russell Feldhausen ([email protected])
# @version 2019-06-05
#
# This set of commands should allow you to stream video from your
# Raspberry Pi Camera to Twitch and Youtube (and possibly other
# RTMP endpoints) with decent quality and performance.
#
# You may need to install raspivid and/or ffmpeg to use this script.
#
# This was tested and built on Raspbian 9 installed using Noobs
# =================================================================
# Set width and height of output video
WIDTH=1920
HEIGHT=1080
# Set output framerate
FRAMERATE=30
# Set keyframe spacing (must be double the framerate)
KEYFRAME=60
# Set bitrate (Twitch recommends 3500000)
BITRATE=3500000
# Set stream URL
URL=
# Set stream key
KEY=
# Command
raspivid -n -t 0 -w $WIDTH -h $HEIGHT -fps $FRAMERATE -b $BITRATE -g $KEYFRAME -o - | ffmpeg -f lavfi -i anullsrc -c:a aac -r $FRAMERATE -i - -g $KEYFRAME -strict experimental -threads 4 -vcodec copy -map 0:a -map 1:v -b:v $BITRATE -preset ultrafast -f flv "${URL}/${KEY}"
# =================================================================
# Full Documentation of Command Options
#
# +++ raspivid +++
# -n = no preview window
# -t = time to capture (0 to disable, which allows streaming)
# -w = video width
# -h = video height
# -fps = output framerate (max 30 for 1080p, 60 for 720p)
# -b = bitrate
# -g = keyframe rate (refresh period)
# -o - = output to stdout (allows piping to ffmpeg)
#
# +++ ffmpeg +++
# -f lavfi = use lavfi filter (see note below)
# -i anullsrc = grab blank input (see note below)
# -c:a aac = set audio codec to aac
# -r = output framerate (should match raspivid framerate)
# -i - = read input from stdin (piped from ffmpeg)
# -g = keyframe rate (refresh period)
# -strict experimental = allow nonstandard things
# -threads 4 = set number of encoding threads to 4 (# of cores)
# -vcodec copy = use video as-is (do not re-encode video)
# -map 0:a = use the audio from input 0 (see note below)
# -map 1:v = use the video from input 1 (raspivid)
# -b:v = bitrate
# -preset ultrafast = use the ultrafast encoding preset
# -f flv = set output format to flv for streaming
# "${URL}/{KEY}" = specify RTMP URL as output for stream
#
# ** NOTE **
# According to some information online, YouTube will reject a live
# stream without an audio channel. So, in the ffmpeg command above
# a blank audio channel is included. It was not required for Twitch
# in my testing.
# =================================================================
@jfthompson1
Copy link

Many thanks for this. I am using a raspberry pi 3B with the raspicam v2 to stream live video, and I have tried many combinations including raspivid, ffmpeg, ncat, and uv4l, and this is the best I have found by far. I am able to stream 30fps at 1920x1080 to a Twitch account. None of the other solutions provided this fps. Having the script will be particularly helpful so I can include this in a cron job. Thanks again for providing this solution.

@TaylorHokanson
Copy link

Hey, this script works great! Like the comment above, I'm interested in automatically starting the script with a cron job or similar. I can't seem to make it work, however. I have the script set as an executable with chmod +x, and it works well when I call it from the terminal, but I can't seem to run it automatically via cron or rc.local. Any advice you have is appreciated!

@florian-luce
Copy link

florian-luce commented Jul 29, 2020

Hello! First, Thanks for this script, it works really well!

@TaylorHokanson, Here is what I used to run this script when the pi starting:

In /etc/systemd/system/ I have create an new file (with sudo): launchTwitchLive.service

[Unit]
Description=Launch Twitch Live
After=network.target

[Service]
ExecStart=/bin/bash -u picam-stream.sh
WorkingDirectory=/home/pi/Live
StandardOutput=inherit
StandardError=inherit
Restart=always
User=pi

[Install]
WantedBy=multi-user.target

(The live script is in /home/pi/Live/picam-stream.sh)

And after, you need to register this service for pi start with: sudo systemctl enable launchTwitchLive.service

You can restart now ;)

If you need to stop after start : sudo systemctl stop launchTwitchLive.service

If you need to start after stop : sudo systemctl stop launchTwitchLive.service

And the doc for more informations: https://www.raspberrypi.org/documentation/linux/usage/systemd.md

Good live!

Edit: I even disabled the desktop on startup to consume less resources, it works great :)

@TaylorHokanson
Copy link

Thanks so much for the detailed answer. When my project goes live I'll be sure to note your help and send you a link.

@russfeld
Copy link
Author

russfeld commented Aug 7, 2020

Thanks everyone for the input! This is fantastic! I'm glad folks are finding this useful.

@florian-luce
Copy link

have you ever tried adding an audio stream from a micro usb adapter like this?
https://www.amazon.fr/gp/product/B01N905VOY/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1

@Luc3as
Copy link

Luc3as commented Aug 17, 2020

have you ever tried adding an audio stream from a micro usb adapter like this?
https://www.amazon.fr/gp/product/B01N905VOY/ref=ppx_yo_dt_b_asin_title_o06_s00?ie=UTF8&psc=1

I am trying to achieve the same ...

@Joey1Daddy
Copy link

Joey1Daddy commented Sep 15, 2020

I got it working with a sound card, but you might need to recompile FFmpeg. I also added audio-video syncing and camera settings:

`#!/bin/bash

# Set width and height of output video
WIDTH=1920
HEIGHT=1080

# Set output framerate
FRAMERATE=30

#Set Rotation
ROTATION=0

# Set keyframe spacing (must be double the framerate)
KEYFRAME=60

# Set bitrate (Twitch recommends 3500000)
BITRATE=3500000

# Camera Settings (includes commands)
SATURATION=25         #sa
SHARPNESS=            #sh
CONTRAST=            #co
BRIGHTNESS=           #br
AWB=               #awb
ISO=                  #iso
SHUTTERSPEED=         #ss
EXPOSURE=             #ex
EV=0                #ev
ANTIFLICKER=          #fli
IMAGEEFFECT=          #ifx

# Set video offset
OFFSET=0.5

# Set Audio input (check using "arecord -l")
INPUT=plughw:2,0

# Set stream URL
URL=

# Set stream key
KEY=

# Command
raspivid -o - -t 0 -w $WIDTH -h $HEIGHT -fps $FRAMERATE -b $BITRATE -rot $ROTATION -g $KEYFRAME -sa $SATURATION -awb $AWB -ev $EV -f | /home/pi/ffmpeg/ffmpeg -use_wallclock_as_timestamps 1 -thread_queue_size 10240 -f h264 -r 30 -i - -itsoffset $OFFSET -f alsa -thread_queue_size 10240 -ac 2 -i $INPUT -vcodec copy -acodec aac -ac 2 -ar 44100 -ab 192k -f flv "${URL}/${KEY}"
`

@russfeld
Copy link
Author

That looks awesome! Thanks for the update. I'll have to try it sometime.

@tjabdoullah
Copy link

thank you, it's working like a charm.

@metalolf
Copy link

Just want to share some appreciations to @russfeld for the script and @florian-luce for the systemd implementation. Works like a charm! 🙏❤

@davefp
Copy link

davefp commented May 23, 2022

This script works brilliantly. A tip if you have the NOIR camera: Add -awb greyworld to the raspivid command so that the output doesn't look pink.

@Sweetkubuni
Copy link

I get the following warnings :
[h264 @ 0x212b090] Thread message queue blocking; consider raising the thread_queue_size option (current value: 8)
[flv @ 0x21dcc40] Timestamps are unset in a packet for stream 1. This is deprecated and will stop working in the future. Fix your code to set the timestamps properly

@carlitoselmago
Copy link

carlitoselmago commented Nov 24, 2022

Thanks for this amazing script, i was checking on the how to add audio to it. I saw the comments about adding an input using a usb soundcard input. In my case I just needed to add a background music to the stream with no need of sync with the video, so my plan is to use prerecorded mp3 audio file, here is how I modified the command for that purpose:

raspivid -n -t 0 -w $WIDTH -h $HEIGHT -fps $FRAMERATE -b $BITRATE -g $KEYFRAME -o - | ffmpeg -i audio-file.mp3 -c:a aac -r $FRAMERATE -i - -g $KEYFRAME -strict experimental -threads 4 -vcodec copy -map 0:a -map 1:v -b:v $BITRATE -preset ultrafast -f flv "${URL}/${KEY}"

@diegozalez
Copy link

diegozalez commented Jan 21, 2023

Hi first for making this script its been a huge help, I have a problem since raspivid is no longer working, I have tried to modify it by changing it to: libcamera-vid -n -t 0 --width $WIDTH --height $HEIGHT --frames $FRAMERATE -g $KEYFRAME -b $BITRATE -o -| ffmpeg but in twitch, I only get a blank screen and 0kbps bitrate. Any idea of what can I do to fix this?
UPDATE:
I've made an updated tool that works with libcamera and with more additions. Here it is: https://github.com/diegozalez/RaspyStream

@SarahDal
Copy link

This is brilliant, thank you so much for this, works a treat!

@diegozalez
Copy link

This is brilliant, thank you so much for this, works a treat!

Thanks a lot!!!! it means to me very much !!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment