一鍵產生 Android 錄屏 gif 的指令碼

來源:互聯網
上載者:User

標籤:comment   目的   boot   ddc   bug   產生   調用   豎屏   .net   

目的

編寫 bash 指令碼, 實現一行命令得到 Android 手機錄製螢幕 gif 動圖檔案.

博主使用 ubuntu 系統, shell 為 bash. 這個指令碼也可以用在 mac 系統上.
聽說 windows 系統出了 ubuntu on windows, 不知道能不能使用這個指令碼.

原理adb shell screenrecord

Android 4.4 版本後系統內預置了一個 screenrecord 命令, 可以用來將螢幕錄製為 MP4 格式. 具體命令格式可以通過 –help 參數查看:

$ adb shell screenrecord --helpUsage: screenrecord [options] <filename>Android screenrecord v1.2.  Records the device‘s display to a .mp4 file.Options:--size WIDTHxHEIGHT    Set the video size, e.g. "1280x720".  Default is the device‘s main    display resolution (if supported), 1280x720 if not.  For best results,    use a size supported by the AVC encoder.--bit-rate RATE    Set the video bit rate, in bits per second.  Value may be specified as    bits or megabits, e.g. ‘4000000‘ is equivalent to ‘4M‘.  Default 4Mbps.--bugreport    Add additional information, such as a timestamp overlay, that is helpful    in videos captured to illustrate bugs.--time-limit TIME    Set the maximum recording time, in seconds.  Default / maximum is 180.--verbose    Display interesting information on stdout.--help    Show this message.Recording continues until Ctrl-C is hit or the time limit is reached.

舉例:

adb shell screenrecord --size "360x640" --bit-rate 2000000 /sdcard/android_screenrecord_test.mp4

上面的命令將把所串連的手機螢幕錄製為 寬高 360x640, 位元速率 2M 的視頻, 儲存為手機 sd 卡根目錄下的 android_screenrecord_test.mp4 檔案.
該命令會持續錄製, 直到用 ctrl-c 終止命令, 那麼錄製也就結束了.
也可以用 –time-limit TIME 參數來預先指定錄製時間長度, 到時間會自動結束. 預設的最大時間長度為 3 分鐘.

ffmpeg

使用 ffmpeg 抽幀的命令將視頻提取為一系列圖片:

ffmpeg -i video.mp4 -r 5 ‘frames/frame-%03d.jpg‘

其中: -r 5 代表抽取的幀率, 即每秒視頻抽取 5 幀出來.

convert

使用 imagemagick 包中的 convert 命令將一系列圖片組合為 gif 動圖格式:

convert -delay 20 -loop 0 *.jpg myimage.gif

其中: -delay 20 代表所產生的 gif 動圖每幀之間的時間間隔, 即每 0.2 秒顯示下一幀.

如果系統內還沒有 convert 命令, 可以用如下命令安裝:
sudo apt-get install imagemagick
博主使用 ubuntu 16.10, 這個命令是預置在系統裡的, 不需要安裝.

ffmpeg 及 convert 參數設定

上面兩個命令中, ffmpeg -r 5convert -delay 20 這兩個參數值, 分別是 視頻抽幀間隔 和 gif每幀間隔, 假設其分別為 video_fps 和 gif_delay, 那麼這兩個參數在設定時必須滿足如下條件:
video_fps * gif_delay = 100

如果乘積小於 100, 則產生的 gif 會比原本的播放速度快;
如果乘積大於 100, 則產生的 gif 會比原本的播放速度慢.

至於原因, 結合上面對這兩個參數的介紹, 思考一下就明白了.

捕獲錄製結束事件

上面三個命令分開調用, 實現錄屏為 gif 已經相當簡單了.
如果要將三條命令寫在一個指令碼裡, 在一個過程中完成功能, 第一個要解決的是如何捕獲錄製結束事件, 即 ctrl-c 命令.
在 bash 中可以通過下面指令碼實現:

# catch ctrl-c signalCTRL_C() {    # ctrl-c hit, do something}trap CTRL_C SIGINT

