Dropped legacy gstreamer-0.10 stuff, added check for aac encoder
[einar-bin] / screencast.sh
index f1a26687a51065a4686fbb9fa06d22c3e6af342b..7a06a8cc7e304e73bf0792a3f0bd8d4be88c3957 100755 (executable)
@@ -1,24 +1,40 @@
 #!/bin/bash
 #!/bin/bash
-# WARNING: This is a terribly dirty and messy shellscript, written over a couple of late nights
-# There was alcohol
-# You probably need to install all the gstreamer-plugins (at least -ugly and -ffmpeg) to get this to work
-# I wanted to make mp4 with x264, I didn't bother with free codecs
-
-# This script allows you to create screencasts on Linux, with optional sound inputs (both Mic and system sounds)
-# You also get to choose to record from the whole screen or just a specified window. It has only been tested
-# on Fedora 18.
 
 
+# WARNING: This is a terribly dirty and messy shellscript, written over a
+# couple of late nights. There was alcohol …
+# You probably need to install all the gstreamer-plugins (at least -ugly
+# and -ffmpeg) as well as gstreamer-tools to get this to work. I wanted to
+# make mp4 files with x264, I didn't bother with free codecs.
+#
+# So this script allows you to create screencasts on Linux, with optional
+# sound inputs (both Microphone and system sounds). It stores system sounds
+# and microphone in separate audio streams.
+#
+# You also get to choose to record from the whole screen or just a specified
+# window. It has been tested on Fedora 18, Ubuntu 13.04 and CrunchBang Waldorf
+# (and thus should work on Debian Wheezy as well).
+#
+# It dumps the recording in your $HOME directory with a filename like
+# screencast-YYYY-MM-DD-HH-MM-SS.mp4
+#
 # Written by Einar Jørgen Haraldseid (http://einar.slaskete.net)
 # License: http://sam.zoy.org/wtfpl/COPYING
 
 # Written by Einar Jørgen Haraldseid (http://einar.slaskete.net)
 # License: http://sam.zoy.org/wtfpl/COPYING
 
