目的

编写 bash 脚本, 实现一行命令得到 Android 手机录制屏幕 gif 动图文件.

博主使用 ubuntu 系统, shell 为 bash. 这个脚本也可以用在 mac 系统上.
听说 windows 系统出了 ubuntu on windows, 不知道能不能使用这个脚本.

原理

adb shell screenrecord

Android 4.4 版本后系统内预置了一个 screenrecord 命令, 可以用来将屏幕录制为 MP4 格式. 具体命令格式可以通过 –help 参数查看:

$ 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

上面的命令将把所连接的手机屏幕录制为 宽高 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 signal
CTRL_C() {# ctrl-c hit, do something
}
trap CTRL_C SIGINT

有了这个方法获取录制结束事件, 再往下就简单了.
这里遇到一个坑, 就是如果捕获 ctrl-c 后直接开始转换 gif 的操作, 会失败. 试过几次后, 发现是 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

开头定义的那几个数组, 是为了便于测试. 最终生成的 gif 文件也直接保存在了当前目录下.
主要是因为加上参数化, 代码会多很多, 就不容易找到主要功能了.
带参数化, 带简易帮助文档的完整脚本, 可以在下面链接中找到:

android_screen2gif.sh

使用

使用前提:

  • adb 可以正常连接到手机, 就是不能有 offline 之类的问题. (这里安利另一篇文章: 解决 ubuntu adb 设备识别问题)
  • 手机必须是 4.4 以上系统.

脚本本身就是为了使用简单写的. 只需在命令行直接执行脚本, 即可开始手机屏幕录制. 因为是测试, 选在 /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

这时录制正在进行, 命令行挂起. 等你认为录制可以结束了, 按下 ctrl-c, 录制结束, 开始转换 gif 的步骤. 一般需要3到4秒, 录屏的 gif 就在当前目录生成了.

^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 录屏文件了.

参数建议

根据自测 及 最终 gif 生成的过程, 可以得到如下结论:

视频解析度参数:
宽高越大越清晰, 最终生成的 gif 文件越大. 这个是很明显的.
最好按手机竖屏显示的方式, 将解析度设置为 9:16 的比例. 如果设置为其他比例, 比如 480:480, 则录制出的视频会有很宽的黑边.

视频比特率参数:
先说结论: 比特率设置基本不会影响最终生成的 gif 文件质量.
因为最终 gif 文件来自视频抽帧, 视频比特率的大小对于比如每秒抽取10帧这样的需求, 对抽取出的图片清晰度影响不大. 因此为了中间文件更小, 建议把这个参数设低即可.

抽帧帧率 及 每帧间隔:
这两个参数对最终 gif 质量影响很大. 其中:
抽帧帧率越大, 最终 gif 质量越高;
每帧间隔越小, 最终 gif 质量越高.
如前述, 这两个参数必须成对设置. 如果这两个参数都取整数的话, 基本上可以设置的就下面这几对:

2, 50
4, 25
5, 20
10, 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


原创文章, 转载请注明出处: http://blog.csdn.net/liuxu0703/article/details/69397154

