Du screencast sous GNU/Linux partie 3
Une solution m’est apparue : ffmpeg, que j’avais dénigré jusqu’ici, est en réalité la meilleure façon de faire un screencast sous GNU/Linux. Qualité vidéo irréprochable, post-traitement (dont une conversion en mp4 HD pour Youtube…), enregistrement des sons et du micro en parallèle, et la cerise sur le gâteau : tout est en ligne de commande.
Je me suis servi du script screencaster disponible
ici sous licence GPL en le
mixant un peu à ma sauce. Il reste donc sous licence GPL, mais n’a été testé
que sous Ubuntu et dérivées jusqu’à présent. À ce titre, il nécessite
libavcodec-extra-52 , mais aussi ffmpeg du dépôt Medibuntu. Le reste des
dépendances s’installe d’un simple sudo apt-get install xdpyinfo grep head sed pacat parec sox
.
Quant à l’utilisation, il suffit de le lancer avec l’option -h
pour
comprendre assez rapidement. L’option -w
fait apparaitre un curseur, il n’y
a plus qu’à cliquer sur la fenêtre de votre choix pour lancer
l’enregistrement. Terminez alors l’enregistrement en tapant Entrée
. Il
existe une petite astuce pour éviter d’avoir à revenir sur la console pour
arrêter l’enregistrement, et donc devoir couper la vidéo en post-prod : on
peut arrêter l’enregistrement en configurant un raccourci clavier et en
utilisant xdotool : xdotool search --onlyvisible --classname "gnome-terminal" key "Return"
.
#!/bin/bash
#
# screencaster.sh - script to make screencasts on Linux
#
# For information about using this script:
# http://www.guillaume.litaudon.fr/blog/
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 3, as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranties of
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
# PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
# list of programs we depend on
progs="xdpyinfo grep head sed ffmpeg pacat parec sox"
# check for programs we depend on
result=0
for prog in $progs
do
type -p $prog > /dev/null
if (( $? != 0 )); then
echo "Error: Cannot find required program '$prog'"
result=1
fi
done
if (( $result != 0 )); then
exit 1
fi
screenSize="$(xwininfo -root | grep 'geometry' | awk '{print $2;}')" # default if we cant detect it
screenOffset="0,0" # default to top-left corner
frameRate="24" # default frame rate
baseName="`date +%Y%m%d`-`date +%H%M%S`-screencast" # default base filename for capture
# attempt to detect the dimension of the screen for the default
dimensions=`xdpyinfo | grep 'dimensions:' | head -1 | \
sed -e 's/^.* \([0-9]\+x[0-9]\+\) pixels.*$/\1/'`
if [[ "$dimensions" =~ [0-9]+x[0-9]+ ]]; then
screenSize=$dimensions
fi
# collect command line settings
while getopts 'hs:o:t:r:p:w' param ; do
case $param in
s)
screenSize="$OPTARG"
;;
o)
screenOffset="$OPTARG"
;;
t)
timeToRecord="$OPTARG"
;;
w)
INFO=$(xwininfo)
WIN_GEO=$(echo $INFO | grep -oEe 'geometry [0-9]+x[0-9]+' | grep -oEe '[0-9]+x[0-9]+')
WIN_XY=$(echo $INFO | grep -oEe 'Corners:\s+\+[0-9]+\+[0-9]+' | grep -oEe '[0-9]+\+[0-9]+' | sed -e 's/\+/,/' )
screenOffset="$WIN_XY"
screenSize="$WIN_GEO"
;;
r)
frameRate="$OPTARG"
;;
*)
echo ""
echo "$0 - records screencast"
echo ""
echo "$0 [options] [base-filename]"
echo ""
echo "options:"
echo " -h show brief help"
echo " -s <size> screensize to record as <width>x<height>"
echo " -o <offset> offset off recording area as <xoffset>,<yoffset>"
echo " -t <time> time to record (in seconds)"
echo " -w window to record"
echo " -r framerate (FPS)"
echo ""
exit 0
;;
esac
done
shift $(( $OPTIND - 1 ))
# determine basename of files
if [ -n "$1" ] ; then
baseName="$1"
fi
echo ""
echo "Size = $screenSize"
echo "Offset = $screenOffset"
echo "Rate = $frameRate"
echo "Filename = $baseName"
# get ready to start recording
echo ""
if [ -n "$timeToRecord" ]; then
echo "Preparing to capture for $timeToRecord seconds."
else
echo "Preparing to capture."
echo "Press ENTER when finished capturing."
fi
sleep 3
echo ""
# start playing silence to make sure there is always audio flowing
pacat /dev/zero &
pidSilence=$!
# starts recording video using x11grab to make mpeg2video
ffmpeg -f alsa -ac 2 -i pulse \
-f x11grab -r "$frameRate" -s "$screenSize" -i :0.0+"$screenOffset" \
-acodec pcm_s16le -vcodec libx264 -vpre lossless_ultrafast \
-threads 0 -y "$baseName.mkv" &
pidVideo=$!
#ffmpeg -y -an \
# -s "$screenSize" -r "$frameRate" -f x11grab -i :0.0+"$screenOffset" \
# -s "$screenSize" -r "$frameRate" -aspect 4:3 -vcodec mpeg2video -sameq \
# -f mpeg2video "$baseName.mpeg" &
#pidVideo=$!
# starts recording raw audio
parec -d alsa_output.pci-0000_00_1b.0.analog-stereo.monitor --format=s16le --rate=44100 --channels=2 "$baseName.raw" &
pidAudio=$!
echo ""
echo "Video recording started with process ID $pidVideo"
echo "Audio recording started with process ID $pidAudio"
echo ""
# wait for recording to be done, either by timer or user hitting enter
if [ -n "$timeToRecord" ]; then
sleep "$timeToRecord"
else
read nothing
fi
# stop recordings
echo ""
echo "Terminating recordings ..."
kill -15 $pidVideo $pidAudio
kill -15 $pidSilence
wait
# filter and normalize the audio
echo ""
echo "Filtering and normalizing sound ..."
sox --norm -s -b 16 -L -r 44100 -c 2 -v 0.33 "$baseName.raw" "$baseName.wav" highpass 65 lowpass 12k
# Récupère le son du microphone
echo ""
echo "Extract audio from mkv"
ffmpeg -i "$baseName.mkv" -ar 44100 -ac 2 "$baseName-2.wav"
# encode video and audio into mp4 file
echo ""
echo "Encoding to final Youtube format..."
sox "$baseName.wav" "$baseName-2.wav" -m -p gain | ffmpeg -f sox -i - -i "$baseName.mkv" -s 1280x720 -aspect 16:9 -vcodec libx264 -vpre fast -crf 18 -threads 0 -acodec libfaac -ab 320k -y "$baseName.mp4"
#ffmpeg -isync -i "$baseName.wav" -i "$baseName.mpeg" -acodec mp2 -ab 192k -vcodec copy "$baseName.avi"
# convert to ogg - to turn on uncomment next three lines
#echo""
#echo "convert to theora"
#ffmpeg2theora "$baseName.avi" -o "$baseName.ogv"
# convert avi to flv - to turn on uncomment next three lines
#echo""
#echo "convert to theora"
# ffmpeg -i "$baseNamee.avi" -ab 56 -ar 44100 -b 200 -r 15 -s 320x240 -f flv "$baseNamee.flv"
echo ""
echo "DONE! Final media written in file $baseName.mp4"
echo ""
exit 0