Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Shell script for recording my desktop with FFmpeg (X11).
#!/bin/bash
# This script is specific to my local machine. Many of the options may need
# to be changed to work on different systems.
#
# Licensing: CC0
# check if necessary executables are available
FFMPEG=$(which ffmpeg)
XWIN=$(which xwininfo)
if [ -z "${FFMPEG}" ]; then
echo -e "\nERROR: FFmpeg executable not found"
exit 1
else
echo "FFmpeg executable: ${FFMPEG}"
fi
if [ -z "${XWIN}" ]; then
echo -e "\nERROR: xwininfo executable not found"
exit 1
else
echo "xwininfo executable: ${XWIN}"
fi
# command line options
# framerate
FPS=30
# use "-nomouse" option to hide cursor
MOUSE=1
# video/audio recording
ENABLE_VIDEO=1
ENABLE_AUDIO=1
# determintes whether audio log will be deleted after successful recording
RM_LOGAUD=1
for OPT in $@; do
if [ "${OPT}" == "-nomouse" ]; then
MOUSE=0
elif [ "${OPT}" == "-mic" ]; then
MIC=1
elif [ "${OPT}" == "-nv" ]; then
ENABLE_VIDEO=0
elif [ "${OPT}" == "-na" ]; then
ENABLE_AUDIO=0
elif [ "${OPT}" == "-logaudio" ]; then
RM_LOGAUD=0
elif [ "${OPT}" == "-list_audio" ]; then
echo "Pulseaudio device names:"
pactl list sources | grep "Name:"
exit 0
fi
done
if [ "${ENABLE_VIDEO}" -eq "0" ] && [ "${ENABLE_AUDIO}" -eq "0" ]; then
echo -e "\nERROR: Cannot use \"-nv\" and \"-na\" together. Must include at leaset one video or audio stream"
exit 1
fi
# find fullscreen resolution
RES=$(xwininfo -root | grep "\-geometry" | cut -d " " -f 4- | cut -d "+" -f -1)
echo "Resolution: ${RES}"
# output
MS=$(date +"%N" | cut -c -3)
TIMESTAMP=$(date +"%F_%H.%M.%S.")${MS}
OUTDIR="${HOME}/Videos/ScreenRecords"
OUTNAME="capture_${TIMESTAMP}"
OUTVID="${OUTDIR}/${OUTNAME}-video.mkv"
OUTAUD="${OUTDIR}/${OUTNAME}-audio.mka"
LOGAUD="${OUTDIR}/${OUTNAME}-audio.log"
LOGMUX="${OUTDIR}/${OUTNAME}-mux.log"
OUTFILE="${OUTDIR}/${OUTNAME}.mkv"
echo -e "\nOutputting to ${OUTFILE}"
# make sure target directory is not a file
if [ -f "${OUTDIR}" ]; then
echo -e "\nERROR: Cannot create target directory ${OUTDIR}, file exists"
exit 1
fi
# create target directory if it does not exist
if [ ! -d "${OUTDIR}" ]; then
echo
mkdir -vp "${OUTDIR}"
fi
# set FFmpeg constant values
FFMPEG="${FFMPEG} -hide_banner"
# empty line before FFmpeg output
echo
# audio input devices
AUDSYS=alsa_output.pci-0000_00_1b.0.analog-stereo.monitor
AUDMIC=alsa_input.pci-0000_00_1b.0.analog-stereo
AUDWC=alsa_input.usb-046d_09a1_62318550-02.analog-mono
if [ "${ENABLE_AUDIO}" -gt "0" ]; then
if [ ! -z "${MIC}" ]; then
echo "Capturing audio from microphone"
AUDIN=${AUDMIC}
else
echo "Capturing audio from system"
AUDIN=${AUDSYS}
fi
# capture audio
${FFMPEG} -rtbufsize 500M -f pulse -channels 1 -sample_rate 44100 -i ${AUDIN} -vn -c:a aac -strict -2 -b:a 128k -ac 1 "${OUTAUD}" > "${LOGAUD}" 2>&1 & APID=$!
fi
# TODO: disable video of -vn specified
# capture video
${FFMPEG} -rtbufsize 500M -probesize 100M -f x11grab -framerate ${FPS} -draw_mouse ${MOUSE} -s ${RES} -i :0.0 -an -c:v mpeg4 -vtag xvid -qscale:v 0 "${OUTVID}"
VEXIT=$?
if [ "${ENABLE_AUDIO}" -gt "0" ]; then
# end audio capture
kill -s SIGINT ${APID}
AEXIT=$?
fi
if [ "${VEXIT}" -ne "0" ]; then
echo -e "\nERROR: Video capture exited with code: ${VEXIT}"
exit ${VEXIT}
else
echo -e "\nVideo capture terminted successfully"
fi
if [ "${ENABLE_AUDIO}" -gt "0" ]; then
if [ "${AEXIT}" -ne "0" ]; then
echo -e "\nERROR: Audio capture exited with code: ${AEXIT}"
echo -e "Check ${LOGAUD} for FFmpeg audio capture log"
exit ${AEXIT}
else
echo -e "\nAudio capture terminated successfully"
if [ "${RM_LOGAUD}" -gt "0" ]; then
echo -e "\nRemoving audio log"
rm -f "${LOGAUD}"
fi
fi
# mux video & audio
echo -e "\nMuxing video with audio ..."
MAPPING="-map 0:0 -map 1:0"
${FFMPEG} -i "${OUTVID}" -i "${OUTAUD}" ${MAPPING} -c copy "${OUTFILE}" > "${LOGMUX}" 2>&1 & APID=$!
# wait for muxing to finish
wait ${APID}
MEXIT=$?
if [ "${MEXIT}" -ne "0" ]; then
echo -e "\nAn error occurred muxing video with audio"
exit ${MEXIT}
else
echo -e "\nVideo/Audio muxing finished successfully"
rm -f "${LOGMUX}"
fi
# remove video & audio independent stream
rm -f "${OUTVID}" "${OUTAUD}"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.