Last active
March 1, 2019 22:53
-
-
Save AntumDeluge/b5fe34c3ae1e0ebef1ae63794c796a67 to your computer and use it in GitHub Desktop.
Shell script for recording my desktop with FFmpeg (X11).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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