有了這個方法擷取錄製結束事件, 再往下就簡單了.
這裡遇到一個坑, 就是如果捕獲 ctrl-c 後直接開始轉換 gif 的操作, 會失敗. 試過幾次後, 發現是 ctrl-c 後其實 Android 的 screenrecord 命令並沒有處理完, 這時候的視頻還不可用. 解決的辦法簡單粗暴, 讓指令碼原地 sleep 2秒, 再去操作所產生的 MP4 檔案就可用了.

最終指令碼

也不知道該寫些啥了, 直接貼出完整指令碼吧:

#!/bin/bash# author : [email protected]#========================================================# define param group hereQUALITY_1=("360x640"  1000000  4  25)QUALITY_2=("360x640"  1000000  5  20)QUALITY_3=("360x640"  1000000  10  10)QUALITY_4=("720x1280"  1000000  4  25)QUALITY_5=("720x1280"  1000000  5  20)#========================================================QUALITY=(${QUALITY_2[@]})RESOLUTION=${QUALITY[0]}BIT_RATE=${QUALITY[1]}GIF_FPS=${QUALITY[2]}GIF_DELAY=${QUALITY[3]}# GIF_FPS and GIF_DELAY must meet the following condition:# GIF_FPS * GIF_DELAY = 100OUTPUT_FILE_NAME=android_screen_record.$(date +%m%d%H%M%S).gifOUTPUT_FILE_DIR=$(pwd)OUTPUT_VIDEO_NAME=screenrecord_$(date +%m%d%H%M%S).mp4OUTPUT_VIDEO_DEVICE_DIR=/sdcardTMP_DIR=/tmp/android_screen_to_gif_$(date +%m%d%H%M%S)RECORDING=true# you may use adb by absolute file path. if so, specify it hereADB="adb"#========================================================# catch ctrl-c signalCTRL_C() {    if $RECORDING; then        echo "stop recording. start convert..."        RECORDING=false    else        # ctrl-c hit but not for stop recording, just exit.        exit $?    fi    # adb screenrecord may still deal with mp4 file creating,    # just wait for it a little while.    sleep 2s    adb pull $OUTPUT_VIDEO_DEVICE_DIR/$OUTPUT_VIDEO_NAME $TMP_DIR    if [ -f $TMP_DIR/$OUTPUT_VIDEO_NAME ]; then        # remove video on phone        adb shell rm $OUTPUT_VIDEO_DEVICE_DIR/$OUTPUT_VIDEO_NAME        echo "converting file: $TMP_DIR/$OUTPUT_VIDEO_NAME"        MP4ToGIF $TMP_DIR/$OUTPUT_VIDEO_NAME    else        echo "* create screen record mp4 fail"        exit 2    fi}trap CTRL_C SIGINT# catch script exit eventCLEAR_WORK() {    if [ -e $TMP_DIR ]; then        # since the tmp files have been put into /tmp/ dir, they will get        # removed on system reboot. thus we are in no hurry to remove them now.        # un-commit this line if you want to remove tmp files immediately after script run        #rm $TMP_DIR        echo    fi}trap "CLEAR_WORK" EXIT#========================================================function MP4ToGIF() {    echo "*** extract frames ***"    mkdir $TMP_DIR/frames    ffmpeg -i $1 -r $GIF_FPS "$TMP_DIR/frames/frame-%03d.jpg"    echo "*** convert frames to gif ***"    convert -delay $GIF_DELAY -loop 0 "$TMP_DIR/frames/*.jpg" $OUTPUT_FILE_DIR/$OUTPUT_FILE_NAME}#========================================================if [ ! -d "$OUTPUT_FILE_DIR" ]; then    echo "* output dir not exists: $OUTPUT_FILE_DIR"    exit 1fiif [ ! -e $TMP_DIR ]; then    mkdir $TMP_DIRfiif [ ! -e $TMP_DIR ]; then    echo "* tmp dir not exists: $TMP_DIR"    exit 1fiecho "params: $RESOLUTION, $BIT_RATE, $GIF_FPS, $GIF_DELAY"adb shell screenrecord --verbose --size $RESOLUTION --bit-rate $BIT_RATE $OUTPUT_VIDEO_DEVICE_DIR/$OUTPUT_VIDEO_NAME

