Skip to content

Instantly share code, notes, and snippets.

@mmm
Last active July 19, 2019 19:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mmm/4a100e509ec6773e3c7d773beac009fc to your computer and use it in GitHub Desktop.
Save mmm/4a100e509ec6773e3c7d773beac009fc to your computer and use it in GitHub Desktop.
#!/bin/bash
#
# Multi-monitor Screencast Capture for Linux
#
# This script uses `ffmpeg` to simultaneously capture
# inputs:
# - hd1080 monitor with "Slides" fullscreen
# - hd1080 monitor "Demo" screen (usually terminal and/or browser)
# - hd1080 webcam (h264)
# - audio (aac)
#
# The monitor layout is set for:
#
# ${DISPLAY}+0,0 ${DISPLAY}+1920,0
# + +
# | |
# v v
# ++------------------------+ ++-----------------------+
# | | | |
# | | | |
# | | | |
# | "Demo" | | "Slides" |
# | | | |
# | | | |
# | | | |
# | | | |
# +-------------------------+ +------------------------+
#
# To change this, edit the offsets used for the `x11grab` inputs in
# `capture_slides()` and `capture_demo()` below.
#
# The output is organized by `scene->shot->take` and saves files into
#
# $(cwd)/
# -> ${scene_name}/
# -> shot-${shot_number}/
# -> take-${timestamp}/
# -> *.mkv
#
# Directories are created under the current directory as needed.
#
# Stop this manually with `Ctrl-c` when done
#
# Copyright and related rights waived via CC0
set -o errexit -o nounset -o pipefail
usage() {
echo "Usage: $0 <scene_name> [<shot_number>]
where:
<scene_name> is something like intro-what-is-data-eng
<shot_number> optional, default is 010"
}
(( $# < 1 )) && usage && exit 1
scene_name=$1
shot_number=${2:-010}
timestamp=`date +%Y-%m-%d-%H%M%S`
output_dir="${scene_name}/shot-${shot_number}/take-${timestamp}"
framerate=30
display=":0.0"
capture_slides() {
local output_dir=$1
ffmpeg \
-hide_banner -nostats -loglevel warning \
-f x11grab -r $framerate -s hd1080 -i ${display}+1920,0 \
-vcodec libx264 \
-preset ultrafast \
$output_dir/slides.mkv > $output_dir/slides.log 2>&1
echo "slides done"
}
capture_demo() {
local output_dir=$1
ffmpeg \
-hide_banner -nostats -loglevel warning \
-f x11grab -r $framerate -s hd1080 -i ${display}+0,0 \
-vcodec libx264 \
-preset ultrafast \
$output_dir/demo.mkv > $output_dir/demo.log 2>&1
echo "demo done"
}
capture_audio() {
local output_dir=$1
ffmpeg \
-hide_banner -nostats -loglevel warning \
-f alsa -i default \
-c copy -copyts -start_at_zero \
$output_dir/audio.wav > $output_dir/audio.log 2>&1
echo "webcam done"
}
capture_webcam() {
local output_dir=$1
ffmpeg \
-hide_banner -nostats -loglevel warning \
-f v4l2 -framerate $framerate -input_format h264 -video_size hd1080 -ts mono2abs -i /dev/video0 \
-c copy -copyts -start_at_zero \
$output_dir/webcam.mkv > $output_dir/webcam.log 2>&1
echo "webcam done"
}
echo "starting ${scene_name}/shot-${shot_number}/take-${timestamp}"
echo "Ctrl-c when done"
mkdir -p $output_dir
echo "capturing slides"
capture_slides $output_dir &
echo "capturing demo"
capture_demo $output_dir &
echo "capturing webcam"
capture_webcam $output_dir &
echo "capturing audio"
capture_audio $output_dir &
for job in `jobs -p`; do
wait $job
done
echo "done"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment