222 lines
6.6 KiB
Plaintext
222 lines
6.6 KiB
Plaintext
|
#!/bin/sh
|
||
|
|
||
|
########
|
||
|
# Copyright (c) 2018-2019 Thomas Frohwein <11335318+rfht@users.noreply.github.com>
|
||
|
#
|
||
|
# Permission to use, copy, modify, and distribute this software for any
|
||
|
# purpose with or without fee is hereby granted, provided that the above
|
||
|
# copyright notice and this permission notice appear in all copies.
|
||
|
#
|
||
|
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||
|
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||
|
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||
|
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||
|
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||
|
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||
|
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||
|
########
|
||
|
|
||
|
############
|
||
|
# TODO:
|
||
|
############
|
||
|
# - ADD OPTION TO SAVE MIC TO SEPARATE FILE (solene request)
|
||
|
# - add mention of $DISPLAY variable for the recording?
|
||
|
# - AFAIK '-preset ultrafast' is specific to libx264 and needs to be disabled
|
||
|
# for use of other codecs
|
||
|
# - get default framerate from xrandr? same for resolution - default to desktop
|
||
|
# resolution?
|
||
|
# - mention need to stop recording with Ctrl-C??
|
||
|
# - add highpass=f=200,lowpass=f=3000
|
||
|
# - document default resolution (if no window name provided) of 1920x1080
|
||
|
# - document that if -n is not given, will default to root window
|
||
|
# - document windowname (-n) needs to be in "" if multiple words
|
||
|
# - document that window needs to be visible/on top
|
||
|
# - link for finding twitch servers:
|
||
|
# http://bashtech.net/twitch/ingest.php
|
||
|
# - does -s option need to be in "" ? -> should not be needed
|
||
|
# - document that compositor has negative effect on smoothness
|
||
|
# - framerate 29 seems to be better than 30 in regads to Twitch stream health
|
||
|
# - should be either resolution (-r) (+ offset (-o)), window name (-n), or fullscreen (-fullscreen)
|
||
|
# -> should ideally default to geometry with default of 1280x720+0+0
|
||
|
# - document '-m' turns on recording from mic
|
||
|
# - '-m' currently uses hardcoded snd/0
|
||
|
# - fix '-fullscreen' parameter (not working correctly)
|
||
|
# - may not need as many 'thread_queue_size options, but definitely for the -f sndio inputs
|
||
|
# - Cryptark crashes/hangs on this Ryzen 7 2700
|
||
|
# - add '-s $OUTRES' ??
|
||
|
# - -m and -noaudio should be mutually exclusive
|
||
|
# - add man page
|
||
|
###########
|
||
|
|
||
|
###########
|
||
|
# LESSONS LEARNED
|
||
|
###########
|
||
|
# - audio offset needs to be applied to the audio in the second ffmpeg,
|
||
|
# right of the pipe. This clearly worked as opposed to left of the pipe
|
||
|
# with Rogue Legacy recording at 900p 60fps.
|
||
|
|
||
|
USAGE="Usage: `basename $0` [-m] [-d mic_device] [-a audiooffset] [-n window_name] [-c codec] [-b bitrate] [-r resolution] [-o offset] [-fullscreen] [-s <scale_x>:<scale_y>] [-f framerate] [-v volume_adjustment] [-vmic mic_volume] [-vmon monitor_volume] [-t threads ] [-noaudio] [-crf crf] <rtmp url>"
|
||
|
|
||
|
# Parse arguments based on http://www.shelldorado.com/goodcoding/cmdargs.html
|
||
|
|
||
|
audiooffset=0.0
|
||
|
bitrate=3500
|
||
|
bufsize=
|
||
|
container=flv
|
||
|
filename=
|
||
|
framerate=30
|
||
|
fullscreen=0
|
||
|
gop=
|
||
|
heightline=
|
||
|
heightval=
|
||
|
hilopass=",lowpass=3000,highpass=200,afftdn"
|
||
|
mic=0
|
||
|
mic_device=snd/0
|
||
|
noaudio=0
|
||
|
offset=
|
||
|
resolution=1280x720
|
||
|
scaleres=
|
||
|
threads=0 # -t 0 is the default and uses as many threads as available/cores
|
||
|
videocodec=libx264
|
||
|
volume=1.0
|
||
|
volume_mic=1.0
|
||
|
volume_mon=1.0
|
||
|
windowname=
|
||
|
widthline=
|
||
|
widthval=
|
||
|
wininfoargs=
|
||
|
xline=
|
||
|
xval=0
|
||
|
yline=
|
||
|
yval=0
|
||
|
|
||
|
# FIXME: set up getopt(1) use
|
||
|
#args=`getopt abo: $*`
|
||
|
#if [ $? -ne 0 ]
|
||
|
#then
|
||
|
#echo 'Usage: ...'
|
||
|
#exit 2
|
||
|
#fi
|
||
|
#set -- $args
|
||
|
#while [ $# -ne 0 ]
|
||
|
#do
|
||
|
#case "$1"
|
||
|
#in
|
||
|
#-a|-b)
|
||
|
#flag="$1"; shift;;
|
||
|
#-o)
|
||
|
#oarg="$2"; shift; shift;;
|
||
|
#--)
|
||
|
#shift; break;;
|
||
|
#esac
|
||
|
#done
|
||
|
|
||
|
if [[ $# -eq 0 ]];then
|
||
|
echo $USAGE; exit 0
|
||
|
fi
|
||
|
|
||
|
while [[ $# -gt 0 ]]
|
||
|
do
|
||
|
case "$1" in
|
||
|
-a) audiooffset="$2"; shift;;
|
||
|
-b) bitrate="$2"; shift;;
|
||
|
-c) videocodec="$2"; shift;;
|
||
|
-container) container="$2"; shift;;
|
||
|
-crf) crf="$2"; shift;;
|
||
|
-d) mic_device="$2"; shift;;
|
||
|
-f) framerate="$2"; shift;;
|
||
|
-fullscreen) fullscreen=1;;
|
||
|
-h) echo $USAGE; exit 0;;
|
||
|
-hl) hilopass="";;
|
||
|
-m) mic=1;;
|
||
|
-n) windowname="$2"; shift;;
|
||
|
-noaudio) noaudio=1;;
|
||
|
-o) offset="$2"; shift;;
|
||
|
-v) volume="$2"; shift;;
|
||
|
-r) resolution="$2"; shift;;
|
||
|
-s) scaleres="$2"; shift;;
|
||
|
-t) threads="$2"; shift;;
|
||
|
-vmic) volume_mic="$2"; shift;;
|
||
|
-vmon) volume_mon="$2"; shift;;
|
||
|
-) filename="$1"; break;;
|
||
|
-?*) echo $USAGE; exit 0;;
|
||
|
*) filename="$1"; break;;
|
||
|
esac
|
||
|
shift
|
||
|
done
|
||
|
|
||
|
if [[ -z "$filename" ]];then
|
||
|
echo $USAGE; exit 0
|
||
|
fi
|
||
|
|
||
|
bufsize=`expr $bitrate \* 2`
|
||
|
gop=`expr $framerate \* 2`
|
||
|
|
||
|
if [[ -n "$scaleres" ]];then
|
||
|
scaleres="scale=${scaleres},"
|
||
|
fi
|
||
|
|
||
|
# if -n was used, overwrite resolution with window parameters
|
||
|
if [[ -n "$windowname" ]];then
|
||
|
xline=`xwininfo -name "$windowname" | grep "Absolute upper-left X"`
|
||
|
yline=`xwininfo -name "$windowname" | grep "Absolute upper-left Y"`
|
||
|
widthline=`xwininfo -name "$windowname" | grep "Width:"`
|
||
|
heightline=`xwininfo -name "$windowname" | grep "Height:"`
|
||
|
xval=`echo "$xline" | cut -f 7 -d " "`
|
||
|
yval=`echo "$yline" | cut -f 7 -d " "`
|
||
|
# width and height need to be multiples of 2
|
||
|
widthval=`echo "$widthline" | cut -f 4 -d " "`
|
||
|
if [[ `expr $widthval % 2` -eq 1 ]]; then
|
||
|
widthval=`expr $widthval + 1`
|
||
|
fi
|
||
|
heightval=`echo "$heightline" | cut -f 4 -d " "`
|
||
|
if [[ `expr $heightval % 2` -eq 1 ]]; then
|
||
|
heightval=`expr $heightval + 1`
|
||
|
fi
|
||
|
resolution="${widthval}x${heightval}"
|
||
|
offset="+${xval},${yval}"
|
||
|
fi
|
||
|
|
||
|
echo "Press Ctrl+C to stop recording\n" >& 2
|
||
|
|
||
|
BASE="\
|
||
|
-hide_banner \
|
||
|
-loglevel error \
|
||
|
-thread_queue_size 512 \
|
||
|
-threads $threads"
|
||
|
|
||
|
VIDEO="-video_size $resolution \
|
||
|
-thread_queue_size 512 \
|
||
|
-f x11grab \
|
||
|
-i $DISPLAY$offset \
|
||
|
-r $framerate \
|
||
|
-c:v $videocodec \
|
||
|
-vb ${bitrate}k \
|
||
|
-minrate ${bitrate}k \
|
||
|
-maxrate ${bitrate}k \
|
||
|
-bufsize ${bufsize}k \
|
||
|
-preset ultrafast \
|
||
|
-vf "${scaleres}format=yuv420p" \
|
||
|
-g $gop \
|
||
|
-keyint_min $framerate"
|
||
|
|
||
|
AUDIOMERGE="volume=$volume_mic,aformat=channel_layouts=stereo$hilopass[l];[1]volume=$volume_mon,aformat=channel_layouts=stereo[m];[l][m]amix=inputs=2[a]"
|
||
|
|
||
|
# if no mic (= no -m), only record from snd/0.mon
|
||
|
# and the only filter is aresample=async=1
|
||
|
|
||
|
if [ $noaudio -lt 1 -a $mic -lt 1 ]; then
|
||
|
#only monitoring stream
|
||
|
ffmpeg $BASE -f sndio -i snd/mon -c:a aac -f nut pipe:1 | \
|
||
|
ffmpeg $BASE -f nut -itsoffset $audiooffset -i pipe:0 $VIDEO -c:a copy -f "${container}" "$filename"
|
||
|
elif [ $noaudio -lt 1 ]; then
|
||
|
#mon + mic stream
|
||
|
ffmpeg $BASE -thread_queue_size 512 -f sndio -i "$mic_device" \
|
||
|
-thread_queue_size 512 -f sndio -i snd/mon \
|
||
|
-filter_complex "[0]${AUDIOMERGE}" -map '[a]' -c:a aac -f nut pipe:1 | \
|
||
|
ffmpeg $BASE -thread_queue_size 512 -f nut -itsoffset $audiooffset -i pipe:0 $VIDEO -c:a copy -f "${container}" "$filename"
|
||
|
else
|
||
|
#no audio
|
||
|
ffmpeg $BASE $VIDEO -f "${container}" "$filename"
|
||
|
fi
|