在「用 Bash 脚本写一个截屏工具」一文的后记里,我将截屏脚本略加改变,失去了一个可录制屏幕中指定窗口区域的脚本。翻手为云,覆手为雨,全拜 ffmpeg 所赐。
我毫无新意地将这个录制屏幕的脚本取名为 recorder,内容为:
#!/bin/bash
NAME=$(date +"%Y-%m-%d %T" | sed -e "s/ /-/g; s/:/-/g")
RECORD=/tmp/${NAME}.mkv
OUTPUT=/tmp/output-${NAME}.mkv
# 获取屏幕分辨率
SCREEN=$(xrandr | grep -o "current [0-9]* x [0-9]*" | sed -e 's/current *//g')
SCREEN_W=$(echo $SCREEN | sed -e 's/ x [0-9]*//')
SCREEN_H=$(echo $SCREEN | sed -e 's/[0-9]* x //')
# 获取窗口几何参数
declare -a WIN_PARAMS
WIN_PARAMS=($(xwininfo | sed -n -e '/^[[:space:]]*Absolute ..*[XY]/p;
/^[[:space:]]*Relative ..*[XY]/p;
/^[[:space:]]*Width:/p;
/^[[:space:]]*Height:/p'| awk'BEGIN{FS=":"}{print $2}'))
# 结构现实中的截图区。# 之所以如此,与 xwininfo 输入的窗口左上角绝对坐标无关。MARGIN=${WIN_PARAMS[2]}
WIN_X=$((${WIN_PARAMS[0]} - ${WIN_PARAMS[2]}))
WIN_Y=$((${WIN_PARAMS[1]} - ${WIN_PARAMS[3]}))
WIN_W=$((${WIN_PARAMS[4]} + ${WIN_PARAMS[2]} + $MARGIN))
WIN_H=$((${WIN_PARAMS[5]} + ${WIN_PARAMS[3]} + $MARGIN))
# 截图区越界解决
if (($WIN_X < 0)); then WIN_X=0; fi
if (($WIN_Y < 0)); then WIN_Y=0; fi
if (($WIN_W + $WIN_X > $SCREEN_W)); then WIN_W=$(($SCREEN_W - $WIN_X)); fi
if (($WIN_H + $WIN_Y > $SCREEN_H)); then WIN_H=$(($SCREEN_H - $WIN_Y)); fi
# 录制指定窗口区域
ffmpeg -video_size ${WIN_W}x${WIN_H} \
-framerate 30 -f x11grab \
-i :0.0+${WIN_X},${WIN_Y} \
-c:v libx264rgb -crf 0 -preset ultrafast $RECORD
# 视频后处理
ffmpeg -i $RECORD -c:v libx264rgb -crf 0 -preset veryslow $OUTPUT
而后有些可惜,感觉没法像截屏脚本那样,能够绑定到桌面环境的某个快捷键上。起因是,ffmpeg 在录制屏幕时,须要我在其运行的命令行窗口里摁一下 q
键方能完结屏幕录制。过后感觉,无解。截屏脚本在抓到屏幕画面后会主动退出,所以不存在这样的问题。
然而,方才筹备睡觉时,突然感觉本人切实是迂腐得很。我能够将桌面环境的快捷键绑定到一个能够运行命令行窗口的脚本上,而后在这个脚本里将命令行窗口和 recorder 建立联系。
脑洞一旦关上,就去调研了一下我的桌面环境的命令行窗口程序 mate-terminal,发现它确实能够容许我以参数的模式传给它 recorder 脚本并由它负责运行:
$ mate-terminal -e recorder
事实上,在我的桌面环境里,没必要去写一个运行 mate-terminal 的脚本,只须要在桌面快捷键绑定设置里间接为带参数的 mate-terminal 绑定一个快捷键即可。