Skip to content

Practical Usage Tips

Daniel Bermond edited this page Sep 11, 2020 · 21 revisions

Rationale

Of course you can use screencast by just typing the command at a terminal window, and finish the recording by pressing the q key on it. But this is not too much productive, specially if you use the same recording settings and make many videos.

Is there a better way to use screencast other than manually typing the commands at a terminal window?

A better approach would be to bind keyboard hotkeys to predefined screencast commands, allowing recordings to be a fast and no-typing experience. But a direct hotkey binding would make the screencast output to be not displayed, since it would not be running in a proper terminal window. Also, there would be no terminal window opened for pressing the q key to finish the recording.

So, using keyboard hotkeys with screencast can be useful, but not directly as we have seen. The following sections will present methods for using keyboard hotkeys with screencast.

Using xdotool

The xdotool utility can send commands to be typed in opened windows and also send keystrokes, working even if the target terminal window is minimized to the taskbar or inactive. In this way, we can use keyboard hotkeys, while retaining the terminal output and the ability to send a q keystroke to finish, with the convenience of hiding the terminal output from the recorded video.

Here is an example using Plasma desktop and the Konsole terminal application with the bash shell:

  1. create a shell script file with this:
    • a xdotool command to make the sc script (shown in step 2) to be executed in an opened Konsole terminal window
    • a xdotool command to send the q keystroke to an opened Konsole terminal window
    • name this file scxdo, make it executable (chmod a+x) and put it in your PATH (for convenience, here it is created as accepting -s option to start recording and -f option to finish recording)
#!/bin/sh

# scxdo - send screencast commands to a konsole terminal window
#
# Copyright (c) 2015-2020 Daniel Bermond < gmail.com: danielbermond >
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY 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/>.

if [ "$#" -ne '1' ] 
then
    printf '%s\n' "error: invalid usage (please use one argument: '-s' or '-f')"
    exit 1
fi

while getopts :sf FLAG
do
    case "$FLAG" in
        # start screencast recording (send command to terminal window)
        s)
            # using xdotool 'key' command + auxiliary script from step 2 is a hack
            # (see notes bellow)
            for key in s c 0xFF0D
            do
                xdotool search --name ': bash' key --delay 0 --clearmodifiers "$key"
            done
            ;;
        # finish screencast recording (send 'q' keystroke to terminal window)
        f)
            xdotool search search --name ': sc' key --delay 0 --clearmodifiers q
            ;;
        *)
            printf '%s\n' "error: invalid option '${FLAG}'"
            exit 1
            ;;
    esac
done

shift "$((OPTIND - 1))"
  1. create an auxiliary shell script file with your desired screencast command. Name this file sc, make it executable (chmod a+x) and put it in your PATH. This is actually a hack to make it work on most systems. See notes bellow.
#!/bin/sh

screencast -p 200,234 -s 1280x720 -m 1.5 -w www.mysitehere.com -g optipng -u -o /home/user/Videos
  1. create two keyboard hotkeys in System Settings -> Shortcuts -> Custom Shortcuts -> <right click> -> New -> Global Shortcut -> Command/URL:
    • one for start recording, using the command scxdo -s
    • one for finish recording, using the command scxdo -f

That's it. Ready to go!

Now, suppose that your hotkey bindings to start and finish recording are Ctrl+F2 and Ctrl+F3 respectively:

  • open a Konsole terminal window (it works even with a minimized and inactive Konsole window)
  • press Ctrl+F2 to start recording with your predefined screencast command from the sc file
  • press Ctrl+F3 to finish recording

Notes about the xdotool method

  • for using other terminal applications, change ': bash' in search --name (step 1) to something else that matches your terminal.
  • you can have multiple predefined screencast recording settings with this approach, each one linked to a different hotkey. Just create more case clauses in script from step 1, create more auxiliary scripts like the one in step 2 and create more keyboard hotkeys in your Desktop Environment.
  • xdotool has also the type command to send complete commands directly. It may work for you / your Desktop Environment, but it does not work for me. To be honest, it works, but only if the Konsole window is active/focused, which is not desired in most recording situations. It does not work with the Konsole window minimized or inactive. Anyway, if you use it, modify the script in step 1 to use it and do not use the auxiliary script from step 2. The solution presented here uses an auxiliary script and the xdotool key command as a hack for it to work properly.

Using a named pipe (FIFO)