一键生成 Android 录屏 gif 的脚本相关推荐

  1. android一键截图代码,偷偷告诉你ADB命令葵花宝典【一键截图和录屏】

    先导预告 作为一名测试工程师,每天可能都会面临从不同的设备导出截图或视频的工作,有些可能是bug截图或bug回放视频,有些截图可能是提供给PM或UI验收等等. 常规操作是iOS设备可以借助于iTool ...

  2. android 屏幕录制方案,Android录屏的三种解决方案

    本文总结三种用于安卓录屏的解决方案: adb shell命令screenrecord MediaRecorder, MediaProjection MediaProjection , MediaCod ...

  3. Android录屏并利用FFmpeg转换成gif(二)交叉编译FFmpeg源码

    Android录屏并利用FFmpeg转换成gif(二) 写博客时经常会希望用一段动画来演示app的行为,目前大多数的做法是在电脑上开模拟器,然后用gif录制软件录制模拟器屏幕,对于非开发人员来讲这种方 ...

  4. PS 一键生成Android各个尺寸的图标

    之前的项目都是用一套尺寸的图标做适配,优点就是减少APP的大小,还不用做多套适配图标,缺点就是每次加载图标都要做缩放,影响APP的性能. 公司最近终于招到UI了,发现他的PS工具可以一键生成Andro ...

  5. Android录屏并利用FFmpeg转换成gif(一)录屏

    Android录屏并利用FFmpeg转换成gif(一) 录屏 写博客时经常会希望用一段动画来演示app的行为,目前大多数的做法是在电脑上开模拟器,然后用gif录制软件录制模拟器屏幕,对于非开发人员来讲 ...

  6. Android录屏并利用FFmpeg转换成gif(三) 在Android中使用ffmpeg命令

    Android录屏并利用FFmpeg转换成gif(三) 写博客时经常会希望用一段动画来演示app的行为,目前大多数的做法是在电脑上开模拟器,然后用gif录制软件录制模拟器屏幕,对于非开发人员来讲这种方 ...

  7. Android录屏并利用FFmpeg转换成gif(四) 将mp4文件转换成gif文件

    Android录屏并利用FFmpeg转换成gif(四) 写博客时经常会希望用一段动画来演示app的行为,目前大多数的做法是在电脑上开模拟器,然后用gif录制软件录制模拟器屏幕,对于非开发人员来讲这种方 ...

  8. Android录屏分析(Android12源码)

    Android录屏分析 目录 Android录屏分析 prepare方法(准备录制) MediaProjection.MediaRecorder.VirtualDisplay的介绍 开始与结束 缩略图 ...

  9. android 录屏 github,GitHub - mabeijianxi/ScreenRecordPushStream: Android 录屏推流demo

    ScreenRecordPushStream 这是一个基于 rtmp 协议的 Android 录屏推流demo (Demo APK 下载) 使用方法 一. 服务器搭建 mkdir nms cd nms ...

  10. Android 录屏服务使用(源码)

    Android 录屏服务使用(源码) 从Android 5.0开始,可以对手机进行录屏,使用场景:如错误场景的视频上传,简单屏幕获取等,下面贴出使用用例和对使用的类一个简单的介绍 - MediaPro ...

最新文章

  1. C#程序实现动态调用DLL的研究(转)
  2. mysql中如何将一个表中的部分记录合并,MySQL数据库将多条记录的单个字段合并成一条记录_MySQL...
  3. Java设计模式:设计模式基础知识和原则
  4. JavaScript this指向相关内容
  5. php js 防止重复提交表单,php如何防止form重复提交
  6. 豆瓣评分9.4!这一部纪录片,探秘中国人迹罕至的未至之境!
  7. 关于apache和tomcat集群,线程是否占用实验
  8. php字符串函数的运用,php中字符串比较函数使用方法
  9. LTI系统对WSS Processes的作用
  10. 离线bootstrap_css下载
  11. 帆软mysql迁移_平台数据迁移- FineReport帮助文档|报表开发|报表使用|学习教程
  12. odac oracle效率差,垃圾,奇慢 ORACLE ODAC
  13. kubernets nodeport 无法访问
  14. linux 浮点测试,浮点运算性能测试
  15. kaggle员工离职预测案例(3)
  16. python爬虫岗位招聘_Python爬虫系列2-抓取拉钩网2020年最新互联网岗位招聘信息
  17. Android实现涂鸦功能
  18. c语言猴子吃桃问题(简洁做法)
  19. shell脚本检查域名证书是否过期
  20. 西安到底需不需要互联网?

热门文章

  1. 虚幻引擎3的代码讲解
  2. vue改页面顶部浏览器标题栏图标、名称和地址栏详细教程
  3. ISO14229-1道路车辆-统一诊断服务(UDS)-1
  4. 欧姆龙CP1H的PLC步进功能图编程实例
  5. 双向三相交错并联DC-DC变换器
  6. Should I design my classes from the outside (interfaces first) or from the inside (data first)?
  7. [C#/DevExpress]VS2010使用CefSharp调用Chrome内核打开网页
  8. 基于Chrome内核(WebKit内核)定制开发DoNet浏览器
  9. 云表中表单配置内嵌浏览器
  10. ASCII码十六进制转换表