243e556821019c58e8918b262bdac7c40d9fd648
[experiments/gstreamer.git] / shell / gst-screencast.sh
1 #!/bin/sh
2 #
3 # gst-screencast - screencasting of a window using GStreamer
4 #
5 # Copyright (C) 2015-2017  Antonio Ospite <ao2@ao2.it>
6 #
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 2 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20 set -e
21
22 usage() {
23   cat <<EOF
24 usage: $(basename $0) [OPTIONS] <output_file> [<ximagesrc_options>]
25
26 Screencast script based on GStreamer.
27
28 Options:
29   --audio         record audio from pulsesrc
30   --frame         include the window manager border, without the shadows
31   --pointer       capture the mouse pointer
32   --single-shot   capture a single snapshot as a PNG instead of a video
33   -h, --help      display this usage message and exit
34
35 EOF
36 }
37
38 CAPTURE_AUDIO=0
39 WINDOW_FRAME=0
40 SHOW_POINTER=0
41 SINGLE_SHOT=0
42
43 while [ $# -gt 0 ];
44 do
45   case "$1" in
46     -h|--help)
47       usage
48       exit 0
49       ;;
50     --audio)
51       CAPTURE_AUDIO=1
52       ;;
53     --frame)
54       WINDOW_FRAME=1
55       ;;
56     --pointer)
57       SHOW_POINTER=1
58       ;;
59     --single-shot)
60       SINGLE_SHOT=1
61       ;;
62     -*)
63       echo "Error: Unknown option '${1}'" 1>&2
64       ;;
65     *)
66       break;
67   esac
68   shift
69 done
70
71 [ "x" = "x$1" ] && { usage 1>&2; exit 1; }
72
73 [ -f "$1" ] && { echo "Error: file '${1}' already exists!" 1>&2; exit 2; }
74
75 FILENAME="$1"
76
77 if [ "x" = "x$2" ];
78 then
79   SHADOW_SIZE=0
80   SHADOW_X_OFFSET=0
81   SHADOW_Y_OFFSET=0
82   if [ $WINDOW_FRAME -eq 1 ];
83   then
84     XWININFO_OPTIONS="-frame"
85
86     # XXX the values below are still hardcoded, they may be different
87     # depending on the theme and the window manager.
88     SHADOW_SIZE=26
89     SHADOW_X_OFFSET=0
90     SHADOW_Y_OFFSET=3
91   fi
92
93   WIN_INFO="$(xwininfo $XWININFO_OPTIONS)"
94
95   X=$(echo "$WIN_INFO" | sed -n -e "/^[[:space:]]*Absolute upper-left X:[[:space:]]*/s///p")
96   Y=$(echo "$WIN_INFO" | sed -n -e "/^[[:space:]]*Absolute upper-left Y:[[:space:]]*/s///p")
97   WIDTH=$(echo "$WIN_INFO" | sed -n -e "/^[[:space:]]*Width:[[:space:]]*/s///p")
98   HEIGHT=$(echo "$WIN_INFO" | sed -n -e "/^[[:space:]]*Height:[[:space:]]*/s///p")
99
100   XIMAGESRC_ARGS="startx=$(($X + $SHADOW_SIZE - $SHADOW_X_OFFSET)) starty=$(($Y + $SHADOW_SIZE - $SHADOW_Y_OFFSET)) endx=$(($X + $WIDTH - 1 - $SHADOW_SIZE - $SHADOW_X_OFFSET)) endy=$(($Y + $HEIGHT - 1 - $SHADOW_SIZE - $SHADOW_Y_OFFSET))"
101 else
102   XIMAGESRC_ARGS="$2"
103 fi
104
105 if [ $SINGLE_SHOT -eq 1 ];
106 then
107   gst-launch-1.0 -v \
108     ximagesrc use-damage=0 show-pointer=$SHOW_POINTER $XIMAGESRC_ARGS num-buffers=1 ! \
109     videoconvert ! pngenc ! filesink location="$FILENAME"
110 else
111   VIDEO_CODEC="video/x-raw,format=I420 ! jpegenc quality=90"
112
113   if [ $CAPTURE_AUDIO -eq 1 ];
114   then
115     AUDIO_PIPELINE="pulsesrc ! audioconvert ! audio/x-raw,rate=44100,channels=2 ! queue ! mux."
116   fi
117
118   gst-launch-1.0 -v \
119     matroskamux name=mux ! filesink location="$FILENAME" \
120     ximagesrc use-damage=0 show-pointer=$SHOW_POINTER $XIMAGESRC_ARGS ! video/x-raw,framerate=25/1 ! \
121     videoconvert ! videorate ! $VIDEO_CODEC ! queue ! mux. \
122     $AUDIO_PIPELINE
123 fi