Named pipes can be used for communication between processes. Differently from the xdotool method, it allows to create keyboard hotkeys without the need of an opened terminal window. The screencast log can still be seen through a log file.

Here is an example on how this can be done.

  1. Create a shell script with the contents below, name it accordingly to scfifo, make it executable (chmod a+x) and put it in your PATH.
#!/bin/sh

# scfifo - start and stop screencast through a fifo
#
# Copyright (c) 2020 Daniel Bermond < gmail.com: danielbermond >
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY 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/>.

#########################################
#           general settings            #
#########################################

SC_OPTIONS="${SC_OPTIONS:-"-u"}"
SC_FIFO="${SC_FIFO:-"${HOME}/.scfifo"}"

notifications='true'
error_icon='dialog-error'
expire_time_long='5000' # expire time for long notifications

#########################################
#              functions                #
#########################################

cleanup() {
    if [ "$SC_ACTION" = 'quit' ] && [ -p "$SC_FIFO" ]
    then
        rm -f "$SC_FIFO"
        printf '%s\n' "${0##*/}: FIFO '${SC_FIFO}' removed"
    fi
}

notify() {
    if [ "$notifications" = 'true' ]
    then
        notify-send --urgency="$1" --expire-time="$2" --icon="$3" \
            "${0##*/}" "$4"
    fi
}

command_error() {
    exit_program "${1} option requires an argument"
}

exit_program() {
    printf '%s\n' "${0##*/}: ${1}" >&2
    notify 'critical' "$expire_time_long" "$error_icon" "error: ${1}"
    exit 1
}

show_usage() {
    cat <<- __EOF__
		Usage: ${0##*/} -a <action> [options]
		For further help run '${0##*/} --help'
__EOF__
}

show_help() {
    cat <<- __EOF__
		screencast FIFO controller - Copyright (c) 2020-$(date +%Y) Daniel Bermond
		https://github.com/dbermond/screencast/
		
		Usage: ${0##*/} -a <action> [options]
		
		Options:
		  -a, --action=ACTION     action to send to screencast through the FIFO
		  -f, --fifo=FILE         the FIFO file to be created [${HOME}/.scfifo]
		  -h, --help              this help screen
		  -l, --logfile=FILE      log screencast output to FILE [disabled]
		  -n, --no-notifications  disable desktop notifications of this script
		  -o, --sc-options=OPTS   options to be passed to screencast [-u]
		
		Actions:
		  start  start screencast recording
		  quit   finish screencast recording (aliases: finish, stop)
		
		note: the action, FIFO file, log file and screencast options can be
		      defined with the SC_ACTION, SC_FIFO, SC_LOG and SC_OPTIONS
		      environment variables respectively. Command line options takes
		      precedence.
		
		note: when passing multiple options to screencast with --sc-options
		      (or SC_OPTIONS), do not forget to enclose them in quotes
__EOF__
}

get_cmd_line() {
    while :
    do
        case "$1" in
            # short option and long option without '='
            -a|--action)
                # search for an argument
                if [ -n "$2" ]
                then
                    # error out if no argument was entered after the option
                    # (will check for a leading '-' in the next parameter,
                    #  meaning that another option was found)
                    if printf '%.1s\n' "$2" | grep -q '-'
                    then
                        command_error '--action (-a)'
                    # error out if no argument is found
                    else
                        SC_ACTION="$2"
                        shift
                    fi
                else
                    command_error '--action (-a)'
                fi
                ;;
            # long option with '='
            --action=?*)
                SC_ACTION="${1#*=}" # assign value after '='
                ;;
            # error out if a long option with '=' has nothing following '='
            --action=)
                command_error '--action (-a)'
                ;;
            
            -f|--fifo)
                if [ -n "$2" ]
                then
                    if printf '%.1s\n' "$2" | grep -q '-'
                    then
                        command_error '--fifo (-f)'
                    
                    else
                        SC_FIFO="$2"
                        shift
                    fi
                else
                    command_error '--fifo (-f)'
                fi
                ;;
            --fifo=?*)
                SC_FIFO="${1#*=}"
                ;;
            --fifo=)
                command_error '--fifo (-f)'
                ;;
            
            -h|-\?|--help)  # option without argument
                show_help
                exit 0
                ;;
            
            -l|--logfile)
                if [ -n "$2" ]
                then
                    if printf '%.1s\n' "$2" | grep -q '-'
                    then
                        command_error '--logfile (-l)'
                    else
                        SC_LOG="$2"
                        shift
                    fi
                else
                    command_error '--logfile (-l)'
                fi
                ;;
            --logfile=?*)
                SC_LOG="${1#*=}"
                ;;
            --logfile=)
                command_error '--logfile (-l)'
                ;;
            
            -n|--no-notifications)  # option without argument
                notifications='false'
                ;;
            
            -o|--sc-options)
                if [ -n "$2" ]
                then
                    SC_OPTIONS="$2"
                    shift
                else
                    command_error '--sc-options (-o)'
                fi
                ;;
            --sc-options=?*)
                SC_OPTIONS="${1#*=}"
                ;;
            --sc-options=)
                command_error '--sc-options (-o)'
                ;;
            
            --) # check for the end of options marker '--'
                shift
                break
                ;;
            
            -?*=?*) # unknown option with '=', handle argument also with '='
                exit_program "unknown option '${1%%=*}'"
                ;;
            
            -?*=) # unknown option with '='
                exit_program "unknown option '${1%=*}'"
                ;;
            
            -?*)
                exit_program "unknown option '${1}'"
                ;;
            
            *)  # no more options left
                break
        esac
        
        shift
    done
}

