t004-screencasts.html - adamsgaard.dk - my academic webpage
 (HTM) git clone git://src.adamsgaard.dk/adamsgaard.dk
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       t004-screencasts.html (4532B)
       ---
            1 <p>On Monday 2020-03-16 the buildings of the danish public
            2 sector were closed as an emergency response to COVID-19.  This
            3 includes Aarhus University where I teach two undergraduate courses.
            4 The university asks lecturers to move their teaching to digital
            5 platforms.  As many times before, this requires creative thinking
            6 for those of us who do not use Microsoft and Apple products.</p>
            7 
            8 <p>I needed a way to record my pdf slideshows while talking over
            9 the presentation.  Ideally, I also wanted the ability to show the
           10 video of my webcam as an overlay in an attempt to make the presentation
           11 a bit more engaging when explaining complex parts.</p>
           12 
           13 <p>Fortunately, <a href="https://ffmpeg.org">ffmpeg(1)</a> makes
           14 it easy to record the screen and laptop audio.  I want to keep the
           15 fan noise low during recording by applying minimal compression and
           16 encoding.  The following shell script serves the purpose of starting
           17 and stopping recording:</p>
           18 
           19 <pre><code>#!/bin/sh
           20 lockfile=/tmp/screenrecord.pid
           21 
           22 startrecording() {
           23     out="$HOME/screenrecord-$(date '+%Y-%m-%d_%H:%M:%S').mkv"
           24     ffmpeg -y \
           25         -f x11grab \
           26         -framerate 60 \
           27         -s "$(xdpyinfo | grep dimensions | awk '{print $2}')" \
           28         -i $DISPLAY \
           29         -f sndio -i default \
           30         -r 30 \
           31         -c:v libx264rgb -crf 0 -preset ultrafast -c:a flac \
           32         "$out" >/dev/null 2>&1 &
           33     printf '%s' "$!" > "$lockfile"
           34 
           35     sleep 1
           36     if [ ! -f "$out" ]; then
           37         echo 'error: ffmpeg recording did not start' >&2
           38         notify-send -u CRITICAL "${0##*/}" 'ffmpeg recording did not start'
           39         rm -f "$lockfile"
           40         exit 1
           41     fi
           42 }
           43 
           44 stoprecording() {
           45     kill "$(cat "$lockfile")"
           46     rm -f "$lockfile"
           47     notify-send "${0##*/}" 'recording ended'
           48 }
           49 
           50 if [ -f "$lockfile" ]; then
           51     stoprecording
           52 else
           53     startrecording
           54 fi
           55 </code></pre>
           56 
           57 <p>I have bound the above script to the key binding Alt+r which
           58 makes it easy to start and stop recording in my X session.</p>
           59 
           60 <p>On Linux systems, the sound driver <b>sndio</b> should be replaced
           61 by <b>alsa</b> in the above ffmpeg(1) command.  Audio recording is
           62 disabled by default on OpenBSD, but can be permanently enabled with
           63 the following commands:</p>
           64 
           65 <pre><code># sysctl kern.audio.record=1
           66 # echo kern.audio.record=1 >> /etc/sysctl.conf
           67 </code></pre>
           68 
           69 <p>On OpenBSD I can show the webcam video feed with the <a
           70 href="https://man.openbsd.org/man1/video.1">video(1)</a> command.
           71 The following script toggles the video feed:<p>
           72 
           73 <pre><code>#!/bin/sh
           74 # remember to `chown $USER /dev/video0`
           75 if pgrep video >/dev/null 2>&1; then
           76     pkill video
           77 else
           78     nohup video -s 320 >/dev/null 2>&1 &
           79 fi
           80 </code></pre>
           81 
           82 <p>On Linux, the command <strong>mpv /dev/video0</strong> can take
           83 place of the video(1) command above.  I have the above script bound
           84 to the keybinding Alt+v so I can quickly show and hide my face while
           85 recording.</p>
           86 
           87 <p>I set <a href="https://dwm.suckless.org">dwm(1)</a>, my window
           88 manager, to open the video feed as a floating window on the bottom
           89 right of the screen.  The full dwm configuration can be found <a
           90 href="https://src.adamsgaard.dk/dwm">here</a>.</p>
           91 
           92 <p>When I am done recording a lecture, I encode and compress the
           93 video file to save bandwidth during upload.  The following script
           94 encodes all input files and reduces file size to roughly 15% without
           95 concievable loss in quality:</p>
           96 
           97 <pre><code>#!/bin/sh
           98 
           99 encode() {
          100     ffmpeg -y -i "$1" \
          101         -c:v libx264 -threads 0 -preset faster -pix_fmt yuv420p \
          102         -c:a aac -crf 10 \
          103         "${1%.*}_out.mp4"
          104 }
          105 
          106 for f in "$@"; do
          107     encode "$f"
          108 done
          109 </code></pre>
          110 
          111 <p>If there is a delay between video and audio, this can also be
          112 adjusted using ffmpeg(1).  I correct for a 0.3 s delay that I
          113 encounter when recording on my laptop:</p>
          114 
          115 <pre><code>#!/bin/sh
          116 
          117 synchronize() {
          118     ffmpeg -y -i "$1" \
          119         -itsoffset 0.300 \
          120         -i "$1" \
          121         -map 0:v -map 1:a \
          122         -c copy \
          123         "${1%.*}_out.${1##*.}"
          124 }
          125 
          126 for f in "$@"; do
          127     synchronize "$f"
          128 done
          129 </code></pre>
          130 
          131 <figure class="pagefigure">
          132     <video poster="video/screencast.jpg" style="object-fit:fill;"
          133         controls preload="none" class="mediaframe">
          134         <source src="video/screencast.webm" type="video/webm">
          135         <source src="video/screencast.ogv" type="video/ogg">
          136         <source src="video/screencast.mp4" type="video/mp4">
          137         <a href="video/screencast.mp4">Link</a>
          138     </video>
          139     <figcaption>
          140         Example screen recording using ffmpeg(1) and video(1)
          141         with the above scripts.
          142     </figcaption>
          143 </figure>
          144