-# Get device names and pretty names for playback sinks:
-PLAYSINKLIST=$(pacmd list-sinks | grep -e "name: " -e "device.description = " | cut -d " " -f "2-" | sed -e "s/name: \|= //g" -e "s/<\|>\|\x22//g")
+# Get device names and pretty names for enumerating playback sinks:
+PLAYSINKLIST=$(pacmd list-sinks | \
+ grep -e "name: " -e "device.description = " | cut -d " " -f "2-" | \
+ sed -e "s/name: \|= //g" -e "s/<\|>\|\x22//g")
 
 # Display playback monitor chooser
 PLAYMON=$(echo "${PLAYSINKLIST}
 none
 
 # Display playback monitor chooser
 PLAYMON=$(echo "${PLAYSINKLIST}
 none
-Don't capture system sounds" | zenity --list --title "Choose Output Device" --text "Choose a sound device to capture system sound from:" --column "device" --column "Name" --print-column=1 --hide-column=1 2>/dev/null)
+Don't capture system sounds" | \
+ zenity --list --title "Choose Output Device" \
+ --text "Choose a sound device to capture system sound from:" \
+ --column "device" --column "Name" --print-column=1 \
+ --hide-column=1 2>/dev/null)
 
 
+# Catch cancel
 if [ -z ${PLAYMON} ]; then
   echo "No choice made on output device, assuming cancel."
   exit 1
 if [ -z ${PLAYMON} ]; then
   echo "No choice made on output device, assuming cancel."
   exit 1
@@ -27,28 +43,47 @@ fi
 if [ ${PLAYMON} != "none" ]; then
   # Unmute monitor of the playback sink (if set):
   PLAYMON="${PLAYMON}.monitor"
 if [ ${PLAYMON} != "none" ]; then
   # Unmute monitor of the playback sink (if set):
   PLAYMON="${PLAYMON}.monitor"
-
   pacmd set-source-mute ${PLAYMON} false >/dev/null
   pacmd set-source-mute ${PLAYMON} false >/dev/null
+  echo "Recording system sounds from ${PLAYMON}"
+else
+  echo "Not recording system sounds."
 fi
 
 # Get device names and pretty names for microphones:
 fi
 
 # Get device names and pretty names for microphones:
-MICLIST=$(pacmd list-sources | grep -e "name: " -e "device.description = " | grep -v -i "monitor" | cut -d " " -f "2-" | sed -e "s/name: \|= //g" -e "s/<\|>\|\x22//g")
+MICLIST=$(pacmd list-sources | \
+ grep -e "name: " -e "device.description = " | \
+ grep -v -i "monitor" | cut -d " " -f "2-" | \
+ sed -e "s/name: \|= //g" -e "s/<\|>\|\x22//g")
 
 # Display device chooser
 MIC=$(echo "${MICLIST}
 none
 
 # Display device chooser
 MIC=$(echo "${MICLIST}
 none
-Don't use a microphone" | zenity --list --title "Choose Microphone" --text "Choose a microphone to capture voice from:" --column "device" --column "Name" --print-column=1 --hide-column=1 2>/dev/null)
+Don't use a microphone" | \
+ zenity --list --title "Choose Microphone" \
+ --text "Choose a microphone to capture voice from:" \
+ --column "device" --column "Name" --print-column=1 \
+ --hide-column=1 2>/dev/null)
 
 if [ -z ${MIC} ]; then
   echo "No choice made on microphone, assuming cancel."
   exit 1
 
 if [ -z ${MIC} ]; then
   echo "No choice made on microphone, assuming cancel."
   exit 1
-fi 
+fi
+
+if [ ${MIC} != "none" ]; then
+  echo "Recording voice from ${MIC}"
+else
+  echo "Not recording voice."
+fi
 
 # Get target window for recording:
 TARGET=$(echo "root
 Whole screen
 window
 
 # Get target window for recording:
 TARGET=$(echo "root
 Whole screen
 window
-Specific window" | zenity --list --title "Choose recording mode" --text "Do you want to record the whole screen, or record a specific window?" --column "target" --column "Mode" --print-column=1 --hide-column=1 2>/dev/null)
+Specific window" | \
+ zenity --list --title "Choose recording mode" \
+ --text "Do you want to record the whole screen,\
+ or record a specific window?" --column "target" \
+ --column "Mode" --print-column=1 --hide-column=1 2>/dev/null)
 
 if [ -z ${TARGET} ]; then
   echo "No choice for recording target, assuming cancel."
 
 if [ -z ${TARGET} ]; then
   echo "No choice for recording target, assuming cancel."
@@ -56,32 +91,49 @@ if [ -z ${TARGET} ]; then
 fi
 
 if [ ${TARGET} = "root" ]; then
 fi
 
 if [ ${TARGET} = "root" ]; then
-  echo "Root chosen"
+  echo "Root window chosen."
   XWININFO=$(xwininfo -root)
 else
   XWININFO=$(xwininfo -root)
 else
-  echo "custom chosen"
+  echo "Custom window chosen."
   XWININFO=$(xwininfo)
 fi
 
   XWININFO=$(xwininfo)
 fi
 
-# Get Window ID and dimensions, make sure dimensions are divisible by two, or else the encoder will fail
+# Get Window ID and dimensions, make sure X and Y dimensions are
+# divisible by two, or else the encoder will fail
 WID=$(echo "${XWININFO}" | grep "Window id:" | awk '{print $4}')
 WID=$(echo "${XWININFO}" | grep "Window id:" | awk '{print $4}')
-WIDTH=$(echo "${XWININFO}" | grep "Width: " | cut -d ":" -f 2 | awk '{print $1+$1%2}')
-HEIGHT=$(echo "${XWININFO}" | grep "Height: " | cut -d ":" -f 2 | awk '{print $1+$1%2}')
+WIDTH=$(echo "${XWININFO}" | grep "Width: " | \
+ cut -d ":" -f 2 | awk '{print $1+$1%2}')
+HEIGHT=$(echo "${XWININFO}" | grep "Height: " | \
+ cut -d ":" -f 2 | awk '{print $1+$1%2}')
 
 # Calculate a suitable bitrate based on window dimensions
 
 # Calculate a suitable bitrate based on window dimensions
-BITRATE=$(echo "${WIDTH} * ${HEIGHT} * 0.006" | bc | cut -d "." -f 1 )
+BITRATE=$(echo "${WIDTH} * ${HEIGHT} * 0.0075" | bc | cut -d "." -f 1 )
+
+# Set file name.
+FILENAME="screencast-$(date +%F-%H-%M-%S).mp4"
+
+# Determine if we have ffenc_aac or avenc_aac available
+AACENC="ffenc_aac"
+if gst-inspect-1.0 --exists avenc_aac; then 
+  AACENC="avenc_aac"
+fi
 
 # Enable inputs as suitable
 if [ ${PLAYMON} != "none" ]; then
 
 # Enable inputs as suitable
 if [ ${PLAYMON} != "none" ]; then
-  MONITORARG="pulsesrc device=${PLAYMON} slave-method=0 provide-clock=false ! audiorate ! audioconvert ! ffenc_aac bitrate=256000 ! queue2 ! mux."
+  MONITORARG="pulsesrc device=${PLAYMON} slave-method=0 provide-clock=false \
+   ! audiorate ! audioconvert ! ${AACENC} bitrate=256000 ! queue2 ! mux."
 fi
 if [ ${MIC} != "none" ]; then
 fi
 if [ ${MIC} != "none" ]; then
-  MICARG="pulsesrc device=${MIC} slave-method=0 provide-clock=false ! audiorate ! audioconvert ! ffenc_aac bitrate=256000 ! queue2 ! mux."
+  MICARG="pulsesrc device=${MIC} slave-method=0 provide-clock=false \
+   ! audiorate ! audioconvert ! ${AACENC} bitrate=256000 ! queue2 ! mux."
 fi
 
 # Launch gstreamer
 fi
 
 # Launch gstreamer
-gst-launch -e ximagesrc xid="${WID}" do-timestamp=1 use-damage=0 ! video/x-raw-rgb,framerate=30/1 \
- ! ffmpegcolorspace ! videoscale method=0 ! video/x-raw-yuv,width=${WIDTH},height=${HEIGHT} \
- ! x264enc speed-preset=ultrafast bitrate=${BITRATE} ! queue2 \
- ! mp4mux name="mux" ! filesink location="output.mp4" $MONITORARG $MICARG
-
+gst-launch-1.0 -q -e ximagesrc xid="${WID}" do-timestamp=1 use-damage=0 \
+ ! video/x-raw,framerate=30/1 ! videoscale method=0 \
+ ! video/x-raw,width=${WIDTH},height=${HEIGHT} ! videoconvert \
+ ! x264enc speed-preset=veryfast bitrate=${BITRATE} ! queue2 \
+ ! mp4mux name="mux" \
+ ! filesink location="${HOME}/${FILENAME}" ${MONITORARG} ${MICARG}
+
+echo "Recording done, file is ${FILENAME}"