2019-04-09 晚的更新

更新了一下昨晚寫的垃圾代碼, 有如下改進。

  1. 有了更好看的輸出信息
    • 需要安裝有 Nerd Fonts 字體才能正確顯示
  2. 修復了開始/結束錄屏後需要手動 restart 一下 i3wm 才能顯示錄屏信息的問題
    • 按理說 i3blocks 正確使用的話,應該不會出現這個問題,不過文檔我看的不是很明白
    • 這也會導致出現另一個影響體驗的問題 (開始/結束錄屏時會閃一下屏),不過不會影響所錄的視頻

寫在前面

以前錄屏都是按照 這裏的方法 進行操作的 (需要結束錄屏就 kill 掉 ffmepg 的進程)。

雖然這種方法很不優雅, 但錄屏功能並不常用, 所以還能將就將就。

不過這兩天錄屏需求比較多, 感覺不能再將就了。

具體實現

直接上代碼 (點擊 此處 下載腳本)

下面代碼實現了開始錄屏, 結束錄屏和輸出錄屏信息 (錄屏時間和文件大小) 功能。

#!/bin/bash
# Copyright (C) 2019 文正•喵 <ivlioioilvi@outlook.com>

# 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 3 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/>.

#
# 使用 FFmpeg + i3blocks 進行錄屏
#

# 定義變量
#
# 日誌路徑
LOG_PATH="$HOME/.cache"
# 具體的日誌文件
REAL_LOG_FILE="$LOG_PATH/scf.log"
# 視頻輸出路徑
VIDEO_PATH="$HOME/Pictures"
# 具體的視頻輸出文件
REAL_VIDEO_FILE="$VIDEO_PATH/Screen-Capture-$(date +'%Y-%m-%d-%H:%M:%S').mp4"
# 分辨率
RESOLUTION_VALUE="1920x1080"

# 開始錄屏
start_Action() {
    # 判斷是否存在 i3-msg 命令 (存在就手動刷新)
    if command -v i3-msg >/dev/null 2>&1; then
        i3-msg restart
    fi

    # 方案一 (有損編碼,產生的文件體積較小,有音頻)
    nohup ffmpeg -f x11grab -video_size "$RESOLUTION_VALUE" -framerate 25 -i "$DISPLAY" -f alsa -i default -c:v libx264 -preset ultrafast -c:a aac "$REAL_VIDEO_FILE" > "$REAL_LOG_FILE" 2>&1 &

    # 方案二 (無損編碼,產生的文件體積很大,無音頻)
    #nohup ffmpeg -f x11grab -video_size "$RESOLUTION_VALUE" -framerate 25 -i "$DISPLAY" -c:v ffvhuff "$REAL_VIDEO_FILE" > "$REAL_LOG_FILE" 2>&1 &
}

# 結束錄屏
end_Action() {
    # 判斷是否存在 i3-msg 命令 (存在就手動刷新)
    if command -v i3-msg >/dev/null 2>&1; then
        i3-msg restart
    fi

    # 結束 FFmpeg 進程
    killall ffmpeg >/dev/null 2>&1
    # 刪除日誌文件
    rm -rf "$REAL_LOG_FILE"
}

# 解析出錄屏時間與文件大小
time_And_Size() {
    # 判斷日誌是否存在 (不存在就退出)
    if [ -f "$REAL_LOG_FILE" ]; then
        # 讀取日誌文件
        cat "$REAL_LOG_FILE" |

        # 替換 ^M 爲回車 (在終端中按下 C-v, C-m 可打出 ^M)
        sed 's/
/\n/g' | 

        # 讀取最後一行的內容
        tail -n 1 |

        # 過濾出其中的時間和文件大小數據
        awk '{ print $6$7, $8 }' |

        # 美化時間與文件大小的信息
        sed 's/size\=/\ /' | sed 's/time\=/\ /'

        # 等待 0.1 秒後遞歸
        sleep 0.1
        time_And_Size
    else
        # 此處表示無可用於解析的日誌文件
        :
    fi
}

# 幫助頁
manual_Page() {
    echo  -e "
    Usage: _scf [options] [arguments]

    Options:
    -h, --help     Displays this help
    -v, --version  Displays version information

    Arguments:
    s     Start recording screen
    e     End recording screen
    t     Resolve the time and file size
    "
}

# 版本信息
show_Version() {
    echo -e "
    _scf v_0.0.2

    It is written in the scripting language Bash.
    "
}

# 參數判斷
case "$1" in
"-h")
    manual_Page
    ;;
"--help")
    manual_Page
    ;;
"-v")
    show_Version
    ;;
"--version")
    show_Version
    ;;
"s")
    start_Action
    ;;
"e")
    end_Action
    ;;
"t")
    time_And_Size
    ;;
*)
    echo -e "
    No options/arguments were used or the wrong options/arguments were used.

    Use the -h/-help option for detailed help.
    "
    ;;
esac

將上面的代碼以 _scf 名稱保存在 PATH 中, 就可以在 Rofi, dmenu, Krunner 等中方便的開始/結束錄屏了。

不過,我比較偏向於鍵盤流, 所以在 i3wm 中綁定了如下的快捷鍵。

bindsym $mod+m mode "+Multimedia"
mode "+Multimedia" {
    bindsym l exec --no-startup-id _scf s       ,mode "default"
    bindsym Shift+l exec --no-startup-id _scf e ,mode "default"
    bindsym Escape mode "default"
    bindsym Return mode "default"
    bindsym $mod+m mode "default"
}

先按下 Win + M 鍵,再按下 L 鍵,可開始錄屏。

先按下 Win + M 鍵,再按下 Shift + L 鍵,可停止錄屏。

反正運行方法多種多樣,看你的喜好。

而運行後,想要在 i3blocks 中顯示錄屏信息 (錄屏時間和文件大小), 將下面的內容添加至 i3blocks 的配置文件中即可。

# Information during screen recording
#
[_scf]
command=_scf t
# The interval value persist (or -3) expects the command to be an infinite loop. Each line of the output will trigger an update of the block.
interval=persist

可還行?

用了幾次,感覺還行吧。