用adb录屏这个事,说简单是真简单,一条命令就能开始;说麻烦也是真麻烦,码率、时长、方向、声音,每个环节都有人踩坑。我过去两年在不同项目里反复用adb shell screenrecord,从最开始只会录默认三分钟,到后来把多设备并行录制、码率控制、异常排查全部捋顺,中间确实积了不少经验。这篇就把我的完整用法和踩坑记录整理出来,给做自动化测试、需要录演示视频、或者经常远程帮人看设备问题的朋友参考。
1. adb录屏到底能做什么:先别急着敲命令
很多刚接触adb录屏的人,第一反应是“不就是录个屏嘛,手机自带录屏不就行了”。但从自动化测试和调试的角度看,adb录屏最大的价值不在于“录”,而在于“可控”:不装App、不污染环境、能用脚本驱动、能配合adb模拟点击和 shell 命令做完整还原。这几个点在不同工作场景里全都用得上。
1.1 自动化测试里最顺手的一环
我在实际项目中遇到最多的需求是回归测试留痕。App改了一版,要验证关键流程是否正常,测试同学手动跑一遍当然可以,但问题在于“当时到底发生了什么”很难追。如果让测试脚本在你跑用例的同时启动一次adb录屏,结束后直接拉取视频存档,那每个用例对应的操作路径、界面前后变化、崩溃弹窗,全部都有了客观证据。这种做法比截图更完整,也比事后补录更可信。
配合 adb 的 input 命令,这套东西还能自己演完整个过程。比如用adb shell input tap x y点击按钮,用adb shell input swipe x1 y1 x2 y2 duration滑动页面,甚至用adb shell am start -n 包名/Activity名直接拉起指定界面。一边模拟操作一边录屏,整个自动化过程就有了可回放的影像记录。出 Bug 的时候,把视频和 logcat 日志一起发给开发,问题定位效率明显高很多。
1.2 演示、对比与远程排查场景
除了测试,adb录屏还有一个很实用的场景:演示操作路径。有段时间我经常要帮朋友看手机里的问题,对方说不清楚操作步骤,我也没法当面看。我的做法是让他在电脑上跑一条 adb 命令开始录屏,然后正常操作手机,操作完再结束录制,把视频发过来。相比文字描述“我点了设置再点关于手机”,视频信息量完全不一样。
另一个我常用的是多设备对比。手里有两三台不同配置的设备,想对比同一个页面的滑动流畅度、启动速度或者布局差异,临时找不到录屏软件,adb录屏就非常合适。只要用adb -s 设备序列号 shell screenrecord分别启动录制,控制好开始时间和操作节奏,最后拉出来的几段视频放在一起,问题一目了然。后面我还会写一个多设备同时录制的脚本,也是在这个基础上扩展出来的。
2. screenrecord基础用法:命令和参数一次讲透
adb录屏最核心的命令就是adb shell screenrecord,Android系统自带这个工具,我们不需要在手机上安装任何录屏App。但很多网上的简短教程只写了命令本身,没有讲参数含义和边界条件,导致多少人录到一半发现停了,或者画面模糊、方向不对。下面我把参数和几个常见误区一次讲清楚。
2.1 一条命令录起来
最基础的录屏命令是这样:
adb shell screenrecord /sdcard/demo.mp4执行之后设备就开始录屏,默认情况下录满180秒自动停止,文件保存在设备内的/sdcard/demo.mp4。这个路径必须写到设备里的稳定存储目录,我习惯写/sdcard/下面,因为后面用 adb pull 拉取时权限路径最省心。如果你直接只写文件名不写路径,有些设备的 shell 当前目录在/根目录,未必有写入权限,很容易报错。
这个命令适合快速验证“能不能录”。实际使用中,我基本都会带上参数,因为默认参数有几个坑:默认码率只有 4Mbps,录动态内容会糊;默认时长只有 180 秒,录不了长视频;某些设备录出来的文件方向信息有问题,在电脑播放时是横着的。所以我想认真用这个工具,上面这几个参数都得掌握。
2.2 关键参数逐个拆解
screenrecord 支持几个我很常用的参数,先用一张表说明:
| 参数 | 默认值 | 作用 | 我的建议 |
|---|---|---|---|
--size WxH | 设备原始分辨率 | 设置录制视频分辨率 | 需要压缩文件体积时使用,否则保持默认 |
--bit-rate RATE | 4Mbps | 设置视频码率,单位是bps | 动态画面建议提到8Mbps~16Mbps |
--time-limit TIME | 180秒 | 设置录制最大时长 | 不要超过180秒,这是原生上限 |
--rotate | 关闭 | 旋转视频方向元数据 | 竖屏录完变横屏时加上再试 |
--bugreport | 关闭 | 录制时额外写入系统诊断信息 | 一般用不到,开了文件会变大 |
--verbose | 关闭 | 在设备shell里输出录制过程日志 | 排查问题时很有用 |
先说--bit-rate,这是最容易让人迷惑的参数,因为它的单位是bps(比特每秒),不是大家习惯的KB、MB。如果要设置12Mbps,需要写成--bit-rate 12000000,不是写12。我之前见过有人写--bit-rate 12,结果录出来的视频画质极其糟糕,就是因为码率被设置成了每秒12比特。默认4Mbps对纯静态界面勉强够用,但只要页面有滚动、动画、游戏画面,马赛克感立刻出现,所以我一般从8M起步。
然后是--size。设备屏幕分辨率越高,编码压力越大,文件也越大。如果只是做功能演示,不追求极致清晰度,可以显式把分辨率压到1280x720,文件体积小很多,传输也快。但要记住一个边界:不要设置超过设备原生屏幕分辨率的尺寸,否则编码器可能报错,或者录出来的视频比实际屏幕小一圈。我遇到过一次某设备设置过大分辨率后直接退出,改回默认就正常了。
--time-limit是另一个容易“翻车”的点。原生 screenrecord 的时长上限就是180秒,也就是三分钟,这不是随便设置的,是工具本身的编码器循环设计决定的。如果录制需求超过三分钟,直接调大参数没有意义,超过之后设备端会强制结束。需要长视频的话,要么写成脚本分段录制再拼接,要么换用其他方案。这一点放在后面进阶章节详细说。
2.3 结束录屏的正确姿势,以及文件拉取
结束录屏看起来简单,但结束方式如果不对,很容易得到损坏文件。我推荐两种稳定的结束方式。
第一种是让它自己到时间结束。设了--time-limit就等它自然停止,视频文件会正常收尾。第二种是提前手动停止,但这里有个细节:如果你直接在当前电脑终端执行adb shell screenrecord ...,然后按Ctrl+C,你终止的其实只是电脑端 adb 这个连接,设备端的录屏进程未必能收到对应的终止信号,结果可能导致文件无法正常关闭。
更稳的做法是分两步。先用adb shell进入设备里的shell环境,再输入screenrecord /sdcard/demo.mp4,录完以后在shell提示符下按Ctrl+C,这个信号能正确发给 screenrecord 进程,文件基本都能正常生成。如果你已经在用非交互式的单条命令,也可以再开一个终端用adb shell killall screenrecord强制结束进程,结束之后同样要注意检查文件是否能播放。
文件录好之后,拉回电脑的命令是:
adb pull /sdcard/demo.mp4 ./demo.mp4拉取完成后,我建议立刻把设备里的临时文件删掉,避免反复录制把设备存储填满:
adb shell rm /sdcard/demo.mp4还有一个小习惯:文件命名最好带上日期或者场景名,不然录了几个版本之后设备里全是demo.mp4,根本分不清谁是谁。我一般会在脚本里用当前时间戳拼接文件名。
3. 进阶玩法:多设备、码率策略与声音方案
基础命令会用之后,很多人马上会遇到三个更高频的诉求:同时录多台设备、怎么让画面更清晰又不至于文件太大、录屏没有声音怎么办。这三个问题我都实际处理过,分别说下我的做法和思考。
3.1 多台设备同时录屏的脚本思路
多设备录屏的核心是给每条adb命令指定设备序列号。先执行adb devices拿到所有在线设备的序列号,然后对每台设备执行:
adb -s 设备序列号 shell screenrecord --time-limit 30 /sdcard/sn.mp4 &关键点是命令结尾的&,让它在后台并行跑,这样几台设备能同时开始录。在实际操作中,我还发现一个前置问题:录屏过程中如果设备息屏了,录出来的多半是黑屏或者锁屏界面。这是因为 screenrecord 只负责采集画面,不会阻止系统休眠。所以多设备开录之前,我会先给每台设备设置屏幕常亮:
adb shell svc power stayon true录制结束之后再把常亮关掉:
adb shell svc power stayon false如果连接的是模拟器,思路也一样,只是设备序列号可能是一串emulator-5554这样的名字。模拟器上的 screenrecord 同样能工作,只是模拟器本身如果跑得卡,录出来也会掉帧,这属于模拟器性能问题,不怪录屏工具。
3.2 卡顿和模糊:码率与分辨率的平衡点
很多人在录完视频后吐槽“画面好糊”“一滚动就花”,根因绝大多数是码率不够。默认4Mbps做静态界面没问题,但录页面滚动、转场动画、游戏画面时,编码器来不及用有限的码率表达所有细节,画面就会发糊、产生马赛克。
我自己的经验值是这样:1080p分辨率下,普通操作演示用8Mbps够用;录游戏或者高频滚动的长列表,我会直接提到12Mbps甚至16Mbps。720p分辨率可以适当降到6Mbps。码率不是越高越好,因为码率上去了,文件体积线性增长,传输和存储都有成本。
有一个简单的文件体积估算方法:码率除以8,得到每秒字节数,再乘以时长秒数。比如12Mbps,即每秒1.5MB,录60秒就是90MB左右。按这个公式可以在开录之前估算要占多少空间。录屏过程中如果发现设备录制掉帧严重,优先检查存储剩余空间,其次再考虑降低分辨率。硬件编码器一般不太吃CPU,但存储写入太慢或者码率超出了设备编码能力,还是会掉帧。
3.3 声音录不了?三条替代路线
这是 screenrecord 最大的一个限制:它只录画面,不录声音。很多人第一次录完发现视频是静音的,会以为是操作不对,其实这是原生工具的既定设计。要做带声音的录屏,我的建议是按场景从三条路线里选。
第一条路线:用支持音频录制的镜像工具,比如 scrcpy 新版本已经支持把设备音频同步录进视频,命令很直观,一条scrcpy --record=file.mp4就能连录带拉流处理,适合需要声音同时又要看画面的场景。
第二条路线:直接用设备自带的系统录屏功能。目前很多手机系统的录屏都能选择“录制系统声音”或“录制麦克风”,这个方案最简单,适合单个设备手动演示,但缺点是不容易脚本化,自动化测试里不好集成。
第三条路线:在电脑端处理。先把手机画面无线投屏到电脑桌面,然后用电脑的录屏软件把桌面区域连同声音一起录下来。自媒体做App演示视频常用这个方式,好处是可以把讲解声和手机操作录在同一个时间轴上。代价是画质经过投屏会损失一层,动态画面可能没有直接录屏那么细腻。
4. 常见问题与排查技巧实录
下面这些故障,我基本都在不同设备上真实遇到过。整理成速查表方便对照,详细原因我逐条展开。
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| 录出来的文件是0字节 | 录制时间太短或结束信号没正确送达 | 至少录2~3秒后再结束,用交互shell按Ctrl+C |
| 录三分钟自动停了 | 原生screenrecord时长上限180秒 | 分段录制再拼接,或改用其他工具 |
| 画面模糊、马赛克严重 | 默认码率4Mbps偏低 | 调高--bit-rate到8M~16M |
| 竖屏录完电脑播放是横屏 | 视频缺少旋转元数据 | 加--rotate参数 |
| 某个App录制出来黑屏 | App开启了屏幕安全保护 | 换测试包或非保护环境录制 |
| 设备和电脑连不上,命令没反应 | adb授权失效或驱动问题 | 重新授权、重启adb服务、换数据线或改用无线调试 |
| 拉取文件特别慢 | USB 2.0口或设备存储繁忙 | 换USB 3.0口、清理设备存储、用无线adb |
4.1 录出来的文件是0字节,或者根本打不开
0字节文件多数情况是录屏进程启动之后马上被结束,还没来得及写入有效的视频数据。如果你执行录屏命令后不到一秒就按了Ctrl+C,出现0字节文件就别奇怪了。正确做法是至少等个两三秒再结束,让编码器先写够头部数据。
还有一种情况是文件有一定体积,但播放器打不开。我遇到过一次是在非交互式命令下直接Ctrl+C,结果文件没有正确收尾。用adb shell killall screenrecord或者进入交互式shell再终止,一般就能正常。如果手头已经有一个损坏的mp4,可以试试用ffmpeg修复,命令是这样:
ffmpeg -i broken.mp4 -c copy repaired.mp4修复的成功率取决于文件损坏程度,但值得一试。需要注意的是,如果你录屏过程中设备本身卡死或者被强制重启,文件基本救不回来,这种情况只能重录。
4.2 设备连不上、文件拉不出来怎么办
adb命令都执行不了的时候,先别怀疑screenrecord,问题多半出在adb连接层。最常见的是电脑上弹了“允许USB调试吗”的授权框,手机上没点确认,那电脑端会显示设备为unauthorized状态。这时候到手机上看通知栏授权弹窗点允许就行。如果没弹窗,可以试试拔掉USB线重新插,或者重启adb服务:
adb kill-server adb start-server换数据线也是排查重点。有些线只有充电功能,没有数据通道,这个问题很容易让人误判成设备坏了。另外,Android 11之后的设备可以用无线调试,物理连接不方便时很好用。在开发者选项里打开“无线调试”,然后用电脑执行配对联接,基本流程是先用adb pair 地址:端口 配对码完成配对,再用adb connect 地址:端口建立连接,之后录屏拉取都走网络,非常方便。
4.3 方向、画面和格式的怪问题
竖屏手机录出来在电脑上横屏播放,这个坑我踩过一次。screenrecord 在部分设备上录出的视频缺少旋转元数据,播放器不知道该转90度。加--rotate参数通常能解决,但我也见过某厂商的设备加了参数反而方向不对,这种就属于厂商适配差异,只能是“哪台设备用哪个参数组合以实测为准”。
有些App录制出来是全黑,这个要注意,这不是adb录屏坏了,而是应用主动开启了屏幕内容保护。类似银行客户端、视频播放App、某些企业办公App,为了保证安全会禁止截屏录屏,系统底层收到采集请求时直接输出黑画面。遇到这种情况,正规的处理思路是找应用方要一个允许录屏的测试包,或者用网页版、开发版环境来录,不建议也不应该去尝试绕过保护。
还有一类奇怪情况是录制分辨率比屏幕实际分辨率小一圈。这个在部分设备上很常见,属于厂商做屏幕缩放后,screenrecord 读到的默认采集尺寸和真实分辨率不一致。一般不用管,如果你对清晰度不满意,可以显式用--size指定接近屏幕原生分辨率的值,再实测对比效果。
5. adb录屏与常用方案的横向对比
很多时候不是某个工具不行,而是没选对工具。adb录屏有它最适合的地方,但也有它明显不擅长的场景。我把三种我常用的录屏方案放在一起做了个对比,方便按需选择。
5.1 三种常见方案参数对比
| 维度 | adb screenrecord | 设备内置录屏 | scrcpy录屏 |
|---|---|---|---|
| 是否需要安装App | 不需要 | 系统自带 | 电脑端工具,设备端无需安装 |
| 是否支持脚本化/自动化 | 支持,可配合adb命令 | 基本不支持 | 支持命令行调用 |
| 是否有声音 | 不支持 | 支持系统声/麦克风 | 新版本支持设备音频 |
| 录制时长上限 | 原生180秒 | 通常无严格限制 | 取决于电脑存储和工具设置 |
| 画质控制 | 码率、分辨率可调 | 通常只有档位可选 | 码率设置相对灵活 |
| 多设备并行 | 很合适 | 不合适 | 可以,但占用电脑资源多 |
| 操作门槛 | 低 | 最低 | 中等 |
从表格可以明显看到,adb录屏最大的优势集中在“自动化”“多设备”“画质控制”这三项。设备内置录屏则在“有声音”“无门槛”上占优。scrcpy是介于两者之间的平衡选项,既能命令行调用,也支持音频,适合个人日常使用。
5.2 我的选型建议
我一般按使用场景来决定用哪个,给大家一个参考:
自动化测试和需要批量留痕的场景,我会优先用adb screenrecord。无入侵、可脚本化,多设备并发也稳。缺点是没有声音,但大多数功能测试场景对声音不敏感,影响不大。
单个设备做演示,而且必须要内部声音,直接用设备内置录屏最省事。不用敲命令,点两下就录,画质也不差。缺点是想自动化重复操作时不方便。
需要在电脑端一边观察手机画面一边录制,同时还要声音,scrcpy很合适。它还能把手机画面显示在电脑窗口里,远程演示或者录教学视频都方便。这里要提醒一句,scrcpy录制较多依赖电脑和设备的连接质量,无线连接不稳定时容易掉帧,有条件优先用数据线。
6. 附一份可以直接改用的多设备录制脚本
最后分享一个我自己日常在用的多设备录制脚本。它做的事情很简单:读取所有在线设备、同时启动录屏、等待录制结束、把每台设备的视频拉回本地。脚本里加了一些防御性处理,适合直接修改使用。
6.1 脚本结构和关键代码
#!/bin/bash # 多设备adb录屏脚本:用法 ./multi_record.sh 15 输出目录 DURATION=${1:-15} OUT_DIR="${2:-$HOME/adb_screenrecords}" mkdir -p "$OUT_DIR" mapfile -t SERIALS < <(adb devices | awk 'NR>1 && $2=="device" {print $1}') if [ ${#SERIALS[@]} -eq 0 ]; then echo "没有可用设备,请先连接手机并开启USB调试" exit 1 fi TS=$(date +%Y%m%d_%H%M%S) REMOTE_FILES=() for sn in "${SERIALS[@]}"; do remote="/sdcard/${sn}_${TS}.mp4" REMOTE_FILES+=("$sn|$remote") echo "开始录制: $sn -> $remote" adb -s "$sn" shell screenrecord --time-limit "$DURATION" "$remote" & done echo "等待录制 $DURATION 秒..." sleep "$((DURATION + 2))" for entry in "${REMOTE_FILES[@]}"; do sn="${entry%%|*}" remote="${entry##*|}" echo "拉取 $remote" adb -s "$sn" pull "$remote" "$OUT_DIR/" adb -s "$sn" shell rm -f "$remote" done echo "录制完成,文件在 $OUT_DIR"这个脚本里有几个细节值得说明。用mapfile读取设备序列号,比直接用adb devices手工复制要稳得多;启动每条screenrecord命令时用&让它们并行;等待时间在DURATION基础上加2秒,是为了给设备端编码器多一点时间完成收尾,避免拉取时文件还没写好。拉完之后顺手删掉设备端文件,防止存储被反复录制占满。
6.2 按需改造成自己常用的版本
这个脚本可以按你的实际需求做很多小改造。比如录制的分辨率想统一压到720p,可以在screenrecord命令里加上--size 1280x720;想让不同设备按场景区分文件,可以把文件名里的$sn改成你自己定义的前缀;如果录制过程中还需要模拟点击操作,可以在等待阶段插入adb -s "$sn" shell input tap ...,这样最终视频里就会完整记录你的模拟操作效果。
我自己的日常操作还会做两件事:一是在录制前先执行svc power stayon true防止设备息屏,录制完再恢复,避免录到黑屏;二是如果录出来的文件需要给其他人看,我会先把所有视频按设备序列号归类到不同目录,再统一打包。脚本化之后,整个流程从原来的十几分钟手工操作,压缩到一条命令执行完。
用adb录屏这个事,归根到底就是把系统自带的 screenrecord 用到极致。参数不多,但真正用起来之后你会发现,所有问题都出在对设备差异和录制边界的理解上。我先记得最深刻的一点就是:遇到录出来的效果和预期不符,先看码率,再看时长,最后检查是不是App防止了录屏,大部分问题都逃不出这三个方向。