28

最近,我写了一个PC客户端,可以使用adb实时显示和控制我的android手机屏幕。我用猴子来控制设备,它工作正常。问题是如何抓取手机屏幕并流畅显示。

我想出的第一个解决方案是不断地抓取framebuffer通过adb(如 DDMS 的屏幕捕获功能)。现在当我这样做时,性能是相当不可接受的。从中捕获的帧速率低至framebuffer每秒 5 帧(帧大小为 800 * 480)。当我在手机上滑动时,我的程序看起来像是在打嗝。

我的程序是用 java 编写的,使用ddmslibto grab framebuffer

补充:我发现将原始数据
编码为格式很慢,否则这将是传输压缩原始图像的快速方法。framebuffer.png

如何将截屏速度提高到流畅的水平?

4

12 回答 12

27
adb shell screencap -p | perl -pe 's/\x0D\x0A/\x0A/g' > screen.png

资源:

http://blog.shvetsov.com/2013/02/grab-android-screenshot-to-computer-via.html

于 2013-08-29T18:54:40.500 回答
12

你可以使用:

$ adb exec-out screencap -p > test.png

更新

Android 11 引入了通过 wifi 进行调试并加快了速度

$ time adb exec-out screencap -p > test.png

real    0m0.661s
user    0m0.050s
sys 0m0.066s

2021 年 9 月更新

使用CulebraTester2的屏幕截图,您可以获得更高的帧速率

./take-screenshot 

 Image in file:///tmp/culebra.zSSYZ6VG.png

于 2012-12-21T05:43:19.283 回答
9

如果缓慢的部分是原始到 png 的转换(time adb shell screencap -p /sdcard/x.pngtime adb shell screencap /sdcard/nonpng.raw我在游戏中使用的速度要慢得多)并且 png 不是必需的,那么你可以像这里一样https://github.com/sowcow/shot。它将原始数据转换为简单的 ppm 格式,并在获取原始数据后使用 imagemagick 将 ppm 转换为 bmp,几乎没有开销

更新:

max_plenert 的这个 shell 脚本是一个更好的例子:

adb shell screencap /sdcard/mytmp/rock.raw
adb pull /sdcard/mytmp/rock.raw
adb shell rm /sdcard/mytmp/rock.raw

// remove the header
tail -c +13 rock.raw > rock.rgba

// extract width height and pixelformat:
hexdump -e '/4 "%d"' -s 0 -n 4 rock.raw
hexdump -e '/4 "%d"' -s 4 -n 4 rock.raw
hexdump -e '/4 "%d"' -s 8 -n 4 rock.raw

convert -size 480x800 -depth 8 rock.rgba rock.png
于 2014-11-24T06:06:44.607 回答
4

使用这种方法,我的应用程序继续以全帧率运行

adb pull /dev/graphics/fb0

这将从帧缓冲区中提取原始数据。它似乎与屏幕的宽度相同,但高度被填充了。我设备上的帧缓冲区似乎是 RGBA8888 格式。要准确获得屏幕上显示的内容,您应该忽略 Alpha 通道。

请注意,这对我来说确实需要大约 0.8 秒的时间来下载(分辨率:480x854),但如果我在连续循环中下载它,它不会影响设备的帧速率。

于 2014-09-16T00:47:08.177 回答
4

在我的 Mac 上的 .bash_profile 中:

function droidShot() {
  /full_path_to_droid_sdk/platform-tools/adb shell screencap -p | perl -pe 's/\x0D\x0A/\x0A/g' > $1.png
}

用法:

droidshot whatever

并且文件显示在whatever.png中

于 2014-08-28T02:30:28.370 回答
3

这是一个缓慢的解决方案,我相信这是您在基于 adb 的解决方案中可能找到的更快的方法,

# this line require a superuser privilege:
adb shell "su -c 'cat /dev/graphics/fb0 > /sdcard/capture.raw'"

adb pull /sdcard/capture.raw