check_requirements() {
    for requirement in screencast notify-send
    do
        if [ "$requirement" = 'notify-send' ] && [ "$notifications" = 'false' ]
        then
            continue
        fi
        
        if ! command -v "$requirement" >/dev/null 2>&1
        then
            printf '%s\n' "'${requirement}' is required but was not found"
            exit 1
        fi
    done
    
    unset -v requirement
}

start_sc() {
    if [ -p "$SC_FIFO" ]
    then
        other_sc_pids="$(ps -A | awk '!/awk/ && /[[:space:]]screencast$/ { print $1 }')"
        
        if [ -n "$other_sc_pids" ]
        then
            exit_program 'it looks like that screencast is already running'
        else
            printf '%s\n' "${0##*/}: warning: '${SC_FIFO}' already exists, removing it"
            rm -f "$SC_FIFO"
        fi
        
        unset -v other_sc_pids
    fi
    
    if ! mkfifo "$SC_FIFO"
    then
        exit_program "error while creating FIFO '${SC_FIFO}'"
    fi
    
    # shellcheck disable=SC2086
    if [ -n "$SC_LOG" ]
    then
        if [ ! -w "$(dirname "$SC_LOG")" ]
        then
            exit_program "no write permission to create log at $(dirname "$SC_LOG")"
        fi
        
        screencast $SC_OPTIONS < "$SC_FIFO" > "$SC_LOG" 2>&1 &
    else
        screencast $SC_OPTIONS < "$SC_FIFO" &
    fi
    
    printf '' > "$SC_FIFO"
    wait "$!"
}

quit_sc() {
    if [ ! -p "$SC_FIFO" ]
    then
        exit_program "no FIFO at '${SC_FIFO}' to interact with"
    fi
    
    [ "$SC_ACTION" != 'quit' ] && SC_ACTION='quit'
    
    printf '%s\n' "${0##*/}: sending the quit keystroke to screencast FIFO"
    printf '%s' 'q' > "$SC_FIFO"
    sleep 1
}

#########################################
#            program start              #
#########################################

trap 'cleanup' EXIT HUP INT QUIT ABRT TERM # signal handling

check_requirements

if [ "$#" -eq '0' ]
then
    show_usage
    exit 0
fi

get_cmd_line "$@"

case "$SC_ACTION" in
    start)
        start_sc
        ;;
    
    quit|stop|finish)
        quit_sc
        ;;
    
    *)
        exit_program "unknown action '${SC_ACTION}'"
        ;;
esac
  1. create two keyboard hotkeys in your desktop environment:
  • one for start recording, using the command scfifo -a start [options]
  • one for finish recording, using the command scfifo -a quit [options]

That's it. Ready to go!

Now, suppose that your hotkey bindings to start and finish recording are Ctrl+F2 and Ctrl+F3 respectively:

  • press Ctrl+F2 to start recording
  • press Ctrl+F3 to finish recording

Notes about the named pipe method

  • run scfifo --help for more details about the script usage, like how to set the screencast options.
  • you can create multiple desktop hotkeys with different options passed to the script if you need to set multiple types of recording (for example, one command for recording with fade effect, another without fade and yet another to use webcam)
Clone this wiki locally