[TriLUG] Streaming to Twitch.tv on Linux

Barry Peddycord III bwpeddyc at ncsu.edu
Thu Jan 9 23:18:51 EST 2014


At dinner tonight, someone indicated interest in how to stream to 
Twitch.tv on Linux. Below (quoted) is a Bash script my brother uses to 
stream on Ubuntu (the avconv scripts on the internet no longer work as 
of the new Xbox One PS4 livestreaming upgrades). All you have to do is 
store your Twitch broadcast key in a file called ~/.twitch_key and set 
the variables in the script correctly.

Twitch uses the same system as justin.tv, so you should be able to fix 
the variables below with some hackery.

Sharing because I was asked to. No warranty of particular 
merchantability porpoises.

> #!/bin/bash
> ## Stream the desktop (and webcam) to livestream.com or twitch.tv!
> ## stream v0.4.0 by haarp
> ## Distributed under the terms of the GNU General Public License v3
> ##
> ## Dependencies: ffmpeg (mandatory, libav may not work!), xwininfo (mandatory)
> ## notify-send (if GUI is desired), pavucontrol (if pulseaudio shall transmit audio)
> ## !! libav users must define an audio device !!
> ##
> ## Uses x264 to encode the stream, which requires a lot of CPU power - the stream will lag
> ## or fall behind if the CPU can't keep up - tweak FPS, PRESET and HALFRES to combat this
>
> ### SETTINGS
> FFMPEG="ffmpeg"		# ffmpeg binary to use, usually "ffmpeg" or "avconv"
> FPS="30"		    # frames per second. default: "30"
> PRESET="ultrafast"	# encoder preset, tweaks encoder speed against quality. default: "medium", possible values:
> 			        # ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow, placebo
> 			        # faster = less cpu
> TUNE=""	# encoder tuning options. default: "" (none), possible values:
> 			        # film, animation, grain, stillimage, psnr, ssim, fastdecode, zerolatency(avoid)
> BITRATE="128k"		# video stream bit/s, should be below network upload bandwidth. default: "" (no limit, may lag)
> HALFRES="true"		# halve the output resolution, reducing processer load. default: "false"
> WEBCAM=""		# webcam device to use (overlaid in upper right corner), e.g. "/dev/video0". default: "" (disabled)
> WEBCAMWIDTH="480"	# camera picture width to use (in pixels). default: "480"
> AUDIO="default"		# ALSA device to use, adds 64kbit/s to the stream, "" to disable. options: "default", "pulse", etc.
> 			# for "pulse" (recommended), run pavucontrol after starting the stream to set an input device
>
> ## -----------------------------------------------------------------------------
> ### TWITCH.TV
> STREAM_KEY=$(cat ~/.twitch_key)
> CHANNEL="channelname"
> ## -----------------------------------------------------------------------------
> OUTPUT="rtmp://live.twitch.tv/app/$STREAM_KEY"
> URL="http://www.twitch.tv/$CHANNEL"
> STREAMURL="http://www.twitch.tv/$CHANNEL/popout"
> CHATURL="http://www.twitch.tv/chat/embed?channel=$CHANNEL&popout_chat=true"
>
> ### OTHER
> #OUTPUT=-
>
> ## -----------------------------------------------------------------------------
> ### DON'T MESS BELOW THIS LINE
> print() {
> 	if [[ $gui == "1" ]]; then
> 		notify-send -i video "$(basename "$0")" "$1"
> 	else
> 		echo -e "$1" >&2
> 	fi
> }
> [[ $TERM == "linux" || $TERM == "dumb" ]] && {
> 	if which notify-send &>/dev/null; then
> 		gui=1
> 	else
> 		gui=0
> 		echo "notify-send not found, using stderr!" >&2
> 	fi
> }
>
> for program in $FFMPEG xwininfo; do
> 	which $program &>/dev/null || {
> 		print "$program not found, aborting!"; exit 9; }
> done
>
> if [[ $WEBCAM ]]; then
> 	if [[ -c "$WEBCAM" ]]; then
> 		print "Using webcam $WEBCAM"
> 		webcamarg1="-vf"
> 		webcamarg2="movie=$WEBCAM:f=video4linux2, scale=$WEBCAMWIDTH:-1, fps, setpts=PTS-STARTPTS [movie]; [in][movie] overlay=main_w-overlay_w-2:2 [out]"
> 	else
> 		print "Device $WEBCAM not found, aborting!"; exit 2
> 	fi
> else
> 	webcamarg1=""
> 	webcamarg2="-stats"	# this is a pointless dummy
> fi
> if [[ $AUDIO ]]; then
> 	print "Using audio device $AUDIO"
> 	audioarg_i="-f alsa -i $AUDIO"
> 	audioarg_o="-acodec libmp3lame -ar 44100 -ab 64k"
> else
> 	audioarg_i="-f lavfi -i aevalsrc=0"	# generate silence (presence of audio track fixes many bugs)
> 						# but causes time and bitrate to be shown all wrong (ffmpeg-1.2.4)
> 	audioarg_o="-acodec libmp3lame -ar 44100 -ab 1k -ac 1"	# make damn sure it's 44100!
> fi
>
> if [[ $1 == "-f" ]]; then
> 	print "Using entire screen."
> 	frame_info=$(xwininfo -root)
> else
> 	print "Select an area by clicking on a window! Use -f for fullscreen."
> 	frame_info=$(xwininfo -frame)
> 	root_info=$(xwininfo -root)
> fi
> frame_coords_x=$(echo "$frame_info" | awk '/Absolute upper-left X:/{print $4}')
> frame_coords_y=$(echo "$frame_info" | awk '/Absolute upper-left Y:/{print $4}')
> frame_geo_x=$(echo "$frame_info" | awk '/Width:/{print $2}')
> frame_geo_y=$(echo "$frame_info" | awk '/Height:/{print $2}')
>
> echo "DEBUG: Input coords: $frame_coords_x,$frame_coords_y; input size: ${frame_geo_x}x${frame_geo_y}" >&2
>
> if [[ $1 != "-f" ]]; then	# clip at screen borders
> 	root_geo_x=$(echo "$root_info" | awk '/Width:/{print $2}')
> 	root_geo_y=$(echo "$root_info" | awk '/Height:/{print $2}')
> 	[[ $(($frame_coords_x + $frame_geo_x)) -gt $root_geo_x  ]] && \
> 		frame_geo_x=$(( $root_geo_x - $frame_coords_x ))
> 	[[ $(($frame_coords_y + $frame_geo_y)) -gt $root_geo_y  ]] && \
> 		frame_geo_y=$(( $root_geo_y - $frame_coords_y ))
> fi
> until [[ $(( $frame_geo_x % 4 )) == 0 ]]; do ((frame_geo_x--)); done	# some versions of x264 can't
> until [[ $(( $frame_geo_y % 4 )) == 0 ]]; do ((frame_geo_y--)); done	# deal with uneven values
>
> if [[ $BITRATE ]]; then	bitarg="-vb $BITRATE"
> 		   else	bitarg=""
> fi
> if [[ $HALFRES == "true" ]]; then
> 	res_x=$(( $frame_geo_x / 2 ))
> 	res_y=$(( $frame_geo_y / 2 ))
> 	resarg="-s ${res_x}x${res_y}"
> 	echo "DEBUG: Cropping input to ${frame_geo_x}x${frame_geo_y}; outputting ${res_x}x${res_y}" >&2
> else
> 	resarg=""
> 	echo "DEBUG: Cropping input to ${frame_geo_x}x${frame_geo_y}" >&2
> fi
>
> print "Starting stream in 5 seconds..."
> sleep 5
>
> $FFMPEG \
> -f x11grab -s ${frame_geo_x}x${frame_geo_y} -r $FPS -i :0.0+${frame_coords_x},${frame_coords_y} \
> $audioarg_i \
> $webcamarg1 "$webcamarg2" \
> -vcodec libx264 -pix_fmt yuv420p -preset "$PRESET" -tune "$TUNE" $bitarg \
> $audioarg_o \
> -f flv -r $FPS $resarg -y "$OUTPUT"
>
> [[ $? == 0 ]] || print "$FFMPEG terminated!"
> exit

Most sincerely,
Barry Peddycord III




More information about the TriLUG mailing list