一键生成 Android 录屏 gif 的脚本
目的
編寫 bash 腳本, 實現(xiàn)一行命令得到 Android 手機(jī)錄制屏幕 gif 動圖文件.
博主使用 ubuntu 系統(tǒng), shell 為 bash. 這個腳本也可以用在 mac 系統(tǒng)上.
聽說 windows 系統(tǒng)出了 ubuntu on windows, 不知道能不能使用這個腳本.
原理
adb shell screenrecord
Android 4.4 版本后系統(tǒng)內(nèi)預(yù)置了一個 screenrecord 命令, 可以用來將屏幕錄制為 MP4 格式. 具體命令格式可以通過 –help 參數(shù)查看:
$ adb shell screenrecord --help Usage: screenrecord [options] <filename>Android screenrecord v1.2. Records the device's display to a .mp4 file.Options: --size WIDTHxHEIGHTSet the video size, e.g. "1280x720". Default is the device's maindisplay resolution (if supported), 1280x720 if not. For best results,use a size supported by the AVC encoder. --bit-rate RATESet the video bit rate, in bits per second. Value may be specified asbits or megabits, e.g. '4000000' is equivalent to '4M'. Default 4Mbps. --bugreportAdd additional information, such as a timestamp overlay, that is helpfulin videos captured to illustrate bugs. --time-limit TIMESet the maximum recording time, in seconds. Default / maximum is 180. --verboseDisplay interesting information on stdout. --helpShow 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上面的命令將把所連接的手機(jī)屏幕錄制為 寬高 360x640, 比特率 2M 的視頻, 保存為手機(jī) sd 卡根目錄下的 android_screenrecord_test.mp4 文件.
該命令會持續(xù)錄制, 直到用 ctrl-c 終止命令, 那么錄制也就結(jié)束了.
也可以用 –time-limit TIME 參數(shù)來預(yù)先指定錄制時長, 到時間會自動結(jié)束. 默認(rèn)的最大時長為 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 秒顯示下一幀.
如果系統(tǒng)內(nèi)還沒有 convert 命令, 可以用如下命令安裝:
sudo apt-get install imagemagick
博主使用 ubuntu 16.10, 這個命令是預(yù)置在系統(tǒng)里的, 不需要安裝.
ffmpeg 及 convert 參數(shù)設(shè)置
上面兩個命令中, ffmpeg -r 5 和 convert -delay 20 這兩個參數(shù)值, 分別是 視頻抽幀間隔 和 gif每幀間隔, 假設(shè)其分別為 video_fps 和 gif_delay, 那么這兩個參數(shù)在設(shè)置時必須滿足如下條件:
video_fps * gif_delay = 100
如果乘積小于 100, 則生成的 gif 會比原本的播放速度快;
如果乘積大于 100, 則生成的 gif 會比原本的播放速度慢.
至于原因, 結(jié)合上面對這兩個參數(shù)的介紹, 思考一下就明白了.
捕獲錄制結(jié)束事件
上面三個命令分開調(diào)用, 實現(xiàn)錄屏為 gif 已經(jīng)相當(dāng)簡單了.
如果要將三條命令寫在一個腳本里, 在一個過程中完成功能, 第一個要解決的是如何捕獲錄制結(jié)束事件, 即 ctrl-c 命令.
在 bash 中可以通過下面腳本實現(xiàn):
有了這個方法獲取錄制結(jié)束事件, 再往下就簡單了.
這里遇到一個坑, 就是如果捕獲 ctrl-c 后直接開始轉(zhuǎn)換 gif 的操作, 會失敗. 試過幾次后, 發(fā)現(xiàn)是 ctrl-c 后其實 Android 的 screenrecord 命令并沒有處理完, 這時候的視頻還不可用. 解決的辦法簡單粗暴, 讓腳本原地 sleep 2秒, 再去操作所生成的 MP4 文件就可用了.
最終腳本
也不知道該寫些啥了, 直接貼出完整腳本吧:
#!/bin/bash # author : liuxu-0703@163.com#======================================================== # 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).gif OUTPUT_FILE_DIR=$(pwd) OUTPUT_VIDEO_NAME=screenrecord_$(date +%m%d%H%M%S).mp4 OUTPUT_VIDEO_DEVICE_DIR=/sdcard TMP_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 here ADB="adb"#========================================================# catch ctrl-c signal CTRL_C() {if $RECORDING; thenecho "stop recording. start convert..."RECORDING=falseelse# 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 2sadb pull $OUTPUT_VIDEO_DEVICE_DIR/$OUTPUT_VIDEO_NAME $TMP_DIRif [ -f $TMP_DIR/$OUTPUT_VIDEO_NAME ]; then# remove video on phoneadb shell rm $OUTPUT_VIDEO_DEVICE_DIR/$OUTPUT_VIDEO_NAMEecho "converting file: $TMP_DIR/$OUTPUT_VIDEO_NAME"MP4ToGIF $TMP_DIR/$OUTPUT_VIDEO_NAMEelseecho "* create screen record mp4 fail"exit 2fi } trap CTRL_C SIGINT# catch script exit event CLEAR_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_DIRechofi } trap "CLEAR_WORK" EXIT#========================================================function MP4ToGIF() {echo "*** extract frames ***"mkdir $TMP_DIR/framesffmpeg -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" ]; thenecho "* output dir not exists: $OUTPUT_FILE_DIR"exit 1 fi if [ ! -e $TMP_DIR ]; thenmkdir $TMP_DIR fi if [ ! -e $TMP_DIR ]; thenecho "* tmp dir not exists: $TMP_DIR"exit 1 fiecho "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開頭定義的那幾個數(shù)組, 是為了便于測試. 最終生成的 gif 文件也直接保存在了當(dāng)前目錄下.
主要是因為加上參數(shù)化, 代碼會多很多, 就不容易找到主要功能了.
帶參數(shù)化, 帶簡易幫助文檔的完整腳本, 可以在下面鏈接中找到:
android_screen2gif.sh
使用
使用前提:
- adb 可以正常連接到手機(jī), 就是不能有 offline 之類的問題. (這里安利另一篇文章: 解決 ubuntu adb 設(shè)備識別問題)
- 手機(jī)必須是 4.4 以上系統(tǒng).
腳本本身就是為了使用簡單寫的. 只需在命令行直接執(zhí)行腳本, 即可開始手機(jī)屏幕錄制. 因為是測試, 選在 /tmp 目錄操作.
$ cd /tmp/ $ android_screen2gif.sh params: 360x640, 1000000, 5, 20 Main display is 720x1280 @60.00fps (orientation=0) Configuring recorder for 360x640 video/avc at 1.00Mbps Content area is 360x640 at offset x=0 y=0這時錄制正在進(jìn)行, 命令行掛起. 等你認(rèn)為錄制可以結(jié)束了, 按下 ctrl-c, 錄制結(jié)束, 開始轉(zhuǎn)換 gif 的步驟. 一般需要3到4秒, 錄屏的 gif 就在當(dāng)前目錄生成了.
^Cstop recording. start convert... [100%] /sdcard/screenrecord_0407090859.mp4 converting 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 錄屏文件了.
參數(shù)建議
根據(jù)自測 及 最終 gif 生成的過程, 可以得到如下結(jié)論:
視頻解析度參數(shù):
寬高越大越清晰, 最終生成的 gif 文件越大. 這個是很明顯的.
最好按手機(jī)豎屏顯示的方式, 將解析度設(shè)置為 9:16 的比例. 如果設(shè)置為其他比例, 比如 480:480, 則錄制出的視頻會有很寬的黑邊.
視頻比特率參數(shù):
先說結(jié)論: 比特率設(shè)置基本不會影響最終生成的 gif 文件質(zhì)量.
因為最終 gif 文件來自視頻抽幀, 視頻比特率的大小對于比如每秒抽取10幀這樣的需求, 對抽取出的圖片清晰度影響不大. 因此為了中間文件更小, 建議把這個參數(shù)設(shè)低即可.
抽幀幀率 及 每幀間隔:
這兩個參數(shù)對最終 gif 質(zhì)量影響很大. 其中:
抽幀幀率越大, 最終 gif 質(zhì)量越高;
每幀間隔越小, 最終 gif 質(zhì)量越高.
如前述, 這兩個參數(shù)必須成對設(shè)置. 如果這兩個參數(shù)都取整數(shù)的話, 基本上可以設(shè)置的就下面這幾對:
其中:
10, 10 這組, 設(shè)置每秒10幀, gif 每幀間隔 0.1 秒, 這樣5秒的gif文件就要大概 10M 大小了.
2, 50 這組, 設(shè)置每秒2幀, gif 每幀間隔 0.5 秒, 最終gif文件卡頓就很嚴(yán)重了.
因此建議選取 5, 20 這組參數(shù). 如果對gif質(zhì)量要求很高, 可以試試 10, 10 這組參數(shù).
綜上, 小伙伴們可以自己嘗試下設(shè)置不同的參數(shù)組合, 試幾次就能體會該怎么設(shè)置了.
參考:
create gif from mp4 via command line
command convert doc
再次無恥的安利安利自己的腳本項目:
android_screen2gif.sh
原創(chuàng)文章, 轉(zhuǎn)載請注明出處: http://blog.csdn.net/liuxu0703/article/details/69397154
總結(jié)
以上是生活随笔為你收集整理的一键生成 Android 录屏 gif 的脚本的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java转换json格式_java中常见
- 下一篇: JAVA生成企业组织机构代码、营业执照代