ffmpeg -loglevel panic -f rawvideo -pix_fmt bgr32 -s 320x480 -i \ 
    capture.raw -vcodec png -vframes 1 capture.png; 

这是我的网络应用程序中的相同代码

于 2016-05-07T01:15:32.207 回答
1

来自文档

截取设备屏幕截图

screencap 命令是一个 shell 实用程序,用于截取设备显示的屏幕截图。在 shell 中,语法是:

screencap <filename>

要从命令行使用屏幕截图,请键入以下内容:

$ adb shell screencap /sdcard/screen.png

这是一个示例屏幕截图会话,使用 adb shell 捕获屏幕截图并使用 pull 命令从设备下载文件:

$ adb shell
shell@ $ screencap /sdcard/screen.png
shell@ $ exit
$ adb pull /sdcard/screen.png

录制设备屏幕

screenrecord 命令是一个 shell 实用程序,用于记录运行 Android 4.4(API 级别 19)及更高版本的设备的显示。该实用程序将屏幕活动记录到 MPEG-4 文件中。

Note: Audio is not recorded with the video file.

开发人员可以使用此文件创建宣传或培训视频。在 shell 中,语法是:

screenrecord [options] <filename>

要从命令行使用 screenrecord,请键入以下内容:

$ adb shell screenrecord /sdcard/demo.mp4

按 Ctrl-C 停止屏幕录制,否则录制会在三分钟或--time-limit设置的时间限制时自动停止。

要开始录制您的设备屏幕,请运行 screenrecord 命令来录制视频。然后,运行 pull 命令将视频从设备下载到主机。这是一个示例录制会话:

$ adb shell
shell@ $ screenrecord --verbose /sdcard/demo.mp4
(press Ctrl-C to stop)
shell@ $ exit
$ adb pull /sdcard/demo.mp4

screenrecord 实用程序可以以您请求的任何支持的分辨率和比特率进行录制,同时保留设备显示的纵横比。该实用程序默认以原始显示分辨率和方向记录,最长为三分钟。

使用 screenrecord 实用程序时应注意一些已知限制:

某些设备可能无法以其原始显示分辨率进行录制。如果遇到屏幕录制问题,请尝试使用较低的屏幕分辨率。不支持在录制过程中旋转屏幕。如果在录制过程中屏幕确实旋转,则部分屏幕会在录制过程中被截断。

于 2015-09-24T18:41:38.727 回答
0

好吧,有些人说在 Perl 中有很多方法可以做一件事。:-) 无论如何,这个可能会表现得更好(因为没有正则表达式),并且可以解决 MS Windows 中 Cygwin 中的问题(其 Perl 定义\n为 CRLF):

adb shell screencap -p | perl -pe 'BEGIN { $/="\cM\cJ"; $\="\cJ"; } chomp;' > screen-$(date +%Y%m%d_%H%M%S).png
于 2014-08-24T01:31:21.640 回答
0

我改进了@steveha 的解决方案:

创建一个 shell 脚本,说:' android-screenshot ',内容如下:

adb shell screencap -p | perl -pe 's/\x0D\x0A/\x0A/g' > screen-`date +%Y-%m-%d_%X`.png

将此文件放在本地 bin 目录或您喜欢的任何其他$PATH中。

这将允许您在当前目录中保存带有时间戳的文件。

请记住使用以下命令使 shell 脚本可执行

chmod +x android-screenshot
于 2014-02-11T13:33:42.960 回答
0

Android 4.4有一个screenrecord程序

adb shell screenrecord /data/local/tmp/test-video.m4v
adb pull /data/local/tmp/test-video.m4v ~/test-video.m4v
于 2015-03-02T16:58:45.090 回答
-1

adb shell screenrecord --bit-rate 8000000 --time-limit 30 /sdcard/example.mp4

您还可以更改比特率并更改视频持续时间。

于 2015-04-14T12:47:42.357 回答
-1
adb shell screencap /sdcard/screen.png && adb pull /sdcard/screen.png my_screen01.png
于 2017-01-30T20:14:15.817 回答