開頭定義的那幾個數組, 是為了便於測試. 最終產生的 gif 檔案也直接儲存在了目前的目錄下.
主要是因為加上參數化, 代碼會多很多, 就不容易找到主要功能了.
帶參數化, 帶簡易協助文檔的完整指令碼, 可以在下面連結中找到:

android_screen2gif.sh

使用

使用前提:

  • adb 可以正常串連到手機, 就是不能有 offline 之類的問題. (這裡安利另一篇文章: 解決 ubuntu adb 裝置識別問題)
  • 手機必須是 4.4 以上系統.

指令碼本身就是為了使用簡單寫的. 只需在命令列直接執行指令碼, 即可開始手機螢幕錄製. 因為是測試, 選在 /tmp 目錄操作.

$ cd /tmp/$ android_screen2gif.sh params: 360x640, 1000000, 5, 20Main display is 720x1280 @60.00fps (orientation=0)Configuring recorder for 360x640 video/avc at 1.00MbpsContent area is 360x640 at offset x=0 y=0

這時錄製進行中, 命令列掛起. 等你認為錄製可以結束了, 按下 ctrl-c, 錄製結束, 開始轉換 gif 的步驟. 一般需要3到4秒, 錄屏的 gif 就在目前的目錄產生了.

^Cstop recording. start convert...[100%] /sdcard/screenrecord_0407090859.mp4converting file: /tmp/android_screen_to_gif_0407090859/screenrecord_0407090859.mp4*** extract frames ***ffmpeg version 3.0.7-0ubuntu0.16.10.1 Copyright (c) 2000-2017 the FFmpeg developers......Input #0, mov,mp4,m4a,3gp,3g2,mj2, from ‘/tmp/android_screen_to_gif_0407090859/screenrecord_0407090859.mp4‘:......Output #0, image2, to ‘/tmp/android_screen_to_gif_0407090859/frames/frame-%03d.jpg‘:......*** convert frames to gif ***result gif file:/tmp/android_screen_record.0407090859.gif

這一步輸出較多, 用 ...... 代替了部分輸出. 最後那行就是最終產生的 gif 錄屏檔案了.

參數建議

根據自測 及 最終 gif 產生的過程, 可以得到如下結論:

視頻解析度參數:
寬高越大越清晰, 最終產生的 gif 檔案越大. 這個是很明顯的.
最好按手機豎屏顯示的方式, 將解析度設定為 9:16 的比例. 如果設定為其他比例, 比如 480:480, 則錄製出的視頻會有很寬的黑邊.

視頻位元速率參數:
先說結論: 位元速率設定基本不會影響最終產生的 gif 檔案品質.
因為最終 gif 檔案來自視頻抽幀, 視頻位元速率的大小對於比如每秒抽取10幀這樣的需求, 對抽取出的圖片清晰度影響不大. 因此為了中間檔案更小, 建議把這個參數設低即可.

抽幀幀率 及 每幀間隔:
這兩個參數對最終 gif 品質影響很大. 其中:
抽幀幀率越大, 最終 gif 品質越高;
每幀間隔越小, 最終 gif 品質越高.
如前述, 這兩個參數必須成對設定. 如果這兩個參數都取整數的話, 基本上可以設定的就下面這幾對:

2, 504, 255, 2010, 10

其中:
10, 10 這組, 設定每秒10幀, gif 每幀間隔 0.1 秒, 這樣5秒的gif檔案就要大概 10M 大小了.
2, 50 這組, 設定每秒2幀, gif 每幀間隔 0.5 秒, 最終gif檔案卡頓就很嚴重了.
因此建議選取 5, 20 這組參數. 如果對gif品質要求很高, 可以試試 10, 10 這組參數.

綜上, 小夥伴們可以自己嘗試下設定不同的參數組合, 試幾次就能體會該怎麼設定了.

參考:

create gif from mp4 via command line
command convert doc

再次無恥的安利安利自己的指令碼項目:

android_screen2gif.sh

一鍵產生 Android 錄屏 gif 的指令碼

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.